diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index 681aa8034..54ed717ae 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -444,9 +444,338 @@ module.exports = { "sidebarDepth": 2 }, { - // TODO: Placeholder and temporary link for this section until it can be migrated from legacy docs. - title: 'Central Ledger Services', - path: 'https://docs.mojaloop.io/legacy/mojaloop-technical-overview/central-ledger/' + "title": "Central Ledger", + "collapsable": true, + "children": [ + { + "title": "Overview", + "path": "central-ledger/" + }, + { + "title": "Admin Operations", + "collapsable": true, + "children": [ + { + "title": "Overview", + "path": "central-ledger/admin-operations/", + }, + { + "title": "POST Participant Limit", + "path": "central-ledger/admin-operations/1.0.0-post-participant-position-limit" + }, + { + "title": "GET Participant Limit Details", + "path": "central-ledger/admin-operations/1.1.0-get-participant-limit-details" + }, + { + "title": "GET All Participant Limits", + "path": "central-ledger/admin-operations/1.0.0-get-limits-for-all-participants" + }, + { + "title": "POST Participant limits", + "path": "central-ledger/admin-operations/1.1.0-post-participant-limits" + }, + { + "title": "GET Transfer Status", + "path": "central-ledger/admin-operations/1.1.5-get-transfer-status" + }, + { + "title": "POST Participant Callback", + "path": "central-ledger/admin-operations/3.1.0-post-participant-callback-details" + }, + { + "title": "GET Participant Callback", + "path": "central-ledger/admin-operations/3.1.0-get-participant-callback-details" + }, + { + "title": "GET Participant Position", + "path": "central-ledger/admin-operations/4.1.0-get-participant-position-details" + }, + { + "title": "GET All Participants Positions", + "path": "central-ledger/admin-operations/4.2.0-get-positions-of-all-participants" + } + ] + }, + { + "title": "Transfers Operations", + "collapsable": true, + "children": [ + { + "title": "Overview", + "path": "central-ledger/transfers/" + }, + { + "title": "Prepare Handler", + "collapsable": true, + "children": [ + { + "title": "Overview", + "path": "central-ledger/transfers/1.1.0-prepare-transfer-request" + }, + { + "title": "Prepare Handler Consume", + "path": "central-ledger/transfers/1.1.1.a-prepare-handler-consume" + } + ] + }, + { + "title": "Prepare Position Handler", + "path": "central-ledger/transfers/1.3.0-position-handler-consume" + }, + { + "title": "Prepare Position Handler v1.1", + "collapsable": true, + "children": [ + { + "title": "Overview", + "path": "central-ledger/transfers/1.3.0-position-handler-consume-v1.1" + }, + { + "title": "Prepare Position Handler", + "path": "central-ledger/transfers/1.3.1-prepare-position-handler-consume" + }, + { + "title": "Position Handler Consume", + "path": "central-ledger/transfers/1.1.2.a-position-handler-consume" + } + ] + }, + { + "title": "Fulfil Handler", + "path": "central-ledger/transfers/2.1.0-fulfil-transfer-request" + }, + { + "title": "Fulfil Handler v1.1", + "collapsable": true, + "children": [ + { + "title": "Overview", + "path": "central-ledger/transfers/2.1.0-fulfil-transfer-request-v1.1" + }, + { + "title": "Fulfil Handler Consume", + "path": "central-ledger/transfers/2.1.1-fulfil-handler-consume" + }, + { + "title": "Fulfil Handler Consume v1.1", + "path": "central-ledger/transfers/2.1.1-fulfil-handler-consume-v1.1" + } + ] + }, + { + "title": "Fulfil Position Handler", + "collapsable": true, + "children": [ + { + "title": "Overview", + "path": "central-ledger/transfers/1.3.0-position-handler-consume" + }, + { + "title": "Fulfil Position Handler", + "path": "central-ledger/transfers/1.3.2-fulfil-position-handler-consume" + }, + { + "title": "Fulfil Position Handler v1.1", + "path": "central-ledger/transfers/1.3.2-fulfil-position-handler-consume-v1.1" + } + ] + }, + { + "title": "Fulfil Reject Transfer", + "collapsable": true, + "children": [ + { + "title": "Overview", + "path": "central-ledger/transfers/2.2.0-fulfil-reject-transfer" + }, + { + "title": "Fulfil Reject Transfer (a)", + "path": "central-ledger/transfers/2.2.0.a-fulfil-abort-transfer" + }, + { + "title": "Fulfil Handler (Reject-Abort)", + "path": "central-ledger/transfers/2.2.1-fulfil-reject-handler" + } + ] + }, + { + "title": "Fulfil Reject Transfer v1.1", + "collapsable": true, + "children": [ + { + "title": "Overview", + "path": "central-ledger/transfers/2.2.0-fulfil-reject-transfer-v1.1" + }, + { + "title": "Fulfil Reject Transfer (a) v1.1", + "path": "central-ledger/transfers/2.2.0.a-fulfil-abort-transfer-v1.1" + }, + { + "title": "Fulfil Handler (Reject-Abort) v1.1", + "path": "central-ledger/transfers/2.2.1-fulfil-reject-handler-v1.1" + } + ] + }, + { + "title": "Notifications", + "collapsable": true, + "children": [ + { + "title": "Notification to Participant (a)", + "path": "central-ledger/transfers/1.1.4.a-send-notification-to-participant" + }, + { + "title": "Notification to Participant (a) - v1.1", + "path": "central-ledger/transfers/1.1.4.a-send-notification-to-participant-v1.1" + }, + { + "title": "Notification to Participant (b)", + "path": "central-ledger/transfers/1.1.4.b-send-notification-to-participant" + } + ] + }, + { + "title": "Reject/Abort", + "collapsable": true, + "children": [ + { + "title": "Abort Position Handler", + "path": "central-ledger/transfers/1.3.3-abort-position-handler-consume" + } + ] + }, + { + "title": "Timeout", + "collapsable": true, + "children": [ + { + "title": "Transfer Timeout", + "path": "central-ledger/transfers/2.3.0-transfer-timeout" + }, + { + "title": "Timeout Handler Consume", + "path": "central-ledger/transfers/2.3.1-timeout-handler-consume" + } + ] + }, + ] + }, + { + "title": "Bulk Transfers Operations", + "collapsable": true, + "children": [ + { + "title": "Overview", + "path": "central-bulk-transfers/" + }, + { + "title": "Bulk Prepare", + "collapsable": true, + "children": [ + { + "title": "Overview", + "path": "central-bulk-transfers/transfers/1.1.0-bulk-prepare-transfer-request-overview" + }, + { + "title": "Bulk Prepare Handler", + "path": "central-bulk-transfers/transfers/1.1.1-bulk-prepare-handler-consume" + } + ] + }, + { + "title": "Prepare Handler", + "collapsable": true, + "path": "central-bulk-transfers/transfers/1.2.1-prepare-handler-consume-for-bulk" + }, + { + "title": "Position Handler", + "collapsable": true, + "children": [ + { + "title": "Overview", + "path": "central-bulk-transfers/transfers/1.3.0-position-handler-consume-overview" + }, + { + "title": "Prepare Position Handler Consume", + "path": "central-bulk-transfers/transfers/1.3.1-prepare-position-handler-consume" + }, + { + "title": "Fulfil Position Handler Consume", + "path": "central-bulk-transfers/transfers/2.3.1-fulfil-position-handler-consume" + }, + { + "title": "Fulfil Abort Position Handler Consume", + "path": "central-bulk-transfers/transfers/2.3.2-position-consume-abort" + } + ] + }, + { + "title": "Bulk Fulfil Handler", + "collapsable": true, + "children": [ + { + "title": "Overview", + "path": "central-bulk-transfers/transfers/2.1.0-bulk-fulfil-transfer-request-overview" + }, + { + "title": "Bulk Fulfil Handler Consume", + "path": "central-bulk-transfers/transfers/2.1.1-bulk-fulfil-handler-consume" + }, + { + "title": "Fulfil Handler - Commit", + "path": "central-bulk-transfers/transfers/2.2.1-fulfil-commit-for-bulk" + }, + { + "title": "Fulfil Handler - Reject/Abort", + "path": "central-bulk-transfers/transfers/2.2.2-fulfil-abort-for-bulk" + } + ] + }, + { + "title": "Bulk Processing Handler", + "path": "central-bulk-transfers/transfers/1.4.1-bulk-processing-handler" + }, + { + "title": "Notifications", + "collapsable": true, + "children": [ + { + "title": "Notification to Participant (a)", + "path": "central-ledger/transfers/1.1.4.a-send-notification-to-participant" + }, + { + "title": "Notification to Participant (b)", + "path": "central-ledger/transfers/1.1.4.b-send-notification-to-participant" + } + ] + }, + { + "title": "Timeout", + "collapsable": true, + "children": [ + { + "title": "Overview", + "path": "central-bulk-transfers/transfers/3.1.0-transfer-timeout-overview-for-bulk" + }, + { + "title": "Timeout Handler Consume", + "path": "central-bulk-transfers/transfers/3.1.1-transfer-timeout-handler-consume" + } + ] + }, + { + "title": "Bulk Abort Overview", + "path": "central-bulk-transfers/transfers/4.1.0-transfer-abort-overview-for-bulk" + }, + { + "title": "Get Bulk Transfer Overview", + "path": "central-bulk-transfers/transfers/5.1.0-transfer-get-overview-for-bulk" + } + ] + } + ], + "sidebarDepth": 2 }, { // TODO: Placeholder and temporary link for this section until it can be migrated from legacy docs. diff --git a/docs/technical/central-bulk-transfers/README.md b/docs/technical/central-bulk-transfers/README.md new file mode 100644 index 000000000..c1d0b3d54 --- /dev/null +++ b/docs/technical/central-bulk-transfers/README.md @@ -0,0 +1,298 @@ +# Bulk Transfers Design + +The Bulk Transfers scenario is described in the API Definition document regarding the resource /bulkTransfers. For details _(refer to section `6.10`)_ as per the [Mojaloop Specification](https://github.com/mojaloop/mojaloop-specification/blob/master/API%20Definition%20v1.0.pdf) + +1. [Introduction](introduction) +2. [Design Considerations](design-considerations) +3. [Steps involved in the high-level Architecture](steps-involved-in-the-high-level-architecture) +4. [Notes](notes) + 1. [Discussion items](discussion-items) + 2. [Proposed new tables](proposed-new-tables) + 3. [Bulk Transfers States](bulk-transfers-states) + 4. [Additional Notes](additional-notes) +5. [Roadmap Topics](roadmap-topics) + +## 1. Introduction + +The Bulk Transfers process is discussed in section 6.10 of the API Definition 1.0 document, depicted in Figure 60, of which a snapshot is posted below. +![Figure 60](./assets/diagrams/architecture/Figure60-Example-Bulk-Transfer-Process-Spec1.0.png) + +The key items implied in the specification in its current version 1.0 are that + +- Reservation of funds is done for each individual transfer from the Payer FSP to the Payee FSP +- Even if a single individual transfer fails during the prepare process, the whole bulk is to be rejected. + +## 2. Design Considerations + +According to the Figure-60 of the specification, below are a few key implications from the Specification. + +1. The Payer DFSP performs user look-ups for the individual parties involved in the bulk payment separately +2. The Payer DFSP performs bulk quoting per Payee DFSP +3. The onus is on the Payer DFSP to prepare bulk transfers based on Payee FSPs and send out a bulk transfer request to a single Payee FSP +4. This seems to be an all-or-nothing process where even if a single individual transfer fails to be reserved, then the whole bulk needs to be rejected because it cannot be sent to the Payee as it is if it has an individual transfer for which funds couldn't be reserved. +5. In light of the above, the proposal being made right now is to empower the Switch (needs updating the Specification) to send out the POST /bulkTransfers request with the list of individual transfers for which funds were able to be reserved on the Switch. +6. The implication is that the Switch aggregates commits/failures from the Payee FSP for the bulk and sends out a single PUT /bulkTransfers/{ID} call to the Payer FSP that includes the entire list of transfers that includes individual transfers that failed both at the Switch and the Payee FSP +7. For example: If there are 1000 individual transfers in a Bulk Transfer and if the Switch is able to reserve funds for 900 of the individual transfers, then a prepare bulk transfer request to the Payee DFSP is sent with the list of those 900 individual transfers. Once the Payee FSP sends the Bulk Fulfil request for those 900 transfers of which lets say, 800 can be committed and 100 are aborted, then the Switch processes those individual transfers accordingly and sends out the PUT callback (PUT /bulkTransfers/{ID}) notification to the Payer FSP with all the 1000 individual transfers, 800 of which are committed and 200 of which are aborted. +8. There will be implications to aspects such as Signature, Encryption, PKI and other security aspects that will need to be addressed. +9. The ordering of the individual transfers need to be considered as well by the Scheme. A Goal for implementation in emerging markets is to maximize the number of transactions involved and so a well designed Scheme may re-order individual transfers in the ascending order of the magnitude of amounts and then process them. But this can be a Scheme consideration. +10. However, a recommended Scheme Rule is that the Payee FSPs shouldn't be allowed to re-order the individual transfers in a bulk to avoid bias towards Payee parties. +11. For Settlements with bulk transfers where Government payments are involved with large sums of money needs to be discussed to allow for moving through transfers without strict liquidity rules needs to be discussed. + +## 3. Steps involved in the high-level Architecture + +Below are the steps involved at a high level for bulk transfers. + +![architecture diagram](./assets/diagrams/architecture/bulk-transfer-arch-flows.svg) + +1. [1.0, 1.1, 1.2] An Incoming bulk Transfer request (POST /bulkTransfers) on the bulk-api-adapter is placed in an object store and a notification with a reference to the actual message is sent via a kafka topic “bulk-prepare” and a 202 is sent to the Payer FSP +2. [1.3] Bulk Prepare handler consumes the request, records the status as RECEIVED + + a. Bulk Prepare handler then validates the Bulk and changes state to PENDING if the validation is successful + + b. One validation rule proposed in addition, here is to reject a bulk if there are duplicate transfer IDs used in the bulk itself. + + c. [1.4] If validation fails, Bulk Prepare handler changes the bulkTransferState to PENDING_INVALID (an internal state) and produces a message onto the bulk processing topic + i. Bulk processing Handler then updates the bulkTransferState to REJECTED and sends a notification to the Payer + +3. [1.4] [Continuing 2.a] Bulk Prepare handler breaks down the bulk into individual transfers and puts each of them on the prepare topic + + a. As part of this, each transfer is individually assigned the 'expiration time' of the bulk Transfer itself (and other fields necessary for individual transfers) + +4. [1.5, 1.6, 1.7] Prepare handler, Position handler are refactored to handle individual transfers in a bulk, using flags such as type, action, status, etc. + + a. Reservation of funds --> This is left to the individual handlers and the whole bulk is then aggregated in the Bulk Processing Handler. + +5. [1.8] Position Handler produces messages corresponding to individual transfers that are part of a bulk to bulk processing topic +6. [1.9] For every message consumed from the bulk processing topic a check is made on the Bulk processing Handler to see if that’s the last individual transfer in a bulk for that processing phase. +7. [1.10, 1.11, 1.12] If it is the last transfer, aggregate the state of all the individual transfers and + + a. If all of them are in reserved state --> Send POST /bulkTransfers to the Payee (by producing a message to the notifications topic which is then consumed by the notification handler) + + b. Once the bulkTransfer prepare request is sent to the Payee, then change status to ACCEPTED + +8. In a successful case of Prepare - when the PUT from the Payee FSP for bulkFulfil is received, a notification is put on the bulk fulfil topic with a reference to the actual Fulfil message that's stored in an Object store. +9. This is to be consumed by the bulkFulfilHandler, which then changes state to PROCESSING. +10. The bulk-fulfil-handler breaks down the bulk into individual transfers and sends each of them through the refactored Fulfil, Position Handlers to commit/abort each of them based on the PUT /bulkTransfers/{ID} message by the Payee and commit/release funds on the Switch +11. The bulk-processing-handler is to then aggregate all the individual transfer results and change the state of bulkTransfer to COMPLETED/REJECTED based on success/failure + + a. If the Payee sends COMMITTED for even one of the individual transfers the proposal is to change bulk state to COMPLETED. + + b. However, for step-8 or if the Payee sends REJECTED as bulkTransferState then final state on Switch should be REJECTED. + +12. Send notifications to both Payer and Payee (similar to Single transfers, though diverging from the Spec 1.0). The Payer-FSP receives the notification that includes an exhaustive list of individual transfers, same as the list present in the prepare request sent by the Payer. The Payee-FSP receives a notification only for sub-set of transfers, which were sent to it from the Switch as the Bulk prepare request (that were able to be reserved at the Switch). + +## 4. Implementation Details + +### 4.1 Bulk Transfer States + +Below are the states of a Bulk transfer as per the Mojaloop API Specification + +1. RECEIVED +2. PENDING +3. ACCEPTED +4. PROCESSING +5. COMPLETED +6. REJECTED +7. Internal state - PENDING_PREPARE (mapped to PENDING) +8. Internal state - PENDING_INVALID (mapped to PENDING) +9. Internal state - PENDING_FULFIL (mapped to PROCESSING) +10. Internal state - EXPIRING (mapped to PROCESSING) +11. Internal state - EXPIRED (mapped to COMPLETED) +12. Internal state - INVALID (mapped to REJECTED) +13. Additional micro-states may be added for internal use on the Switch + +### 4.2 Proposed New tables + +Below are the proposed tables as part of designing the Bulk transfers + +- bulkTransfer +- bulkTransferStateChange +- bulkTransferError +- bulkTransferDuplicateCheck +- bulkTransferFulfilment +- bulkTransferFulfilmentDuplicateCheck +- bulkTransferAssociation +- bulkTransferExtension +- bulkTransferState +- bulkProcessingState + +### 4.3 Internal Type-Action-Status combinations + +#### 1. Bulk transfer that passes schema validation [ml-api-adapter -> bulk-prepare-handler] + + 1. type: bulk-prepare + 2. action: bulk-prepare + 3. Status: success + 4. Result: bulkTransferState=RECEIVED, bulkProcessingState=RECEIVED + +#### 2. Duplicate [bulk-prepare-handler -> notification handler] + + 1. type: notification + 2. action: bulk-prepare-duplicate + 3. Status: success + 4. Result: bulkTransferState=N/A, bulkProcessingState=N/A + +#### 3. Validate Bulk Prepare transfer failure [bulk-prepare-handler -> notification-handler] + + 1. type: notification + 2. action: bulk-abort + 3. Status: error + +#### 4. For a Valid Bulk Prepare transfer (broken down and sent as individual transfers) [bulk-prepare-handler -> prepare-handler] + + 1. type: prepare + 2. action: bulk-prepare + 3. Status: success + +#### 5. Duplicate of individual transfer that is part of a bulk-transfer [prepare-handler -> bulk-processing-handler] + + 1. type: bulk-processing + 2. action: prepare-duplicate + 3. Status: success + 4. Expected action: Add error message indicating it’s a duplicate + 5. Result: bulkTransferState=PENDING_PREPARE/ACCEPTED (depending on whether it’s the last one), bulkProcessingState=RECEIVED_DUPLICATE + +#### 6. For individual Prepare transfer that’s a valid duplicate in prepare handler [prepare-handler -> bulk-processing-handler] + + 1. type: bulk-processing + 2. action: prepare-duplicate + 3. Status: error + 4. Result: bulkTransferState=PENDING_PREPARE/ACCEPTED (depending on whether it’s the last one), bulkProcessingState=RECEIVED_DUPLICATE + +#### 7. For a Valid individual Prepare transfer that’s part of a bulk [prepare-handler -> position-handler] + + 1. type: position + 2. action: bulk-prepare + 3. Status: success + +#### 8. For individual Prepare transfer that’s part of a bulk that failed validation in prepare handler [prepare-handler -> bulk-processing-handler] + + 1. type: bulk-processing + 2. action: bulk-prepare + 3. Status: error + 4. Result: bulkTransferState=PENDING_PREPARE/ACCEPTED (depending on whether it’s the last one), bulkProcessingState=RECEIVED_INVALID + +#### 9. For a Valid individual Prepare transfer that’s part of a bulk [position-handler -> bulk-processing-handler] + + 1. type: bulk-processing + 2. action: bulk-prepare + 3. Status: success + 4. Result: bulkTransferState=PENDING_PREPARE/ACCEPTED (depending on whether it’s the last one), bulkProcessingState=ACCEPTED + +#### 10. For individual Prepare transfer that’s part of a bulk that failed validation in position handler [position-handler -> bulk-processing-handler] + + 1. type: bulk-processing + 2. action: bulk-prepare + 3. Status: error + 4. Result: bulkTransferState=PENDING_PREPARE/ACCEPTED (depending on whether it’s the last one), bulkProcessingState=RECEIVED_INVALID + +#### 11. For a Valid individual Fulfil transfer (for commit) that’s part of a bulk [position-handler -> bulk-processing-handler] + + 1. type: bulk-processing + 2. action: bulk-commit + 3. Status: success + 4. Result: bulkTransferState=PENDING_FULFIL/COMPLETED (depending on whether it’s the last one), bulkProcessingState=COMPLETED + +#### 12. For Bulk transfer Fulfil message that passes validation [ml-api-adapter -> bulk-fulfil-handler] + + 1. type: bulk-fulfil + 2. action: bulk-commit + 3. Status: success + +#### 13. For a valid individual transfer part of a bulk that timed-out in position handler [position-handler -> bulk-processing-handler] + + 1. type: bulk-processing + 2. action: bulk-timeout-reserved + 3. Status: error + 4. Result: bulkTransferState=PENDING_FULFIL/COMPLETED (depending on whether it’s the last one), bulkProcessingState=FULFIL_INVALID + +#### 14. For a Valid individual Fulfil transfer (for reject) that’s part of a bulk [position-handler -> bulk-processing-handler] + + 1. type: bulk-processing + 2. action: reject + 3. Status: success + 4. Result: bulkTransferState=PENDING_FULFIL/COMPLETED (depending on whether it’s the last one), bulkProcessingState=REJECTED + +#### 15. Invalid Fulfil duplicate of an individual transfer in a bulk [fulfil-handler -> bulk-processing-handler] + + 1. type: bulk-processing + 2. action: fulfil-duplicate + 3. Status: error + 4. Result: bulkTransferState=PENDING_FULFIL/COMPLETED (depending on whether it’s the last one), bulkProcessingState=FULFIL_DUPLICATE + +#### 16. Valid Fulfil duplicate of an individual transfer in a bulk [fulfil-handler -> bulk-processing-handler] + + 1. type: bulk-processing + 2. action: fulfil-duplicate + 3. Status: success + 4. Result: bulkTransferState=PENDING_FULFIL/COMPLETED (depending on whether it’s the last one), bulkProcessingState=FULFIL_DUPLICATE + +#### 17. Valid Fulfil message of an individual transfer in a bulk [fulfil-handler -> position-handler] + + 1. type: position + 2. action: bulk-commit + 3. Status: success + +#### 18. For individual Fulfil transfer that’s part of a bulk that failed validation in fulfil handler [fulfil-handler -> bulk-processing-handler] + + 1. type: bulk-processing + 2. action: bulk-commit + 3. Status: error + 4. Result: bulkTransferState=PENDING_FULFIL/COMPLETED (depending on whether it’s the last one), bulkProcessingState=FULFIL_INVALID + +#### 19. Fulfil transfer request that’s part of a bulk that passes validation [bulk-fulfil-handler -> fulfil-handler] + + 1. type: bulk-fulfil + 2. action: bulk-commit + 3. Status: success + +#### 20. For Bulk transfers failing validation at bulk-fulfil-handler level [bulk-fulfil-handler -> notification-handler] + + 1. type: notification + 2. action: bulk-abort + 3. Status: error + +#### 21. For Bulk transfer notifications to FSPs [bulk-processing-handler -> notification-handler] + + 1. type: notification + 2. action: bulk-prepare / bulk-commit + 3. Status: success + +#### 22. For timeout notification [timeout-handler -> bulk-processing-handler] + + 1. type: bulk-processing + 2. action: bulk-timeout-received + 3. Status: error + 4. Result: bulkTransferState=COMPLETED (for the last one), bulkProcessingState=EXPIRED + +#### 23. For timeout notification [timeout-handler -> position-handler] + + 1. type: position + 2. action: bulk-timeout-reserved + 3. Status: error + +#### 24. For timeout notification after position adjust [position-handler -> bulk-processing-handler] + + 1. type: bulk-processing + 2. action: bulk-timeout-reserved + 3. Status: error + 4. Result: bulkTransferState=COMPLETED (for the last one), bulkProcessingState=EXPIRED + +### 4.4 Additional Notes + +1. Document GET /bulkTransfers to indicate the difference in responses the Payer-FSP & Payee-FSP receive for Bulk Transfers +2. Used a separate service: bulk-api-adapter to support bulk transfers end-points (that includes persistence as discussed above) + +## 5. Roadmap Topics + +1. Re-assess the need to support multiple Payee FSPs as part of a Bulk and the changes to the Specification needed. +2. Issues, learnings from the PoC that are documented are addressed in order of priority +3. Find out a need to support something like a Bulk make resource (/bulkMake ?) in which the Switch accepts an entire Bulk as it is and then takes care of all three phases - lookup, quote and transfers. +4. Throttling of individual transfers in a bulk? +5. The aspect of ordering in a Bulk - the order of processing at the Switch and at the FSPs. Recommendation to Scheme to incorporate Rule to mandate all FSPs to process transactions a bulk in the existing order and not have preferential processing. On the Switch currently being neutral with ordering but best practice is to sort in ascending order of amounts and process. +6. For Settlements with bulk transfers where Government payments are involved with large sums of money needs to be discussed to allow for moving through transfers without strict liquidity rules needs to be discussed. +7. Implement GET /bulkTransfers +8. Implement notifications/logging for all bulk negative scenarios +9. Full unit tests code coverage +10. Integration testing of successful bulk transfer (golden path) +11. Regression testing, including negative scenarios diff --git a/docs/technical/central-bulk-transfers/assets/database/central-ledger-ddl-MySQLWorkbench.sql b/docs/technical/central-bulk-transfers/assets/database/central-ledger-ddl-MySQLWorkbench.sql new file mode 100644 index 000000000..f6995bc85 --- /dev/null +++ b/docs/technical/central-bulk-transfers/assets/database/central-ledger-ddl-MySQLWorkbench.sql @@ -0,0 +1,1600 @@ +-- MySQL dump 10.13 Distrib 8.0.16, for macos10.14 (x86_64) +-- +-- Host: 127.0.0.1 Database: central_ledger +-- ------------------------------------------------------ +-- Server version 8.0.13 + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; + SET NAMES utf8 ; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Table structure for table `amountType` +-- + +DROP TABLE IF EXISTS `amountType`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `amountType` ( + `amountTypeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(256) NOT NULL, + `description` varchar(1024) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`amountTypeId`), + UNIQUE KEY `amounttype_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `balanceOfPayments` +-- + +DROP TABLE IF EXISTS `balanceOfPayments`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `balanceOfPayments` ( + `balanceOfPaymentsId` int(10) unsigned NOT NULL, + `name` varchar(256) NOT NULL, + `description` varchar(1024) DEFAULT NULL COMMENT 'Possible values and meaning are defined in https://www.imf.org/external/np/sta/bopcode/', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`balanceOfPaymentsId`), + UNIQUE KEY `balanceofpayments_name_unique` (`name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='See https://www.imf.org/external/np/sta/bopcode/guide.htm'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `bulkProcessingState` +-- + +DROP TABLE IF EXISTS `bulkProcessingState`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `bulkProcessingState` ( + `bulkProcessingStateId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`bulkProcessingStateId`), + UNIQUE KEY `bulkprocessingstate_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `bulkTransfer` +-- + +DROP TABLE IF EXISTS `bulkTransfer`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `bulkTransfer` ( + `bulkTransferId` varchar(36) NOT NULL, + `bulkQuoteId` varchar(36) DEFAULT NULL, + `payerParticipantId` int(10) unsigned DEFAULT NULL, + `payeeParticipantId` int(10) unsigned DEFAULT NULL, + `expirationDate` datetime NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`bulkTransferId`), + KEY `bulktransfer_payerparticipantid_index` (`payerParticipantId`), + KEY `bulktransfer_payeeparticipantid_index` (`payeeParticipantId`), + CONSTRAINT `bulktransfer_bulktransferid_foreign` FOREIGN KEY (`bulkTransferId`) REFERENCES `bulkTransferDuplicateCheck` (`bulktransferid`), + CONSTRAINT `bulktransfer_payeeparticipantid_foreign` FOREIGN KEY (`payeeParticipantId`) REFERENCES `participant` (`participantid`), + CONSTRAINT `bulktransfer_payerparticipantid_foreign` FOREIGN KEY (`payerParticipantId`) REFERENCES `participant` (`participantid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `bulkTransferAssociation` +-- + +DROP TABLE IF EXISTS `bulkTransferAssociation`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `bulkTransferAssociation` ( + `bulkTransferAssociationId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `transferId` varchar(36) NOT NULL, + `bulkTransferId` varchar(36) NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `bulkProcessingStateId` int(10) unsigned NOT NULL, + `lastProcessedDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `errorCode` int(10) unsigned DEFAULT NULL, + `errorDescription` varchar(128) DEFAULT NULL, + PRIMARY KEY (`bulkTransferAssociationId`), + UNIQUE KEY `bulktransferassociation_transferid_bulktransferid_unique` (`transferId`,`bulkTransferId`), + KEY `bulktransferassociation_bulktransferid_foreign` (`bulkTransferId`), + KEY `bulktransferassociation_bulkprocessingstateid_foreign` (`bulkProcessingStateId`), + CONSTRAINT `bulktransferassociation_bulkprocessingstateid_foreign` FOREIGN KEY (`bulkProcessingStateId`) REFERENCES `bulkProcessingState` (`bulkprocessingstateid`), + CONSTRAINT `bulktransferassociation_bulktransferid_foreign` FOREIGN KEY (`bulkTransferId`) REFERENCES `bulkTransfer` (`bulktransferid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `bulkTransferDuplicateCheck` +-- + +DROP TABLE IF EXISTS `bulkTransferDuplicateCheck`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `bulkTransferDuplicateCheck` ( + `bulkTransferId` varchar(36) NOT NULL, + `hash` varchar(256) NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`bulkTransferId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `bulkTransferError` +-- + +DROP TABLE IF EXISTS `bulkTransferError`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `bulkTransferError` ( + `bulkTransferErrorId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `bulkTransferStateChangeId` bigint(20) unsigned NOT NULL, + `errorCode` int(10) unsigned NOT NULL, + `errorDescription` varchar(128) NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`bulkTransferErrorId`), + KEY `bulktransfererror_bulktransferstatechangeid_index` (`bulkTransferStateChangeId`), + CONSTRAINT `bulktransfererror_bulktransferstatechangeid_foreign` FOREIGN KEY (`bulkTransferStateChangeId`) REFERENCES `bulkTransferStateChange` (`bulktransferstatechangeid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `bulkTransferExtension` +-- + +DROP TABLE IF EXISTS `bulkTransferExtension`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `bulkTransferExtension` ( + `bulkTransferExtensionId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `bulkTransferId` varchar(36) NOT NULL, + `isFulfilment` tinyint(1) NOT NULL DEFAULT '0', + `key` varchar(128) NOT NULL, + `value` text NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`bulkTransferExtensionId`), + KEY `bulktransferextension_bulktransferid_index` (`bulkTransferId`), + CONSTRAINT `bulktransferextension_bulktransferid_foreign` FOREIGN KEY (`bulkTransferId`) REFERENCES `bulkTransfer` (`bulktransferid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `bulkTransferFulfilment` +-- + +DROP TABLE IF EXISTS `bulkTransferFulfilment`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `bulkTransferFulfilment` ( + `bulkTransferId` varchar(36) NOT NULL, + `completedDate` datetime NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`bulkTransferId`), + CONSTRAINT `bulktransferfulfilment_bulktransferid_foreign` FOREIGN KEY (`bulkTransferId`) REFERENCES `bulkTransferFulfilmentDuplicateCheck` (`bulktransferid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `bulkTransferFulfilmentDuplicateCheck` +-- + +DROP TABLE IF EXISTS `bulkTransferFulfilmentDuplicateCheck`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `bulkTransferFulfilmentDuplicateCheck` ( + `bulkTransferId` varchar(36) NOT NULL, + `hash` varchar(256) NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`bulkTransferId`), + CONSTRAINT `bulktransferfulfilmentduplicatecheck_bulktransferid_foreign` FOREIGN KEY (`bulkTransferId`) REFERENCES `bulkTransfer` (`bulktransferid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `bulkTransferState` +-- + +DROP TABLE IF EXISTS `bulkTransferState`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `bulkTransferState` ( + `bulkTransferStateId` varchar(50) NOT NULL, + `enumeration` varchar(50) NOT NULL COMMENT 'bulkTransferState associated to the Mojaloop API', + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`bulkTransferStateId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `bulkTransferStateChange` +-- + +DROP TABLE IF EXISTS `bulkTransferStateChange`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `bulkTransferStateChange` ( + `bulkTransferStateChangeId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `bulkTransferId` varchar(36) NOT NULL, + `bulkTransferStateId` varchar(50) NOT NULL, + `reason` varchar(512) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`bulkTransferStateChangeId`), + KEY `bulktransferstatechange_bulktransferid_index` (`bulkTransferId`), + KEY `bulktransferstatechange_bulktransferstateid_index` (`bulkTransferStateId`), + CONSTRAINT `bulktransferstatechange_bulktransferid_foreign` FOREIGN KEY (`bulkTransferId`) REFERENCES `bulkTransfer` (`bulktransferid`), + CONSTRAINT `bulktransferstatechange_bulktransferstateid_foreign` FOREIGN KEY (`bulkTransferStateId`) REFERENCES `bulkTransferState` (`bulktransferstateid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `contactType` +-- + +DROP TABLE IF EXISTS `contactType`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `contactType` ( + `contactTypeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`contactTypeId`), + UNIQUE KEY `contacttype_name_unique` (`name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `currency` +-- + +DROP TABLE IF EXISTS `currency`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `currency` ( + `currencyId` varchar(3) NOT NULL, + `name` varchar(128) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `scale` int(10) unsigned NOT NULL DEFAULT '4', + PRIMARY KEY (`currencyId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `endpointType` +-- + +DROP TABLE IF EXISTS `endpointType`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `endpointType` ( + `endpointTypeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`endpointTypeId`), + UNIQUE KEY `endpointtype_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `event` +-- + +DROP TABLE IF EXISTS `event`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `event` ( + `eventId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(128) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`eventId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `geoCode` +-- + +DROP TABLE IF EXISTS `geoCode`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `geoCode` ( + `geoCodeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `quotePartyId` bigint(20) unsigned NOT NULL COMMENT 'Optionally the GeoCode for the Payer/Payee may have been provided. If the Quote Response has the GeoCode for the Payee, an additional row is added', + `latitude` varchar(50) NOT NULL COMMENT 'Latitude of the initiating Party', + `longitude` varchar(50) NOT NULL COMMENT 'Longitude of the initiating Party', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`geoCodeId`), + KEY `geocode_quotepartyid_foreign` (`quotePartyId`), + CONSTRAINT `geocode_quotepartyid_foreign` FOREIGN KEY (`quotePartyId`) REFERENCES `quoteParty` (`quotepartyid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ilpPacket` +-- + +DROP TABLE IF EXISTS `ilpPacket`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `ilpPacket` ( + `transferId` varchar(36) NOT NULL, + `value` text NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferId`), + CONSTRAINT `ilppacket_transferid_foreign` FOREIGN KEY (`transferId`) REFERENCES `transfer` (`transferid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ledgerAccountType` +-- + +DROP TABLE IF EXISTS `ledgerAccountType`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `ledgerAccountType` ( + `ledgerAccountTypeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`ledgerAccountTypeId`), + UNIQUE KEY `ledgeraccounttype_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ledgerEntryType` +-- + +DROP TABLE IF EXISTS `ledgerEntryType`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `ledgerEntryType` ( + `ledgerEntryTypeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`ledgerEntryTypeId`), + UNIQUE KEY `ledgerentrytype_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `migration` +-- + +DROP TABLE IF EXISTS `migration`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `migration` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(255) DEFAULT NULL, + `batch` int(11) DEFAULT NULL, + `migration_time` timestamp NULL DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=138 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `migration_lock` +-- + +DROP TABLE IF EXISTS `migration_lock`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `migration_lock` ( + `index` int(10) unsigned NOT NULL AUTO_INCREMENT, + `is_locked` int(11) DEFAULT NULL, + PRIMARY KEY (`index`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `participant` +-- + +DROP TABLE IF EXISTS `participant`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `participant` ( + `participantId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(256) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `createdBy` varchar(128) NOT NULL, + PRIMARY KEY (`participantId`), + UNIQUE KEY `participant_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `participantContact` +-- + +DROP TABLE IF EXISTS `participantContact`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `participantContact` ( + `participantContactId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `participantId` int(10) unsigned NOT NULL, + `contactTypeId` int(10) unsigned NOT NULL, + `value` varchar(256) NOT NULL, + `priorityPreference` int(11) NOT NULL DEFAULT '9', + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `createdBy` varchar(128) NOT NULL, + PRIMARY KEY (`participantContactId`), + KEY `participantcontact_participantid_index` (`participantId`), + KEY `participantcontact_contacttypeid_index` (`contactTypeId`), + CONSTRAINT `participantcontact_contacttypeid_foreign` FOREIGN KEY (`contactTypeId`) REFERENCES `contactType` (`contacttypeid`), + CONSTRAINT `participantcontact_participantid_foreign` FOREIGN KEY (`participantId`) REFERENCES `participant` (`participantid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `participantCurrency` +-- + +DROP TABLE IF EXISTS `participantCurrency`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `participantCurrency` ( + `participantCurrencyId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `participantId` int(10) unsigned NOT NULL, + `currencyId` varchar(3) NOT NULL, + `ledgerAccountTypeId` int(10) unsigned NOT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `createdBy` varchar(128) NOT NULL, + PRIMARY KEY (`participantCurrencyId`), + UNIQUE KEY `participantcurrency_pcl_unique` (`participantId`,`currencyId`,`ledgerAccountTypeId`), + KEY `participantcurrency_ledgeraccounttypeid_foreign` (`ledgerAccountTypeId`), + KEY `participantcurrency_participantid_index` (`participantId`), + KEY `participantcurrency_currencyid_index` (`currencyId`), + CONSTRAINT `participantcurrency_currencyid_foreign` FOREIGN KEY (`currencyId`) REFERENCES `currency` (`currencyid`), + CONSTRAINT `participantcurrency_ledgeraccounttypeid_foreign` FOREIGN KEY (`ledgerAccountTypeId`) REFERENCES `ledgerAccountType` (`ledgeraccounttypeid`), + CONSTRAINT `participantcurrency_participantid_foreign` FOREIGN KEY (`participantId`) REFERENCES `participant` (`participantid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `participantEndpoint` +-- + +DROP TABLE IF EXISTS `participantEndpoint`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `participantEndpoint` ( + `participantEndpointId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `participantId` int(10) unsigned NOT NULL, + `endpointTypeId` int(10) unsigned NOT NULL, + `value` varchar(512) NOT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `createdBy` varchar(128) NOT NULL, + PRIMARY KEY (`participantEndpointId`), + KEY `participantendpoint_participantid_index` (`participantId`), + KEY `participantendpoint_endpointtypeid_index` (`endpointTypeId`), + CONSTRAINT `participantendpoint_endpointtypeid_foreign` FOREIGN KEY (`endpointTypeId`) REFERENCES `endpointType` (`endpointtypeid`), + CONSTRAINT `participantendpoint_participantid_foreign` FOREIGN KEY (`participantId`) REFERENCES `participant` (`participantid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `participantLimit` +-- + +DROP TABLE IF EXISTS `participantLimit`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `participantLimit` ( + `participantLimitId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `participantCurrencyId` int(10) unsigned NOT NULL, + `participantLimitTypeId` int(10) unsigned NOT NULL, + `value` decimal(18,4) NOT NULL DEFAULT '0.0000', + `thresholdAlarmPercentage` decimal(5,2) NOT NULL DEFAULT '10.00', + `startAfterParticipantPositionChangeId` bigint(20) unsigned DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `createdBy` varchar(128) NOT NULL, + PRIMARY KEY (`participantLimitId`), + KEY `participantlimit_participantcurrencyid_index` (`participantCurrencyId`), + KEY `participantlimit_participantlimittypeid_index` (`participantLimitTypeId`), + KEY `participantlimit_startafterparticipantpositionchangeid_index` (`startAfterParticipantPositionChangeId`), + CONSTRAINT `participantlimit_participantcurrencyid_foreign` FOREIGN KEY (`participantCurrencyId`) REFERENCES `participantCurrency` (`participantcurrencyid`), + CONSTRAINT `participantlimit_participantlimittypeid_foreign` FOREIGN KEY (`participantLimitTypeId`) REFERENCES `participantLimitType` (`participantlimittypeid`), + CONSTRAINT `participantlimit_startafterparticipantpositionchangeid_foreign` FOREIGN KEY (`startAfterParticipantPositionChangeId`) REFERENCES `participantPositionChange` (`participantpositionchangeid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `participantLimitType` +-- + +DROP TABLE IF EXISTS `participantLimitType`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `participantLimitType` ( + `participantLimitTypeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`participantLimitTypeId`), + UNIQUE KEY `participantlimittype_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `participantParty` +-- + +DROP TABLE IF EXISTS `participantParty`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `participantParty` ( + `participantPartyId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `participantId` int(10) unsigned NOT NULL, + `partyId` bigint(20) unsigned NOT NULL, + PRIMARY KEY (`participantPartyId`), + UNIQUE KEY `participantparty_participantid_partyid_unique` (`participantId`,`partyId`), + KEY `participantparty_participantid_index` (`participantId`), + CONSTRAINT `participantparty_participantid_foreign` FOREIGN KEY (`participantId`) REFERENCES `participant` (`participantid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `participantPosition` +-- + +DROP TABLE IF EXISTS `participantPosition`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `participantPosition` ( + `participantPositionId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `participantCurrencyId` int(10) unsigned NOT NULL, + `value` decimal(18,4) NOT NULL, + `reservedValue` decimal(18,4) NOT NULL, + `changedDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`participantPositionId`), + KEY `participantposition_participantcurrencyid_index` (`participantCurrencyId`), + CONSTRAINT `participantposition_participantcurrencyid_foreign` FOREIGN KEY (`participantCurrencyId`) REFERENCES `participantCurrency` (`participantcurrencyid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `participantPositionChange` +-- + +DROP TABLE IF EXISTS `participantPositionChange`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `participantPositionChange` ( + `participantPositionChangeId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `participantPositionId` bigint(20) unsigned NOT NULL, + `transferStateChangeId` bigint(20) unsigned NOT NULL, + `value` decimal(18,4) NOT NULL, + `reservedValue` decimal(18,4) NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`participantPositionChangeId`), + KEY `participantpositionchange_participantpositionid_index` (`participantPositionId`), + KEY `participantpositionchange_transferstatechangeid_index` (`transferStateChangeId`), + CONSTRAINT `participantpositionchange_participantpositionid_foreign` FOREIGN KEY (`participantPositionId`) REFERENCES `participantPosition` (`participantpositionid`), + CONSTRAINT `participantpositionchange_transferstatechangeid_foreign` FOREIGN KEY (`transferStateChangeId`) REFERENCES `transferStateChange` (`transferstatechangeid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `party` +-- + +DROP TABLE IF EXISTS `party`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `party` ( + `partyId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `quotePartyId` bigint(20) unsigned NOT NULL, + `firstName` varchar(128) DEFAULT NULL, + `middleName` varchar(128) DEFAULT NULL, + `lastName` varchar(128) DEFAULT NULL, + `dateOfBirth` datetime DEFAULT NULL, + PRIMARY KEY (`partyId`), + KEY `party_quotepartyid_foreign` (`quotePartyId`), + CONSTRAINT `party_quotepartyid_foreign` FOREIGN KEY (`quotePartyId`) REFERENCES `quoteParty` (`quotepartyid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Optional pers. data provided during Quote Request & Response'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `partyIdentifierType` +-- + +DROP TABLE IF EXISTS `partyIdentifierType`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `partyIdentifierType` ( + `partyIdentifierTypeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + `description` varchar(512) NOT NULL, + PRIMARY KEY (`partyIdentifierTypeId`), + UNIQUE KEY `partyidentifiertype_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `partyType` +-- + +DROP TABLE IF EXISTS `partyType`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `partyType` ( + `partyTypeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(128) NOT NULL, + `description` varchar(256) NOT NULL, + PRIMARY KEY (`partyTypeId`), + UNIQUE KEY `partytype_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `quote` +-- + +DROP TABLE IF EXISTS `quote`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `quote` ( + `quoteId` varchar(36) NOT NULL, + `transactionReferenceId` varchar(36) NOT NULL COMMENT 'Common ID (decided by the Payer FSP) between the FSPs for the future transaction object', + `transactionRequestId` varchar(36) DEFAULT NULL COMMENT 'Optional previously-sent transaction request', + `note` text COMMENT 'A memo that will be attached to the transaction', + `expirationDate` datetime DEFAULT NULL COMMENT 'Optional expiration for the requested transaction', + `transactionInitiatorId` int(10) unsigned NOT NULL COMMENT 'This is part of the transaction initiator', + `transactionInitiatorTypeId` int(10) unsigned NOT NULL COMMENT 'This is part of the transaction initiator type', + `transactionScenarioId` int(10) unsigned NOT NULL COMMENT 'This is part of the transaction scenario', + `balanceOfPaymentsId` int(10) unsigned DEFAULT NULL COMMENT 'This is part of the transaction type that contains the elements- balance of payment', + `transactionSubScenarioId` int(10) unsigned DEFAULT NULL COMMENT 'This is part of the transaction type sub scenario as defined by the local scheme', + `amountTypeId` int(10) unsigned NOT NULL COMMENT 'This is part of the transaction type that contains valid elements for - Amount Type', + `amount` decimal(18,4) NOT NULL DEFAULT '0.0000' COMMENT 'The amount that the quote is being requested for. Need to be interpert in accordance with the amount type', + `currencyId` varchar(255) DEFAULT NULL COMMENT 'Trading currency pertaining to the Amount', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`quoteId`), + KEY `quote_transactionreferenceid_foreign` (`transactionReferenceId`), + KEY `quote_transactionrequestid_foreign` (`transactionRequestId`), + KEY `quote_transactioninitiatorid_foreign` (`transactionInitiatorId`), + KEY `quote_transactioninitiatortypeid_foreign` (`transactionInitiatorTypeId`), + KEY `quote_transactionscenarioid_foreign` (`transactionScenarioId`), + KEY `quote_balanceofpaymentsid_foreign` (`balanceOfPaymentsId`), + KEY `quote_transactionsubscenarioid_foreign` (`transactionSubScenarioId`), + KEY `quote_amounttypeid_foreign` (`amountTypeId`), + KEY `quote_currencyid_foreign` (`currencyId`), + CONSTRAINT `quote_amounttypeid_foreign` FOREIGN KEY (`amountTypeId`) REFERENCES `amountType` (`amounttypeid`), + CONSTRAINT `quote_balanceofpaymentsid_foreign` FOREIGN KEY (`balanceOfPaymentsId`) REFERENCES `balanceOfPayments` (`balanceofpaymentsid`), + CONSTRAINT `quote_currencyid_foreign` FOREIGN KEY (`currencyId`) REFERENCES `currency` (`currencyid`), + CONSTRAINT `quote_transactioninitiatorid_foreign` FOREIGN KEY (`transactionInitiatorId`) REFERENCES `transactionInitiator` (`transactioninitiatorid`), + CONSTRAINT `quote_transactioninitiatortypeid_foreign` FOREIGN KEY (`transactionInitiatorTypeId`) REFERENCES `transactionInitiatorType` (`transactioninitiatortypeid`), + CONSTRAINT `quote_transactionreferenceid_foreign` FOREIGN KEY (`transactionReferenceId`) REFERENCES `transactionReference` (`transactionreferenceid`), + CONSTRAINT `quote_transactionrequestid_foreign` FOREIGN KEY (`transactionRequestId`) REFERENCES `transactionReference` (`transactionreferenceid`), + CONSTRAINT `quote_transactionscenarioid_foreign` FOREIGN KEY (`transactionScenarioId`) REFERENCES `transactionScenario` (`transactionscenarioid`), + CONSTRAINT `quote_transactionsubscenarioid_foreign` FOREIGN KEY (`transactionSubScenarioId`) REFERENCES `transactionSubScenario` (`transactionsubscenarioid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `quoteDuplicateCheck` +-- + +DROP TABLE IF EXISTS `quoteDuplicateCheck`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `quoteDuplicateCheck` ( + `quoteId` varchar(36) NOT NULL COMMENT 'Common ID between the FSPs for the quote object, decided by the Payer FSP', + `hash` varchar(1024) DEFAULT NULL COMMENT 'hash value received for the quote request', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`quoteId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `quoteError` +-- + +DROP TABLE IF EXISTS `quoteError`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `quoteError` ( + `quoteErrorId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `quoteId` varchar(36) NOT NULL COMMENT 'Common ID between the FSPs for the quote object, decided by the Payer FSP', + `quoteResponseId` bigint(20) unsigned DEFAULT NULL COMMENT 'The response to the intial quote', + `errorCode` int(10) unsigned NOT NULL, + `errorDescription` varchar(128) NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`quoteErrorId`), + KEY `quoteerror_quoteid_foreign` (`quoteId`), + KEY `quoteerror_quoteresponseid_foreign` (`quoteResponseId`), + CONSTRAINT `quoteerror_quoteid_foreign` FOREIGN KEY (`quoteId`) REFERENCES `quote` (`quoteid`), + CONSTRAINT `quoteerror_quoteresponseid_foreign` FOREIGN KEY (`quoteResponseId`) REFERENCES `quoteResponse` (`quoteresponseid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `quoteExtension` +-- + +DROP TABLE IF EXISTS `quoteExtension`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `quoteExtension` ( + `quoteExtensionId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `quoteId` varchar(36) NOT NULL COMMENT 'Common ID between the FSPs for the quote object, decided by the Payer FSP', + `quoteResponseId` bigint(20) unsigned NOT NULL COMMENT 'The response to the intial quote', + `transactionId` varchar(36) NOT NULL COMMENT 'The transaction reference that is part of the initial quote', + `key` varchar(128) NOT NULL, + `value` text NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`quoteExtensionId`), + KEY `quoteextension_quoteid_foreign` (`quoteId`), + KEY `quoteextension_quoteresponseid_foreign` (`quoteResponseId`), + KEY `quoteextension_transactionid_foreign` (`transactionId`), + CONSTRAINT `quoteextension_quoteid_foreign` FOREIGN KEY (`quoteId`) REFERENCES `quote` (`quoteid`), + CONSTRAINT `quoteextension_quoteresponseid_foreign` FOREIGN KEY (`quoteResponseId`) REFERENCES `quoteResponse` (`quoteresponseid`), + CONSTRAINT `quoteextension_transactionid_foreign` FOREIGN KEY (`transactionId`) REFERENCES `transactionReference` (`transactionreferenceid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `quoteParty` +-- + +DROP TABLE IF EXISTS `quoteParty`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `quoteParty` ( + `quotePartyId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `quoteId` varchar(36) NOT NULL COMMENT 'Common ID between the FSPs for the quote object, decided by the Payer FSP', + `partyTypeId` int(10) unsigned NOT NULL COMMENT 'Specifies the type of party this row relates to; typically PAYER or PAYEE', + `partyIdentifierTypeId` int(10) unsigned NOT NULL COMMENT 'Specifies the type of identifier used to identify this party e.g. MSISDN, IBAN etc...', + `partyIdentifierValue` varchar(128) NOT NULL COMMENT 'The value of the identifier used to identify this party', + `partySubIdOrTypeId` int(10) unsigned DEFAULT NULL COMMENT 'A sub-identifier or sub-type for the Party', + `fspId` varchar(255) DEFAULT NULL COMMENT 'This is the FSP ID as provided in the quote. For the switch between multi-parties it is required', + `participantId` int(10) unsigned DEFAULT NULL COMMENT 'Reference to the resolved FSP ID (if supplied/known). If not an error will be reported', + `merchantClassificationCode` varchar(4) DEFAULT NULL COMMENT 'Used in the context of Payee Information, where the Payee happens to be a merchant accepting merchant payments', + `partyName` varchar(128) DEFAULT NULL COMMENT 'Display name of the Party, could be a real name or a nick name', + `transferParticipantRoleTypeId` int(10) unsigned NOT NULL COMMENT 'The role this Party is playing in the transaction', + `ledgerEntryTypeId` int(10) unsigned NOT NULL COMMENT 'The type of financial entry this Party is presenting', + `amount` decimal(18,4) NOT NULL, + `currencyId` varchar(3) NOT NULL COMMENT 'Trading currency pertaining to the party amount', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`quotePartyId`), + KEY `quoteparty_quoteid_foreign` (`quoteId`), + KEY `quoteparty_partytypeid_foreign` (`partyTypeId`), + KEY `quoteparty_partyidentifiertypeid_foreign` (`partyIdentifierTypeId`), + KEY `quoteparty_partysubidortypeid_foreign` (`partySubIdOrTypeId`), + KEY `quoteparty_participantid_foreign` (`participantId`), + KEY `quoteparty_transferparticipantroletypeid_foreign` (`transferParticipantRoleTypeId`), + KEY `quoteparty_ledgerentrytypeid_foreign` (`ledgerEntryTypeId`), + KEY `quoteparty_currencyid_foreign` (`currencyId`), + CONSTRAINT `quoteparty_currencyid_foreign` FOREIGN KEY (`currencyId`) REFERENCES `currency` (`currencyid`), + CONSTRAINT `quoteparty_ledgerentrytypeid_foreign` FOREIGN KEY (`ledgerEntryTypeId`) REFERENCES `ledgerEntryType` (`ledgerentrytypeid`), + CONSTRAINT `quoteparty_participantid_foreign` FOREIGN KEY (`participantId`) REFERENCES `participant` (`participantid`), + CONSTRAINT `quoteparty_partyidentifiertypeid_foreign` FOREIGN KEY (`partyIdentifierTypeId`) REFERENCES `partyIdentifierType` (`partyidentifiertypeid`), + CONSTRAINT `quoteparty_partysubidortypeid_foreign` FOREIGN KEY (`partySubIdOrTypeId`) REFERENCES `partyIdentifierType` (`partyidentifiertypeid`), + CONSTRAINT `quoteparty_partytypeid_foreign` FOREIGN KEY (`partyTypeId`) REFERENCES `partyType` (`partytypeid`), + CONSTRAINT `quoteparty_quoteid_foreign` FOREIGN KEY (`quoteId`) REFERENCES `quote` (`quoteid`), + CONSTRAINT `quoteparty_transferparticipantroletypeid_foreign` FOREIGN KEY (`transferParticipantRoleTypeId`) REFERENCES `transferParticipantRoleType` (`transferparticipantroletypeid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Temporary view structure for view `quotePartyView` +-- + +DROP TABLE IF EXISTS `quotePartyView`; +/*!50001 DROP VIEW IF EXISTS `quotePartyView`*/; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8mb4; +/*!50001 CREATE VIEW `quotePartyView` AS SELECT + 1 AS `quoteId`, + 1 AS `quotePartyId`, + 1 AS `partyType`, + 1 AS `identifierType`, + 1 AS `partyIdentifierValue`, + 1 AS `partySubIdOrType`, + 1 AS `fspId`, + 1 AS `merchantClassificationCode`, + 1 AS `partyName`, + 1 AS `firstName`, + 1 AS `lastName`, + 1 AS `middleName`, + 1 AS `dateOfBirth`, + 1 AS `longitude`, + 1 AS `latitude`*/; +SET character_set_client = @saved_cs_client; + +-- +-- Table structure for table `quoteResponse` +-- + +DROP TABLE IF EXISTS `quoteResponse`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `quoteResponse` ( + `quoteResponseId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `quoteId` varchar(36) NOT NULL COMMENT 'Common ID between the FSPs for the quote object, decided by the Payer FSP', + `transferAmountCurrencyId` varchar(3) NOT NULL COMMENT 'CurrencyId of the transfer amount', + `transferAmount` decimal(18,4) NOT NULL COMMENT 'The amount of money that the Payer FSP should transfer to the Payee FSP', + `payeeReceiveAmountCurrencyId` varchar(3) DEFAULT NULL COMMENT 'CurrencyId of the payee receive amount', + `payeeReceiveAmount` decimal(18,4) DEFAULT NULL COMMENT 'The amount of Money that the Payee should receive in the end-to-end transaction. Optional as the Payee FSP might not want to disclose any optional Payee fees', + `payeeFspFeeCurrencyId` varchar(3) DEFAULT NULL COMMENT 'CurrencyId of the payee fsp fee amount', + `payeeFspFeeAmount` decimal(18,4) DEFAULT NULL COMMENT 'Payee FSP’s part of the transaction fee', + `payeeFspCommissionCurrencyId` varchar(3) DEFAULT NULL COMMENT 'CurrencyId of the payee fsp commission amount', + `payeeFspCommissionAmount` decimal(18,4) DEFAULT NULL COMMENT 'Transaction commission from the Payee FSP', + `ilpCondition` varchar(256) NOT NULL, + `responseExpirationDate` datetime DEFAULT NULL COMMENT 'Optional expiration for the requested transaction', + `isValid` tinyint(1) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`quoteResponseId`), + KEY `quoteresponse_quoteid_foreign` (`quoteId`), + KEY `quoteresponse_transferamountcurrencyid_foreign` (`transferAmountCurrencyId`), + KEY `quoteresponse_payeereceiveamountcurrencyid_foreign` (`payeeReceiveAmountCurrencyId`), + KEY `quoteresponse_payeefspcommissioncurrencyid_foreign` (`payeeFspCommissionCurrencyId`), + CONSTRAINT `quoteresponse_payeefspcommissioncurrencyid_foreign` FOREIGN KEY (`payeeFspCommissionCurrencyId`) REFERENCES `currency` (`currencyid`), + CONSTRAINT `quoteresponse_payeereceiveamountcurrencyid_foreign` FOREIGN KEY (`payeeReceiveAmountCurrencyId`) REFERENCES `currency` (`currencyid`), + CONSTRAINT `quoteresponse_quoteid_foreign` FOREIGN KEY (`quoteId`) REFERENCES `quote` (`quoteid`), + CONSTRAINT `quoteresponse_transferamountcurrencyid_foreign` FOREIGN KEY (`transferAmountCurrencyId`) REFERENCES `currency` (`currencyid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='This table is the primary store for quote responses'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `quoteResponseDuplicateCheck` +-- + +DROP TABLE IF EXISTS `quoteResponseDuplicateCheck`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `quoteResponseDuplicateCheck` ( + `quoteResponseId` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'The response to the intial quote', + `quoteId` varchar(36) NOT NULL COMMENT 'Common ID between the FSPs for the quote object, decided by the Payer FSP', + `hash` varchar(255) DEFAULT NULL COMMENT 'hash value received for the quote response', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`quoteResponseId`), + KEY `quoteresponseduplicatecheck_quoteid_foreign` (`quoteId`), + CONSTRAINT `quoteresponseduplicatecheck_quoteid_foreign` FOREIGN KEY (`quoteId`) REFERENCES `quote` (`quoteid`), + CONSTRAINT `quoteresponseduplicatecheck_quoteresponseid_foreign` FOREIGN KEY (`quoteResponseId`) REFERENCES `quoteResponse` (`quoteresponseid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `quoteResponseIlpPacket` +-- + +DROP TABLE IF EXISTS `quoteResponseIlpPacket`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `quoteResponseIlpPacket` ( + `quoteResponseId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `value` text NOT NULL COMMENT 'ilpPacket returned from Payee in response to a quote request', + PRIMARY KEY (`quoteResponseId`), + CONSTRAINT `quoteresponseilppacket_quoteresponseid_foreign` FOREIGN KEY (`quoteResponseId`) REFERENCES `quoteResponse` (`quoteresponseid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Temporary view structure for view `quoteResponseView` +-- + +DROP TABLE IF EXISTS `quoteResponseView`; +/*!50001 DROP VIEW IF EXISTS `quoteResponseView`*/; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8mb4; +/*!50001 CREATE VIEW `quoteResponseView` AS SELECT + 1 AS `quoteResponseId`, + 1 AS `quoteId`, + 1 AS `transferAmountCurrencyId`, + 1 AS `transferAmount`, + 1 AS `payeeReceiveAmountCurrencyId`, + 1 AS `payeeReceiveAmount`, + 1 AS `payeeFspFeeCurrencyId`, + 1 AS `payeeFspFeeAmount`, + 1 AS `payeeFspCommissionCurrencyId`, + 1 AS `payeeFspCommissionAmount`, + 1 AS `ilpCondition`, + 1 AS `responseExpirationDate`, + 1 AS `isValid`, + 1 AS `createdDate`, + 1 AS `ilpPacket`, + 1 AS `longitude`, + 1 AS `latitude`*/; +SET character_set_client = @saved_cs_client; + +-- +-- Temporary view structure for view `quoteView` +-- + +DROP TABLE IF EXISTS `quoteView`; +/*!50001 DROP VIEW IF EXISTS `quoteView`*/; +SET @saved_cs_client = @@character_set_client; +SET character_set_client = utf8mb4; +/*!50001 CREATE VIEW `quoteView` AS SELECT + 1 AS `quoteId`, + 1 AS `transactionReferenceId`, + 1 AS `transactionRequestId`, + 1 AS `note`, + 1 AS `expirationDate`, + 1 AS `transactionInitiator`, + 1 AS `transactionInitiatorType`, + 1 AS `transactionScenario`, + 1 AS `balanceOfPaymentsId`, + 1 AS `transactionSubScenario`, + 1 AS `amountType`, + 1 AS `amount`, + 1 AS `currency`*/; +SET character_set_client = @saved_cs_client; + +-- +-- Table structure for table `segment` +-- + +DROP TABLE IF EXISTS `segment`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `segment` ( + `segmentId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `segmentType` varchar(50) NOT NULL, + `enumeration` int(11) NOT NULL DEFAULT '0', + `tableName` varchar(50) NOT NULL, + `value` bigint(20) NOT NULL, + `changedDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`segmentId`), + KEY `segment_keys_index` (`segmentType`,`enumeration`,`tableName`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlement` +-- + +DROP TABLE IF EXISTS `settlement`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `settlement` ( + `settlementId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `reason` varchar(512) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `currentStateChangeId` bigint(20) unsigned DEFAULT NULL, + PRIMARY KEY (`settlementId`), + KEY `settlement_currentstatechangeid_foreign` (`currentStateChangeId`), + CONSTRAINT `settlement_currentstatechangeid_foreign` FOREIGN KEY (`currentStateChangeId`) REFERENCES `settlementStateChange` (`settlementstatechangeid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementParticipantCurrency` +-- + +DROP TABLE IF EXISTS `settlementParticipantCurrency`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `settlementParticipantCurrency` ( + `settlementParticipantCurrencyId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `settlementId` bigint(20) unsigned NOT NULL, + `participantCurrencyId` int(10) unsigned NOT NULL, + `netAmount` decimal(18,4) NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `currentStateChangeId` bigint(20) unsigned DEFAULT NULL, + `settlementTransferId` varchar(36) DEFAULT NULL, + PRIMARY KEY (`settlementParticipantCurrencyId`), + KEY `settlementparticipantcurrency_settlementid_index` (`settlementId`), + KEY `settlementparticipantcurrency_participantcurrencyid_index` (`participantCurrencyId`), + KEY `settlementparticipantcurrency_settlementtransferid_index` (`settlementTransferId`), + KEY `spc_currentstatechangeid_foreign` (`currentStateChangeId`), + CONSTRAINT `settlementparticipantcurrency_participantcurrencyid_foreign` FOREIGN KEY (`participantCurrencyId`) REFERENCES `participantCurrency` (`participantcurrencyid`), + CONSTRAINT `settlementparticipantcurrency_settlementid_foreign` FOREIGN KEY (`settlementId`) REFERENCES `settlement` (`settlementid`), + CONSTRAINT `spc_currentstatechangeid_foreign` FOREIGN KEY (`currentStateChangeId`) REFERENCES `settlementParticipantCurrencyStateChange` (`settlementparticipantcurrencystatechangeid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementParticipantCurrencyStateChange` +-- + +DROP TABLE IF EXISTS `settlementParticipantCurrencyStateChange`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `settlementParticipantCurrencyStateChange` ( + `settlementParticipantCurrencyStateChangeId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `settlementParticipantCurrencyId` bigint(20) unsigned NOT NULL, + `settlementStateId` varchar(50) NOT NULL, + `reason` varchar(512) DEFAULT NULL, + `externalReference` varchar(50) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`settlementParticipantCurrencyStateChangeId`), + KEY `spcsc_settlementparticipantcurrencyid_index` (`settlementParticipantCurrencyId`), + KEY `spcsc_settlementstateid_index` (`settlementStateId`), + CONSTRAINT `spcsc_settlementparticipantcurrencyid_foreign` FOREIGN KEY (`settlementParticipantCurrencyId`) REFERENCES `settlementParticipantCurrency` (`settlementparticipantcurrencyid`), + CONSTRAINT `spcsc_settlementstateid_foreign` FOREIGN KEY (`settlementStateId`) REFERENCES `settlementState` (`settlementstateid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementSettlementWindow` +-- + +DROP TABLE IF EXISTS `settlementSettlementWindow`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `settlementSettlementWindow` ( + `settlementSettlementWindowId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `settlementId` bigint(20) unsigned NOT NULL, + `settlementWindowId` bigint(20) unsigned NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`settlementSettlementWindowId`), + UNIQUE KEY `settlementsettlementwindow_unique` (`settlementId`,`settlementWindowId`), + KEY `settlementsettlementwindow_settlementid_index` (`settlementId`), + KEY `settlementsettlementwindow_settlementwindowid_index` (`settlementWindowId`), + CONSTRAINT `settlementsettlementwindow_settlementid_foreign` FOREIGN KEY (`settlementId`) REFERENCES `settlement` (`settlementid`), + CONSTRAINT `settlementsettlementwindow_settlementwindowid_foreign` FOREIGN KEY (`settlementWindowId`) REFERENCES `settlementWindow` (`settlementwindowid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementState` +-- + +DROP TABLE IF EXISTS `settlementState`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `settlementState` ( + `settlementStateId` varchar(50) NOT NULL, + `enumeration` varchar(50) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`settlementStateId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementStateChange` +-- + +DROP TABLE IF EXISTS `settlementStateChange`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `settlementStateChange` ( + `settlementStateChangeId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `settlementId` bigint(20) unsigned NOT NULL, + `settlementStateId` varchar(50) NOT NULL, + `reason` varchar(512) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`settlementStateChangeId`), + KEY `settlementstatechange_settlementid_index` (`settlementId`), + KEY `settlementstatechange_settlementstateid_index` (`settlementStateId`), + CONSTRAINT `settlementstatechange_settlementid_foreign` FOREIGN KEY (`settlementId`) REFERENCES `settlement` (`settlementid`), + CONSTRAINT `settlementstatechange_settlementstateid_foreign` FOREIGN KEY (`settlementStateId`) REFERENCES `settlementState` (`settlementstateid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementTransferParticipant` +-- + +DROP TABLE IF EXISTS `settlementTransferParticipant`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `settlementTransferParticipant` ( + `settlementTransferParticipantId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `settlementId` bigint(20) unsigned NOT NULL, + `settlementWindowId` bigint(20) unsigned NOT NULL, + `participantCurrencyId` int(10) unsigned NOT NULL, + `transferParticipantRoleTypeId` int(10) unsigned NOT NULL, + `ledgerEntryTypeId` int(10) unsigned NOT NULL, + `amount` decimal(18,4) NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`settlementTransferParticipantId`), + KEY `settlementtransferparticipant_settlementid_index` (`settlementId`), + KEY `settlementtransferparticipant_settlementwindowid_index` (`settlementWindowId`), + KEY `settlementtransferparticipant_participantcurrencyid_index` (`participantCurrencyId`), + KEY `stp_transferparticipantroletypeid_index` (`transferParticipantRoleTypeId`), + KEY `settlementtransferparticipant_ledgerentrytypeid_index` (`ledgerEntryTypeId`), + CONSTRAINT `settlementtransferparticipant_ledgerentrytypeid_foreign` FOREIGN KEY (`ledgerEntryTypeId`) REFERENCES `ledgerEntryType` (`ledgerentrytypeid`), + CONSTRAINT `settlementtransferparticipant_participantcurrencyid_foreign` FOREIGN KEY (`participantCurrencyId`) REFERENCES `participantCurrency` (`participantcurrencyid`), + CONSTRAINT `settlementtransferparticipant_settlementid_foreign` FOREIGN KEY (`settlementId`) REFERENCES `settlement` (`settlementid`), + CONSTRAINT `settlementtransferparticipant_settlementwindowid_foreign` FOREIGN KEY (`settlementWindowId`) REFERENCES `settlementWindow` (`settlementwindowid`), + CONSTRAINT `stp_transferparticipantroletypeid_foreign` FOREIGN KEY (`transferParticipantRoleTypeId`) REFERENCES `transferParticipantRoleType` (`transferparticipantroletypeid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementWindow` +-- + +DROP TABLE IF EXISTS `settlementWindow`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `settlementWindow` ( + `settlementWindowId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `reason` varchar(512) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `currentStateChangeId` bigint(20) unsigned DEFAULT NULL, + PRIMARY KEY (`settlementWindowId`), + KEY `settlementwindow_currentstatechangeid_foreign` (`currentStateChangeId`), + CONSTRAINT `settlementwindow_currentstatechangeid_foreign` FOREIGN KEY (`currentStateChangeId`) REFERENCES `settlementWindowStateChange` (`settlementwindowstatechangeid`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementWindowState` +-- + +DROP TABLE IF EXISTS `settlementWindowState`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `settlementWindowState` ( + `settlementWindowStateId` varchar(50) NOT NULL, + `enumeration` varchar(50) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`settlementWindowStateId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementWindowStateChange` +-- + +DROP TABLE IF EXISTS `settlementWindowStateChange`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `settlementWindowStateChange` ( + `settlementWindowStateChangeId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `settlementWindowId` bigint(20) unsigned NOT NULL, + `settlementWindowStateId` varchar(50) NOT NULL, + `reason` varchar(512) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`settlementWindowStateChangeId`), + KEY `settlementwindowstatechange_settlementwindowid_index` (`settlementWindowId`), + KEY `settlementwindowstatechange_settlementwindowstateid_index` (`settlementWindowStateId`), + CONSTRAINT `settlementwindowstatechange_settlementwindowid_foreign` FOREIGN KEY (`settlementWindowId`) REFERENCES `settlementWindow` (`settlementwindowid`), + CONSTRAINT `settlementwindowstatechange_settlementwindowstateid_foreign` FOREIGN KEY (`settlementWindowStateId`) REFERENCES `settlementWindowState` (`settlementwindowstateid`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `token` +-- + +DROP TABLE IF EXISTS `token`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `token` ( + `tokenId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `participantId` int(10) unsigned NOT NULL, + `value` varchar(256) NOT NULL, + `expiration` bigint(20) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`tokenId`), + UNIQUE KEY `token_value_unique` (`value`), + KEY `token_participantid_index` (`participantId`), + CONSTRAINT `token_participantid_foreign` FOREIGN KEY (`participantId`) REFERENCES `participant` (`participantid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transactionInitiator` +-- + +DROP TABLE IF EXISTS `transactionInitiator`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `transactionInitiator` ( + `transactionInitiatorId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(256) NOT NULL, + `description` varchar(1024) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`transactionInitiatorId`), + UNIQUE KEY `transactioninitiator_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transactionInitiatorType` +-- + +DROP TABLE IF EXISTS `transactionInitiatorType`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `transactionInitiatorType` ( + `transactionInitiatorTypeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(256) NOT NULL, + `description` varchar(1024) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`transactionInitiatorTypeId`), + UNIQUE KEY `transactioninitiatortype_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transactionReference` +-- + +DROP TABLE IF EXISTS `transactionReference`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `transactionReference` ( + `transactionReferenceId` varchar(36) NOT NULL COMMENT 'Common ID (decided by the Payer FSP) between the FSPs for the future transaction object', + `quoteId` varchar(36) DEFAULT NULL COMMENT 'Common ID between the FSPs for the quote object, decided by the Payer FSP', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System row creation timestamp', + PRIMARY KEY (`transactionReferenceId`), + KEY `transactionreference_quoteid_index` (`quoteId`), + CONSTRAINT `transactionreference_quoteid_foreign` FOREIGN KEY (`quoteId`) REFERENCES `quoteDuplicateCheck` (`quoteid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transactionScenario` +-- + +DROP TABLE IF EXISTS `transactionScenario`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `transactionScenario` ( + `transactionScenarioId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(256) NOT NULL, + `description` varchar(1024) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`transactionScenarioId`), + UNIQUE KEY `transactionscenario_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transactionSubScenario` +-- + +DROP TABLE IF EXISTS `transactionSubScenario`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `transactionSubScenario` ( + `transactionSubScenarioId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(256) NOT NULL, + `description` varchar(1024) DEFAULT NULL COMMENT 'Possible sub-scenario, defined locally within the scheme', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`transactionSubScenarioId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transfer` +-- + +DROP TABLE IF EXISTS `transfer`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `transfer` ( + `transferId` varchar(36) NOT NULL, + `amount` decimal(18,4) NOT NULL, + `currencyId` varchar(3) NOT NULL, + `ilpCondition` varchar(256) NOT NULL, + `expirationDate` datetime NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferId`), + KEY `transfer_currencyid_index` (`currencyId`), + CONSTRAINT `transfer_currencyid_foreign` FOREIGN KEY (`currencyId`) REFERENCES `currency` (`currencyid`), + CONSTRAINT `transfer_transferid_foreign` FOREIGN KEY (`transferId`) REFERENCES `transferDuplicateCheck` (`transferid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferDuplicateCheck` +-- + +DROP TABLE IF EXISTS `transferDuplicateCheck`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `transferDuplicateCheck` ( + `transferId` varchar(36) NOT NULL, + `hash` varchar(256) NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferError` +-- + +DROP TABLE IF EXISTS `transferError`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `transferError` ( + `transferId` varchar(36) NOT NULL, + `transferStateChangeId` bigint(20) unsigned NOT NULL, + `errorCode` int(10) unsigned NOT NULL, + `errorDescription` varchar(128) NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferId`), + KEY `transfererror_transferstatechangeid_foreign` (`transferStateChangeId`), + CONSTRAINT `transfererror_transferstatechangeid_foreign` FOREIGN KEY (`transferStateChangeId`) REFERENCES `transferStateChange` (`transferstatechangeid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferErrorDuplicateCheck` +-- + +DROP TABLE IF EXISTS `transferErrorDuplicateCheck`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `transferErrorDuplicateCheck` ( + `transferId` varchar(36) NOT NULL, + `hash` varchar(256) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferId`), + CONSTRAINT `transfererrorduplicatecheck_transferid_foreign` FOREIGN KEY (`transferId`) REFERENCES `transfer` (`transferid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferExtension` +-- + +DROP TABLE IF EXISTS `transferExtension`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `transferExtension` ( + `transferExtensionId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `transferId` varchar(36) NOT NULL, + `key` varchar(128) NOT NULL, + `value` text NOT NULL, + `isFulfilment` tinyint(1) NOT NULL DEFAULT '0', + `isError` tinyint(1) NOT NULL DEFAULT '0', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferExtensionId`), + KEY `transferextension_transferid_foreign` (`transferId`), + CONSTRAINT `transferextension_transferid_foreign` FOREIGN KEY (`transferId`) REFERENCES `transfer` (`transferid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferFulfilment` +-- + +DROP TABLE IF EXISTS `transferFulfilment`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `transferFulfilment` ( + `transferId` varchar(36) NOT NULL, + `ilpFulfilment` varchar(256) DEFAULT NULL, + `completedDate` datetime NOT NULL, + `isValid` tinyint(1) DEFAULT NULL, + `settlementWindowId` bigint(20) unsigned DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferId`), + KEY `transferfulfilment_settlementwindowid_foreign` (`settlementWindowId`), + CONSTRAINT `transferfulfilment_settlementwindowid_foreign` FOREIGN KEY (`settlementWindowId`) REFERENCES `settlementWindow` (`settlementwindowid`), + CONSTRAINT `transferfulfilment_transferid_foreign` FOREIGN KEY (`transferId`) REFERENCES `transferFulfilmentDuplicateCheck` (`transferid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferFulfilmentDuplicateCheck` +-- + +DROP TABLE IF EXISTS `transferFulfilmentDuplicateCheck`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `transferFulfilmentDuplicateCheck` ( + `transferId` varchar(36) NOT NULL, + `hash` varchar(256) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferId`), + CONSTRAINT `transferfulfilmentduplicatecheck_transferid_foreign` FOREIGN KEY (`transferId`) REFERENCES `transfer` (`transferid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferParticipant` +-- + +DROP TABLE IF EXISTS `transferParticipant`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `transferParticipant` ( + `transferParticipantId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `transferId` varchar(36) NOT NULL, + `participantCurrencyId` int(10) unsigned NOT NULL, + `transferParticipantRoleTypeId` int(10) unsigned NOT NULL, + `ledgerEntryTypeId` int(10) unsigned NOT NULL, + `amount` decimal(18,4) NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferParticipantId`), + KEY `transferparticipant_transferid_index` (`transferId`), + KEY `transferparticipant_participantcurrencyid_index` (`participantCurrencyId`), + KEY `transferparticipant_transferparticipantroletypeid_index` (`transferParticipantRoleTypeId`), + KEY `transferparticipant_ledgerentrytypeid_index` (`ledgerEntryTypeId`), + CONSTRAINT `transferparticipant_ledgerentrytypeid_foreign` FOREIGN KEY (`ledgerEntryTypeId`) REFERENCES `ledgerEntryType` (`ledgerentrytypeid`), + CONSTRAINT `transferparticipant_participantcurrencyid_foreign` FOREIGN KEY (`participantCurrencyId`) REFERENCES `participantCurrency` (`participantcurrencyid`), + CONSTRAINT `transferparticipant_transferid_foreign` FOREIGN KEY (`transferId`) REFERENCES `transfer` (`transferid`), + CONSTRAINT `transferparticipant_transferparticipantroletypeid_foreign` FOREIGN KEY (`transferParticipantRoleTypeId`) REFERENCES `transferParticipantRoleType` (`transferparticipantroletypeid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferParticipantRoleType` +-- + +DROP TABLE IF EXISTS `transferParticipantRoleType`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `transferParticipantRoleType` ( + `transferParticipantRoleTypeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferParticipantRoleTypeId`), + UNIQUE KEY `transferparticipantroletype_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferRules` +-- + +DROP TABLE IF EXISTS `transferRules`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `transferRules` ( + `transferRulesId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(128) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `rule` text NOT NULL, + `enabled` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferRulesId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferState` +-- + +DROP TABLE IF EXISTS `transferState`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `transferState` ( + `transferStateId` varchar(50) NOT NULL, + `enumeration` varchar(50) NOT NULL COMMENT 'transferState associated to the Mojaloop API', + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferStateId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferStateChange` +-- + +DROP TABLE IF EXISTS `transferStateChange`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `transferStateChange` ( + `transferStateChangeId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `transferId` varchar(36) NOT NULL, + `transferStateId` varchar(50) NOT NULL, + `reason` varchar(512) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferStateChangeId`), + KEY `transferstatechange_transferid_index` (`transferId`), + KEY `transferstatechange_transferstateid_index` (`transferStateId`), + CONSTRAINT `transferstatechange_transferid_foreign` FOREIGN KEY (`transferId`) REFERENCES `transfer` (`transferid`), + CONSTRAINT `transferstatechange_transferstateid_foreign` FOREIGN KEY (`transferStateId`) REFERENCES `transferState` (`transferstateid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferTimeout` +-- + +DROP TABLE IF EXISTS `transferTimeout`; +/*!40101 SET @saved_cs_client = @@character_set_client */; + SET character_set_client = utf8mb4 ; +CREATE TABLE `transferTimeout` ( + `transferTimeoutId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `transferId` varchar(36) NOT NULL, + `expirationDate` datetime NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferTimeoutId`), + UNIQUE KEY `transfertimeout_transferid_unique` (`transferId`), + CONSTRAINT `transfertimeout_transferid_foreign` FOREIGN KEY (`transferId`) REFERENCES `transfer` (`transferid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Final view structure for view `quotePartyView` +-- + +/*!50001 DROP VIEW IF EXISTS `quotePartyView`*/; +/*!50001 SET @saved_cs_client = @@character_set_client */; +/*!50001 SET @saved_cs_results = @@character_set_results */; +/*!50001 SET @saved_col_connection = @@collation_connection */; +/*!50001 SET character_set_client = utf8 */; +/*!50001 SET character_set_results = utf8 */; +/*!50001 SET collation_connection = utf8_general_ci */; +/*!50001 CREATE ALGORITHM=UNDEFINED */ +/*!50013 DEFINER=`central_ledger`@`%` SQL SECURITY DEFINER */ +/*!50001 VIEW `quotePartyView` AS select `qp`.`quoteId` AS `quoteId`,`qp`.`quotePartyId` AS `quotePartyId`,`pt`.`name` AS `partyType`,`pit`.`name` AS `identifierType`,`qp`.`partyIdentifierValue` AS `partyIdentifierValue`,`spit`.`name` AS `partySubIdOrType`,`qp`.`fspId` AS `fspId`,`qp`.`merchantClassificationCode` AS `merchantClassificationCode`,`qp`.`partyName` AS `partyName`,`p`.`firstName` AS `firstName`,`p`.`lastName` AS `lastName`,`p`.`middleName` AS `middleName`,`p`.`dateOfBirth` AS `dateOfBirth`,`gc`.`longitude` AS `longitude`,`gc`.`latitude` AS `latitude` from (((((`quoteParty` `qp` join `partyType` `pt` on((`pt`.`partyTypeId` = `qp`.`partyTypeId`))) join `partyIdentifierType` `pit` on((`pit`.`partyIdentifierTypeId` = `qp`.`partyIdentifierTypeId`))) left join `party` `p` on((`p`.`quotePartyId` = `qp`.`quotePartyId`))) left join `partyIdentifierType` `spit` on((`spit`.`partyIdentifierTypeId` = `qp`.`partySubIdOrTypeId`))) left join `geoCode` `gc` on((`gc`.`quotePartyId` = `qp`.`quotePartyId`))) */; +/*!50001 SET character_set_client = @saved_cs_client */; +/*!50001 SET character_set_results = @saved_cs_results */; +/*!50001 SET collation_connection = @saved_col_connection */; + +-- +-- Final view structure for view `quoteResponseView` +-- + +/*!50001 DROP VIEW IF EXISTS `quoteResponseView`*/; +/*!50001 SET @saved_cs_client = @@character_set_client */; +/*!50001 SET @saved_cs_results = @@character_set_results */; +/*!50001 SET @saved_col_connection = @@collation_connection */; +/*!50001 SET character_set_client = utf8 */; +/*!50001 SET character_set_results = utf8 */; +/*!50001 SET collation_connection = utf8_general_ci */; +/*!50001 CREATE ALGORITHM=UNDEFINED */ +/*!50013 DEFINER=`central_ledger`@`%` SQL SECURITY DEFINER */ +/*!50001 VIEW `quoteResponseView` AS select `qr`.`quoteResponseId` AS `quoteResponseId`,`qr`.`quoteId` AS `quoteId`,`qr`.`transferAmountCurrencyId` AS `transferAmountCurrencyId`,`qr`.`transferAmount` AS `transferAmount`,`qr`.`payeeReceiveAmountCurrencyId` AS `payeeReceiveAmountCurrencyId`,`qr`.`payeeReceiveAmount` AS `payeeReceiveAmount`,`qr`.`payeeFspFeeCurrencyId` AS `payeeFspFeeCurrencyId`,`qr`.`payeeFspFeeAmount` AS `payeeFspFeeAmount`,`qr`.`payeeFspCommissionCurrencyId` AS `payeeFspCommissionCurrencyId`,`qr`.`payeeFspCommissionAmount` AS `payeeFspCommissionAmount`,`qr`.`ilpCondition` AS `ilpCondition`,`qr`.`responseExpirationDate` AS `responseExpirationDate`,`qr`.`isValid` AS `isValid`,`qr`.`createdDate` AS `createdDate`,`qrilp`.`value` AS `ilpPacket`,`gc`.`longitude` AS `longitude`,`gc`.`latitude` AS `latitude` from ((((`quoteResponse` `qr` join `quoteResponseIlpPacket` `qrilp` on((`qrilp`.`quoteResponseId` = `qr`.`quoteResponseId`))) join `quoteParty` `qp` on((`qp`.`quoteId` = `qr`.`quoteId`))) join `partyType` `pt` on((`pt`.`partyTypeId` = `qp`.`partyTypeId`))) left join `geoCode` `gc` on((`gc`.`quotePartyId` = `qp`.`quotePartyId`))) where (`pt`.`name` = 'PAYEE') */; +/*!50001 SET character_set_client = @saved_cs_client */; +/*!50001 SET character_set_results = @saved_cs_results */; +/*!50001 SET collation_connection = @saved_col_connection */; + +-- +-- Final view structure for view `quoteView` +-- + +/*!50001 DROP VIEW IF EXISTS `quoteView`*/; +/*!50001 SET @saved_cs_client = @@character_set_client */; +/*!50001 SET @saved_cs_results = @@character_set_results */; +/*!50001 SET @saved_col_connection = @@collation_connection */; +/*!50001 SET character_set_client = utf8 */; +/*!50001 SET character_set_results = utf8 */; +/*!50001 SET collation_connection = utf8_general_ci */; +/*!50001 CREATE ALGORITHM=UNDEFINED */ +/*!50013 DEFINER=`central_ledger`@`%` SQL SECURITY DEFINER */ +/*!50001 VIEW `quoteView` AS select `q`.`quoteId` AS `quoteId`,`q`.`transactionReferenceId` AS `transactionReferenceId`,`q`.`transactionRequestId` AS `transactionRequestId`,`q`.`note` AS `note`,`q`.`expirationDate` AS `expirationDate`,`ti`.`name` AS `transactionInitiator`,`tit`.`name` AS `transactionInitiatorType`,`ts`.`name` AS `transactionScenario`,`q`.`balanceOfPaymentsId` AS `balanceOfPaymentsId`,`tss`.`name` AS `transactionSubScenario`,`amt`.`name` AS `amountType`,`q`.`amount` AS `amount`,`q`.`currencyId` AS `currency` from (((((`quote` `q` join `transactionInitiator` `ti` on((`ti`.`transactionInitiatorId` = `q`.`transactionInitiatorId`))) join `transactionInitiatorType` `tit` on((`tit`.`transactionInitiatorTypeId` = `q`.`transactionInitiatorTypeId`))) join `transactionScenario` `ts` on((`ts`.`transactionScenarioId` = `q`.`transactionScenarioId`))) join `amountType` `amt` on((`amt`.`amountTypeId` = `q`.`amountTypeId`))) left join `transactionSubScenario` `tss` on((`tss`.`transactionSubScenarioId` = `q`.`transactionSubScenarioId`))) */; +/*!50001 SET character_set_client = @saved_cs_client */; +/*!50001 SET character_set_results = @saved_cs_results */; +/*!50001 SET collation_connection = @saved_col_connection */; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2019-10-14 21:12:45 diff --git a/docs/technical/central-bulk-transfers/assets/database/central-ledger-schema-DBeaver.erd b/docs/technical/central-bulk-transfers/assets/database/central-ledger-schema-DBeaver.erd new file mode 100644 index 000000000..12059bab5 --- /dev/null +++ b/docs/technical/central-bulk-transfers/assets/database/central-ledger-schema-DBeaver.erd @@ -0,0 +1,235 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + COLOR LEGEND: +Green - subject specific entity +Gray - transfer specific entity +Brown - bulk transfer entity +Red - settlement specific entity +Blue - lookup entity +Cyan - impl. specific +Yellow - tbd + + \ No newline at end of file diff --git a/docs/technical/central-bulk-transfers/assets/database/central-ledger-schema.png b/docs/technical/central-bulk-transfers/assets/database/central-ledger-schema.png new file mode 100644 index 000000000..6afdaf2ea Binary files /dev/null and b/docs/technical/central-bulk-transfers/assets/database/central-ledger-schema.png differ diff --git a/docs/technical/central-bulk-transfers/assets/diagrams/architecture/Figure60-Example-Bulk-Transfer-Process-Spec1.0.png b/docs/technical/central-bulk-transfers/assets/diagrams/architecture/Figure60-Example-Bulk-Transfer-Process-Spec1.0.png new file mode 100644 index 000000000..aa361a64a Binary files /dev/null and b/docs/technical/central-bulk-transfers/assets/diagrams/architecture/Figure60-Example-Bulk-Transfer-Process-Spec1.0.png differ diff --git a/docs/technical/central-bulk-transfers/assets/diagrams/architecture/bulk-transfer-arch-flows.svg b/docs/technical/central-bulk-transfers/assets/diagrams/architecture/bulk-transfer-arch-flows.svg new file mode 100644 index 000000000..b22f23afe --- /dev/null +++ b/docs/technical/central-bulk-transfers/assets/diagrams/architecture/bulk-transfer-arch-flows.svg @@ -0,0 +1,3 @@ + + +
1.7 Increment Position (fsp1)
[Not supported by viewer]
1.6 Increment
Position (fsp1)

[Not supported by viewer]
Fulfil
Sucess
[Not supported by viewer]
2.6 Fulfil
Success
[Not supported by viewer]
<alt> 2.6  Fulfil Reject
[Not supported by viewer]
Fulfil
Reject
[Not supported by viewer]
<alt> 2.7 Decrement
Position (fsp1)

[Not supported by viewer]
Central - Services
<font style="font-size: 18px">Central - Services</font>
3.0 Reject
[Not supported by viewer]
1.0 Bulk Transfer 
Request

[Not supported by viewer]
3.1 Decrement
Position (fsp1)

[Not supported by viewer]
ML-Adapter
[Not supported by viewer]
Bulk Transfer
Bulk Transfer<br>
Notification
Event Handler
[Not supported by viewer]
notifications
notifications
FSP1
(Payer)

[Not supported by viewer]
FSP2
(Payee)
[Not supported by viewer]
1.1
Prepare Request
[Not supported by viewer]
1.2 Accpeted
(202)
[Not supported by viewer]
Bulk Transfer
Bulk Transfer<br>
2.0 Bulk Fulfil 
Success / 
Reject

[Not supported by viewer]
bulk fulfil
bulk fulfil
2.7 Decrement
Position (fsp2)

[Not supported by viewer]
2.1 Bulk Fulfil 
Success / Reject

[Not supported by viewer]
2.2 OK
(202)
[Not supported by viewer]
OK (200)
[Not supported by viewer]
OK (200)
[Not supported by viewer]
Transfer Timeout
Handler
[Not supported by viewer]
2.12 Bulk Fulfil Notify Callback /
<alt> 2.12 Bulk Reject Response (Fulfil reject) /
3.6 Bulk Reject Response (Timeout) /
<alt> 1.8 Bulk Prepare Failure 
[Not supported by viewer]
1.12 Bulk Prepare Notify /
2.13 Bulk Fulfil Notify /
<alt> 2.13 Bulk Reject Response (Fulfil reject)
3.7 Bulk Reject Response (Timeout)

[Not supported by viewer]
positions
positions<br>
bulk processing
bulk processing
BulkFulfil
Handler
[Not supported by viewer]
1.3 Bulk Prepare Consume
[Not supported by viewer]
BulkPrepare
Handler
BulkPrepare<br>Handler
 prepare
 prepare
fulfil
fulfil
BulkProcessing Handler
BulkProcessing Handler<br>
1.4 Individual Prepare
[Not supported by viewer]
1.5 Individual Prepare
[Not supported by viewer]
1.5
 / 1.9 / 2.9 / 3.3
 Individual Notify
[Not supported by viewer]
1.8 / 2.8 / 3.2 Individual
Notify
[Not supported by viewer]
1.6 / 1.10 / 2.10 / 3.4 Bulk Notify
[Not supported by viewer]
1.7 / 1.11 / 2.11 / 3.5 Bulk Notify
[Not supported by viewer]
2.3 Bulk Fulfil Consume
[Not supported by viewer]
2.4 Individual
Fulfil
[Not supported by viewer]
2.5 Individual
Fulfil
[Not supported by viewer]
FulfilHandler
FulfilHandler
Success/
Reject
[Not supported by viewer]
PositionHandler
PositionHandler
PrepareHandler
PrepareHandler
Object Store
[Not supported by viewer]
<alt> 1.4 Bulk Prepare Failure
[Not supported by viewer]
<alt> 1.6 Individual Prepare Failure
[Not supported by viewer]
<alt> 1.8 Individual
Failure Notify

[Not supported by viewer]
<alt> 2.4 Bulk Fulfil Failure
[Not supported by viewer]
<alt> 2.6 Individual Fulfil Failure
[Not supported by viewer]
bulk prepare
bulk prepare
Object Store
[Not supported by viewer]
Object Store
[Not supported by viewer]
\ No newline at end of file diff --git a/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.1.0-bulk-prepare-overview.plantuml b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.1.0-bulk-prepare-overview.plantuml new file mode 100644 index 000000000..5bdd8119f --- /dev/null +++ b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.1.0-bulk-prepare-overview.plantuml @@ -0,0 +1,217 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Samuel Kummary + -------------- + ******'/ + +@startuml +' declare title +title 1.1.0. DFSP1 sends a Bulk Prepare Transfer request to DFSP2 + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +actor "DFSP1\nPayer" as DFSP1 +actor "DFSP2\nPayee" as DFSP2 +boundary "Bulk API Adapter" as BULK_API +control "Bulk API Notification \nHandler" as NOTIFY_HANDLER +collections "mojaloop-\nobject-store\n(**MLOS**)" as OBJECT_STORE +boundary "Central Service API" as CSAPI +collections "topic-\nbulk-prepare" as TOPIC_BULK_PREPARE +control "Bulk Prepare\nHandler" as BULK_PREP_HANDLER +collections "topic-\ntransfer-prepare" as TOPIC_TRANSFER_PREPARE +control "Prepare Handler" as PREP_HANDLER +collections "topic-\ntransfer-position" as TOPIC_TRANSFER_POSITION +control "Position Handler" as POS_HANDLER +collections "topic-\nbulk-processing" as TOPIC_BULK_PROCESSING +control "Bulk Processing\nHandler" as BULK_PROC_HANDLER +collections "topic-\nnotifications" as TOPIC_NOTIFICATIONS + +box "Financial Service Providers" #lightGray + participant DFSP1 + participant DFSP2 +end box + +box "Bulk API Adapter Service" #LightBlue + participant BULK_API + participant NOTIFY_HANDLER +end box + +box "Central Service" #LightYellow + participant OBJECT_STORE + participant CSAPI + participant TOPIC_BULK_PREPARE + participant BULK_PREP_HANDLER + participant TOPIC_TRANSFER_PREPARE + participant PREP_HANDLER + participant TOPIC_TRANSFER_POSITION + participant POS_HANDLER + participant TOPIC_BULK_PROCESSING + participant BULK_PROC_HANDLER + participant TOPIC_NOTIFICATIONS +end box + +' start flow +activate NOTIFY_HANDLER +activate BULK_PREP_HANDLER +activate PREP_HANDLER +activate POS_HANDLER +activate BULK_PROC_HANDLER +group DFSP1 sends a Bulk Prepare Transfer request to DFSP2 + note right of DFSP1 #yellow + Headers - transferHeaders: { + Content-Length: , + Content-Type: , + Date: , + FSPIOP-Source: , + FSPIOP-Destination: , + FSPIOP-Encryption: , + FSPIOP-Signature: , + FSPIOP-URI: , + FSPIOP-HTTP-Method: + } + + Payload - bulkTransferMessage: + { + bulkTransferId: , + bulkQuoteId: , + payeeFsp: , + payerFsp: , + individualTransfers: [ + { + transferId: , + transferAmount: + { + currency: , + amount: + }, + ilpPacket: , + condition: , + extensionList: { extension: [ + { key: , value: } + ] } + } + ], + extensionList: { extension: [ + { key: , value: } + ] }, + expiration: + } + end note + DFSP1 ->> BULK_API: POST - /bulkTransfers + activate BULK_API + BULK_API -> BULK_API: Validate incoming message\nError codes: 3000-3002, 3100-3107 + loop + BULK_API -> OBJECT_STORE: Persist individual transfers in the bulk to\nobject store: **MLOS.individualTransfers** + activate OBJECT_STORE + OBJECT_STORE --> BULK_API: Return messageId reference to the stored object(s) + deactivate OBJECT_STORE + end + note right of BULK_API #yellow + Message: + { + id: + to: , + from: , + type: "application/json" + content: { + headers: , + payload: { + bulkTransferId: , + bulkQuoteId": , + payerFsp: , + payeeFsp: , + expiration: , + hash: + } + }, + metadata: { + event: { + id: , + type: "bulk-prepare", + action: "bulk-prepare", + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + BULK_API -> TOPIC_BULK_PREPARE: Route & Publish Bulk Prepare event \nfor Payer\nError code: 2003 + activate TOPIC_BULK_PREPARE + TOPIC_BULK_PREPARE <-> TOPIC_BULK_PREPARE: Ensure event is replicated \nas configured (ACKS=all)\nError code: 2003 + TOPIC_BULK_PREPARE --> BULK_API: Respond replication acknowledgements \nhave been received + deactivate TOPIC_BULK_PREPARE + BULK_API -->> DFSP1: Respond HTTP - 202 (Accepted) + deactivate BULK_API + ||| + TOPIC_BULK_PREPARE <- BULK_PREP_HANDLER: Consume message + ref over TOPIC_BULK_PREPARE, BULK_PREP_HANDLER, TOPIC_TRANSFER_PREPARE: Bulk Prepare Handler Consume \n + alt Success + BULK_PREP_HANDLER -> TOPIC_TRANSFER_PREPARE: Produce (stream) single transfer message\nfor each individual transfer [loop] + else Failure + BULK_PREP_HANDLER --> TOPIC_NOTIFICATIONS: Produce single message for the entire bulk + end + ||| + TOPIC_TRANSFER_PREPARE <- PREP_HANDLER: Consume message + ref over TOPIC_TRANSFER_PREPARE, PREP_HANDLER, TOPIC_TRANSFER_POSITION: Prepare Handler Consume\n + alt Success + PREP_HANDLER -> TOPIC_TRANSFER_POSITION: Produce message + else Failure + PREP_HANDLER --> TOPIC_BULK_PROCESSING: Produce message + end + ||| + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume message + ref over TOPIC_TRANSFER_POSITION, POS_HANDLER, TOPIC_BULK_PROCESSING: Position Handler Consume\n + POS_HANDLER -> TOPIC_BULK_PROCESSING: Produce message + ||| + TOPIC_BULK_PROCESSING <- BULK_PROC_HANDLER: Consume message + ref over TOPIC_BULK_PROCESSING, BULK_PROC_HANDLER, TOPIC_NOTIFICATIONS: Bulk Processing Handler Consume\n + BULK_PROC_HANDLER -> OBJECT_STORE: Persist bulk message by destination to the\nobject store: **MLOS.bulkTransferResults** + activate OBJECT_STORE + OBJECT_STORE --> BULK_PROC_HANDLER: Return the reference to the stored \nnotification object(s): **messageId** + deactivate OBJECT_STORE + BULK_PROC_HANDLER -> TOPIC_NOTIFICATIONS: Send Bulk Prepare notification + ||| + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message + NOTIFY_HANDLER -> OBJECT_STORE: Retrieve bulk notification(s) by reference & destination:\n**MLOS.bulkTransferResults.messageId + destination** + activate OBJECT_STORE + OBJECT_STORE --> NOTIFY_HANDLER: Return notification(s) payload + deactivate OBJECT_STORE + ref over DFSP2, TOPIC_NOTIFICATIONS: Send notification to Participant (Payee)\n + NOTIFY_HANDLER -> DFSP2: Send Bulk Prepare notification to Payee + ||| +end +deactivate POS_HANDLER +deactivate BULK_PREP_HANDLER +deactivate PREP_HANDLER +deactivate BULK_PROC_HANDLER +deactivate NOTIFY_HANDLER +@enduml diff --git a/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.1.0-bulk-prepare-overview.svg b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.1.0-bulk-prepare-overview.svg new file mode 100644 index 000000000..b24804c17 --- /dev/null +++ b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.1.0-bulk-prepare-overview.svg @@ -0,0 +1,788 @@ + + + + + + + + + + + 1.1.0. DFSP1 sends a Bulk Prepare Transfer request to DFSP2 + + + + Financial Service Providers + + + + Bulk API Adapter Service + + + + Central Service + + + + + + + + + + DFSP1 + + + Payer + + + + + DFSP1 + + + Payer + + + + + DFSP2 + + + Payee + + + + + DFSP2 + + + Payee + + + + + Bulk API Adapter + + + + + Bulk API Adapter + + + + + Bulk API Notification + + + Handler + + + + + Bulk API Notification + + + Handler + + + + + + + mojaloop- + + + object-store + + + ( + + + MLOS + + + ) + + + + + mojaloop- + + + object-store + + + ( + + + MLOS + + + ) + + + Central Service API + + + + + Central Service API + + + + + + + topic- + + + bulk-prepare + + + + + topic- + + + bulk-prepare + + + Bulk Prepare + + + Handler + + + + + Bulk Prepare + + + Handler + + + + + + + topic- + + + transfer-prepare + + + + + topic- + + + transfer-prepare + + + Prepare Handler + + + + + Prepare Handler + + + + + + + topic- + + + transfer-position + + + + + topic- + + + transfer-position + + + Position Handler + + + + + Position Handler + + + + + + + topic- + + + bulk-processing + + + + + topic- + + + bulk-processing + + + Bulk Processing + + + Handler + + + + + Bulk Processing + + + Handler + + + + + + + topic- + + + notifications + + + + + topic- + + + notifications + + + + + + DFSP1 sends a Bulk Prepare Transfer request to DFSP2 + + + + + Headers - transferHeaders: { + + + Content-Length: <int>, + + + Content-Type: <string>, + + + Date: <date>, + + + FSPIOP-Source: <string>, + + + FSPIOP-Destination: <string>, + + + FSPIOP-Encryption: <string>, + + + FSPIOP-Signature: <string>, + + + FSPIOP-URI: <uri>, + + + FSPIOP-HTTP-Method: <string> + + + } + + + Payload - bulkTransferMessage: + + + { + + + bulkTransferId: <uuid>, + + + bulkQuoteId: <uuid>, + + + payeeFsp: <string>, + + + payerFsp: <string>, + + + individualTransfers: [ + + + { + + + transferId: <uuid>, + + + transferAmount: + + + { + + + currency: <string>, + + + amount: <string> + + + }, + + + ilpPacket: <string>, + + + condition: <string>, + + + extensionList: { extension: [ + + + { key: <string>, value: <string> } + + + ] } + + + } + + + ], + + + extensionList: { extension: [ + + + { key: <string>, value: <string> } + + + ] }, + + + expiration: <string> + + + } + + + + 1 + + + POST - /bulkTransfers + + + + + 2 + + + Validate incoming message + + + Error codes: + + + 3000-3002, 3100-3107 + + + + + loop + + + + + 3 + + + Persist individual transfers in the bulk to + + + object store: + + + MLOS.individualTransfers + + + + + 4 + + + Return messageId reference to the stored object(s) + + + + + Message: + + + { + + + id: <messageId> + + + to: <payeeFspName>, + + + from: <payerFspName>, + + + type: "application/json" + + + content: { + + + headers: <bulkTransferHeaders>, + + + payload: { + + + bulkTransferId: <uuid>, + + + bulkQuoteId": <uuid>, + + + payerFsp: <string>, + + + payeeFsp: <string>, + + + expiration: <timestamp>, + + + hash: <string> + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + type: "bulk-prepare", + + + action: "bulk-prepare", + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 5 + + + Route & Publish Bulk Prepare event + + + for Payer + + + Error code: + + + 2003 + + + + + 6 + + + Ensure event is replicated + + + as configured (ACKS=all) + + + Error code: + + + 2003 + + + + + 7 + + + Respond replication acknowledgements + + + have been received + + + + + 8 + + + Respond HTTP - 202 (Accepted) + + + + + 9 + + + Consume message + + + + + ref + + + Bulk Prepare Handler Consume + + + + + alt + + + [Success] + + + + + 10 + + + Produce (stream) single transfer message + + + for each individual transfer [loop] + + + + [Failure] + + + + + 11 + + + Produce single message for the entire bulk + + + + + 12 + + + Consume message + + + + + ref + + + Prepare Handler Consume + + + + + alt + + + [Success] + + + + + 13 + + + Produce message + + + + [Failure] + + + + + 14 + + + Produce message + + + + + 15 + + + Consume message + + + + + ref + + + Position Handler Consume + + + + + 16 + + + Produce message + + + + + 17 + + + Consume message + + + + + ref + + + Bulk Processing Handler Consume + + + + + 18 + + + Persist bulk message by destination to the + + + object store: + + + MLOS.bulkTransferResults + + + + + 19 + + + Return the reference to the stored + + + notification object(s): + + + messageId + + + + + 20 + + + Send Bulk Prepare notification + + + + + 21 + + + Consume message + + + + + 22 + + + Retrieve bulk notification(s) by reference & destination: + + + MLOS.bulkTransferResults.messageId + destination + + + + + 23 + + + Return notification(s) payload + + + + + ref + + + Send notification to Participant (Payee) + + + + + 24 + + + Send Bulk Prepare notification to Payee + + diff --git a/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.1.1-bulk-prepare-handler.plantuml b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.1.1-bulk-prepare-handler.plantuml new file mode 100644 index 000000000..a9c53292f --- /dev/null +++ b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.1.1-bulk-prepare-handler.plantuml @@ -0,0 +1,320 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Samuel Kummary + -------------- + ******'/ + +@startuml +' declare title +title 1.1.1. Bulk Prepare Handler Consume + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +collections "topic-\nbulk-prepare" as TOPIC_BULK_PREPARE +collections "mojaloop-\nobject-store\n(**MLOS**)" as OBJECT_STORE +control "Bulk Prepare \nHandler" as BULK_PREP_HANDLER +collections "topic-\ntransfer-prepare" as TOPIC_TRANSFER_PREPARE +collections "topic-event" as TOPIC_EVENTS +collections "topic-\nnotification" as TOPIC_NOTIFICATIONS +collections "topic-bulk-\nprocessing" as TOPIC_BULK_PROCESSING +entity "Bulk DAO" as BULK_DAO +entity "Participant DAO" as PARTICIPANT_DAO +database "Central Store" as DB + +box "Central Service" #LightYellow + participant OBJECT_STORE + participant TOPIC_BULK_PREPARE + participant BULK_PREP_HANDLER + participant TOPIC_TRANSFER_PREPARE + participant TOPIC_EVENTS + participant TOPIC_NOTIFICATIONS + participant TOPIC_BULK_PROCESSING + participant BULK_DAO + participant PARTICIPANT_DAO + participant DB +end box + +' start flow +activate BULK_PREP_HANDLER +group Bulk Prepare Handler Consume + TOPIC_BULK_PREPARE <- BULK_PREP_HANDLER: Consume Bulk Prepare message + activate TOPIC_BULK_PREPARE + deactivate TOPIC_BULK_PREPARE + group Validate Bulk Prepare Transfer + group Duplicate Check + note right of BULK_PREP_HANDLER #cyan + The Specification doesn't touch on the duplicate handling + of bulk transfers, so the current design mostly follows the + strategy used for individual transfers, except in two places: + + 1. For duplicate requests where hash matches, the current design + includes only the status of the bulk & timestamp (if completed), + but not the individual transfers (for which a GET should be used). + + 2. For duplicate requests where hash matches, but are not in a + finalized state, only the state of the bulkTransfer is sent. + end note + ||| + BULK_PREP_HANDLER -> DB: Request Duplicate Check + ref over BULK_PREP_HANDLER, DB: Request Duplicate Check (using message.content.payload)\n + DB --> BULK_PREP_HANDLER: Return { hasDuplicateId: Boolean, hasDuplicateHash: Boolean } + end + + alt hasDuplicateId == TRUE && hasDuplicateHash == TRUE + break Return TRUE & Log ('Not implemented') + end + else hasDuplicateId == TRUE && hasDuplicateHash == FALSE + note right of BULK_PREP_HANDLER #yellow + { + id: , + from: , + to: , + type: "application/json", + content: { + headers: , + payload: { + errorInformation: { + errorCode: "3106", + errorDescription: "Modified request", + extensionList: { + extension: [ + { + key: "_cause", + value: + } + ] + } + }, + uriParams: { + id: + } + } + }, + metadata: { + correlationId: , + event: { + id: , + type: "notification", + action: "bulk-prepare", + createdAt: , + state: { + status: "error", + code: "3106", + description: "Modified request" + }, + responseTo: + } + } + } + end note + BULK_PREP_HANDLER -> TOPIC_NOTIFICATIONS: Publish Notification (failure) event for Payer\nError codes: 3106 + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + else hasDuplicateId == FALSE + group Validate Bulk Transfer Prepare Request + BULK_PREP_HANDLER <-> BULK_PREP_HANDLER: FSPIOP Source matches Payer + BULK_PREP_HANDLER <-> BULK_PREP_HANDLER: Check expiration + BULK_PREP_HANDLER <-> BULK_PREP_HANDLER: Payer and Payee FSP's are different + group Validate Payer + BULK_PREP_HANDLER -> PARTICIPANT_DAO: Request to retrieve Payer Participant details (if it exists) + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Request Participant details + hnote over DB #lightyellow + participant + participantCurrency + end note + activate DB + PARTICIPANT_DAO <-- DB: Return Participant details if it exists + deactivate DB + PARTICIPANT_DAO --> BULK_PREP_HANDLER: Return Participant details if it exists + deactivate PARTICIPANT_DAO + BULK_PREP_HANDLER <-> BULK_PREP_HANDLER: Validate Payer\nError codes: 3202 + end + group Validate Payee + BULK_PREP_HANDLER -> PARTICIPANT_DAO: Request to retrieve Payee Participant details (if it exists) + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Request Participant details + hnote over DB #lightyellow + participant + participantCurrency + end note + activate DB + PARTICIPANT_DAO <-- DB: Return Participant details if it exists + deactivate DB + PARTICIPANT_DAO --> BULK_PREP_HANDLER: Return Participant details if it exists + deactivate PARTICIPANT_DAO + BULK_PREP_HANDLER <-> BULK_PREP_HANDLER: Validate Payee\nError codes: 3203 + end + end + ||| + alt Validate Bulk Transfer Prepare Request (success) + group Persist Bulk Transfer State (with bulkTransferState='RECEIVED') + BULK_PREP_HANDLER -> BULK_DAO: Request to persist bulk transfer\nError codes: 2003 + activate BULK_DAO + BULK_DAO -> DB: Persist bulkTransfer + hnote over DB #lightyellow + bulkTransfer + bulkTransferExtension + bulkTransferStateChange + end note + activate DB + deactivate DB + BULK_DAO --> BULK_PREP_HANDLER: Return state + deactivate BULK_DAO + end + else Validate Bulk Transfer Prepare Request (failure) + group Persist Bulk Transfer State (with bulkTransferState='INVALID') (Introducing a new status INVALID to mark these entries) + BULK_PREP_HANDLER -> BULK_DAO: Request to persist bulk transfer\n(when Payee/Payer/crypto-condition validation fails)\nError codes: 2003 + activate BULK_DAO + BULK_DAO -> DB: Persist transfer + hnote over DB #lightyellow + bulkTransfer + bulkTransferExtension + bulkTransferStateChange + bulkTransferError + end note + activate DB + deactivate DB + BULK_DAO --> BULK_PREP_HANDLER: Return state + deactivate BULK_DAO + end + end + end + end + alt Validate Bulk Prepare Transfer (success) + loop for each individual transfer in the bulk + BULK_PREP_HANDLER -> OBJECT_STORE: Retrieve individual transfers from the bulk using\nreference: **MLOS.individualTransfers.messageId** + activate OBJECT_STORE + note right of OBJECT_STORE #lightgrey + Add elements such as Expiry time, Payer FSP, Payee FSP, etc. to each + transfer to make their format similar to a single transfer + end note + OBJECT_STORE --> BULK_PREP_HANDLER: Stream bulk's individual transfers + deactivate OBJECT_STORE + + group Insert Bulk Transfer Association (with bulkProcessingState='RECEIVED') + BULK_PREP_HANDLER -> BULK_DAO: Request to persist bulk transfer association\nError codes: 2003 + activate BULK_DAO + BULK_DAO -> DB: Insert bulkTransferAssociation + hnote over DB #lightyellow + bulkTransferAssociation + bulkTransferStateChange + end note + activate DB + deactivate DB + BULK_DAO --> BULK_PREP_HANDLER: Return state + deactivate BULK_DAO + end + + note right of BULK_PREP_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: "prepare", + action: "bulk-prepare", + createdAt: , + state: { + status: "success", + code: 0, + description:"action successful" + } + } + } + } + end note + BULK_PREP_HANDLER -> TOPIC_TRANSFER_PREPARE: Route & Publish Prepare event to the Payee for the Individual Transfer\nError codes: 2003 + activate TOPIC_TRANSFER_PREPARE + deactivate TOPIC_TRANSFER_PREPARE + end + else Validate Bulk Prepare Transfer (failure) + note right of BULK_PREP_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: "application/json", + content: { + headers: , + payload: { + "errorInformation": { + "errorCode": + "errorDescription": "", + "extensionList": + } + }, + metadata: { + event: { + id: , + responseTo: , + type: "bulk-processing", + action: "bulk-abort", + createdAt: , + state: { + status: "error", + code: + description: + } + } + } + } + end note + BULK_PREP_HANDLER -> TOPIC_BULK_PROCESSING: Publish Processing (failure) event for Payer\nError codes: 2003 + activate TOPIC_BULK_PROCESSING + deactivate TOPIC_BULK_PROCESSING + group Insert Bulk Transfer Association (with bulkProcessingState='INVALID') + BULK_PREP_HANDLER -> BULK_DAO: Request to persist bulk transfer association\nError codes: 2003 + activate BULK_DAO + BULK_DAO -> DB: Insert bulkTransferAssociation + hnote over DB #lightyellow + bulkTransferAssociation + bulkTransferStateChange + end note + activate DB + deactivate DB + BULK_DAO --> BULK_PREP_HANDLER: Return state + deactivate BULK_DAO + end + + end +end +deactivate BULK_PREP_HANDLER +@enduml + diff --git a/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.1.1-bulk-prepare-handler.svg b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.1.1-bulk-prepare-handler.svg new file mode 100644 index 000000000..eb4b20b44 --- /dev/null +++ b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.1.1-bulk-prepare-handler.svg @@ -0,0 +1,1009 @@ + + + + + + + + + + + 1.1.1. Bulk Prepare Handler Consume + + + + Central Service + + + + + + + + + + + + + + + + + + + + + + mojaloop- + + + object-store + + + ( + + + MLOS + + + ) + + + + + mojaloop- + + + object-store + + + ( + + + MLOS + + + ) + + + + + topic- + + + bulk-prepare + + + + + topic- + + + bulk-prepare + + + Bulk Prepare + + + Handler + + + + + Bulk Prepare + + + Handler + + + + + + + topic- + + + transfer-prepare + + + + + topic- + + + transfer-prepare + + + + + topic-event + + + + + topic-event + + + + + topic- + + + notification + + + + + topic- + + + notification + + + + + topic-bulk- + + + processing + + + + + topic-bulk- + + + processing + + + Bulk DAO + + + + + Bulk DAO + + + + + Participant DAO + + + + + Participant DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Bulk Prepare Handler Consume + + + + + 1 + + + Consume Bulk Prepare message + + + + + Validate Bulk Prepare Transfer + + + + + Duplicate Check + + + + + The Specification doesn't touch on the duplicate handling + + + of bulk transfers, so the current design mostly follows the + + + strategy used for individual transfers, except in two places: + + + 1. For duplicate requests where hash matches, the current design + + + includes only the status of the bulk & timestamp (if completed), + + + but not the individual transfers (for which a GET should be used). + + + 2. For duplicate requests where hash matches, but are not in a + + + finalized state, only the state of the bulkTransfer is sent. + + + + + 2 + + + Request Duplicate Check + + + + + ref + + + Request Duplicate Check (using message.content.payload) + + + + + 3 + + + Return { hasDuplicateId: Boolean, hasDuplicateHash: Boolean } + + + + + alt + + + [hasDuplicateId == TRUE && hasDuplicateHash == TRUE] + + + + + break + + + [Return TRUE & Log ('Not implemented')] + + + + [hasDuplicateId == TRUE && hasDuplicateHash == FALSE] + + + + + { + + + id: <messageId>, + + + from: <ledgerName>, + + + to: <payerFspName>, + + + type: "application/json", + + + content: { + + + headers: <bulkTransferHeaders>, + + + payload: { + + + errorInformation: { + + + errorCode: "3106", + + + errorDescription: "Modified request", + + + extensionList: { + + + extension: [ + + + { + + + key: "_cause", + + + value: <FSPIOPError> + + + } + + + ] + + + } + + + }, + + + uriParams: { + + + id: <bulkTransferId> + + + } + + + } + + + }, + + + metadata: { + + + correlationId: <uuid>, + + + event: { + + + id: <uuid>, + + + type: "notification", + + + action: "bulk-prepare", + + + createdAt: <timestamp>, + + + state: { + + + status: "error", + + + code: "3106", + + + description: "Modified request" + + + }, + + + responseTo: <uuid> + + + } + + + } + + + } + + + + + 4 + + + Publish Notification (failure) event for Payer + + + Error codes: + + + 3106 + + + + [hasDuplicateId == FALSE] + + + + + Validate Bulk Transfer Prepare Request + + + + + 5 + + + FSPIOP Source matches Payer + + + + + 6 + + + Check expiration + + + + + 7 + + + Payer and Payee FSP's are different + + + + + Validate Payer + + + + + 8 + + + Request to retrieve Payer Participant details (if it exists) + + + + + 9 + + + Request Participant details + + + + participant + + + participantCurrency + + + + + 10 + + + Return Participant details if it exists + + + + + 11 + + + Return Participant details if it exists + + + + + 12 + + + Validate Payer + + + Error codes: + + + 3202 + + + + + Validate Payee + + + + + 13 + + + Request to retrieve Payee Participant details (if it exists) + + + + + 14 + + + Request Participant details + + + + participant + + + participantCurrency + + + + + 15 + + + Return Participant details if it exists + + + + + 16 + + + Return Participant details if it exists + + + + + 17 + + + Validate Payee + + + Error codes: + + + 3203 + + + + + alt + + + [Validate Bulk Transfer Prepare Request (success)] + + + + + Persist Bulk Transfer State (with bulkTransferState='RECEIVED') + + + + + 18 + + + Request to persist bulk transfer + + + Error codes: + + + 2003 + + + + + 19 + + + Persist bulkTransfer + + + + bulkTransfer + + + bulkTransferExtension + + + bulkTransferStateChange + + + + + 20 + + + Return state + + + + [Validate Bulk Transfer Prepare Request (failure)] + + + + + Persist Bulk Transfer State (with bulkTransferState='INVALID') (Introducing a new status INVALID to mark these entries) + + + + + 21 + + + Request to persist bulk transfer + + + (when Payee/Payer/crypto-condition validation fails) + + + Error codes: + + + 2003 + + + + + 22 + + + Persist transfer + + + + bulkTransfer + + + bulkTransferExtension + + + bulkTransferStateChange + + + bulkTransferError + + + + + 23 + + + Return state + + + + + alt + + + [Validate Bulk Prepare Transfer (success)] + + + + + loop + + + [for each individual transfer in the bulk] + + + + + 24 + + + Retrieve individual transfers from the bulk using + + + reference: + + + MLOS.individualTransfers.messageId + + + + + Add elements such as Expiry time, Payer FSP, Payee FSP, etc. to each + + + transfer to make their format similar to a single transfer + + + + + 25 + + + Stream bulk's individual transfers + + + + + Insert Bulk Transfer Association (with bulkProcessingState='RECEIVED') + + + + + 26 + + + Request to persist bulk transfer association + + + Error codes: + + + 2003 + + + + + 27 + + + Insert bulkTransferAssociation + + + + bulkTransferAssociation + + + bulkTransferStateChange + + + + + 28 + + + Return state + + + + + Message: + + + { + + + id: <messageId> + + + from: <payerFspName>, + + + to: <payeeFspName>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: "prepare", + + + action: "bulk-prepare", + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0, + + + description:"action successful" + + + } + + + } + + + } + + + } + + + + + 29 + + + Route & Publish Prepare event to the Payee for the Individual Transfer + + + Error codes: + + + 2003 + + + + [Validate Bulk Prepare Transfer (failure)] + + + + + Message: + + + { + + + id: <messageId> + + + from: <ledgerName>, + + + to: <bulkTransferMessage.payerFsp>, + + + type: "application/json", + + + content: { + + + headers: <bulkTransferHeaders>, + + + payload: { + + + "errorInformation": { + + + "errorCode": <possible codes: [2003, 3100, 3105, 3106, 3202, 3203, 3300, 3301]> + + + "errorDescription": "<refer to section 7.6 for description>", + + + "extensionList": <transferMessage.extensionList> + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: "bulk-processing", + + + action: "bulk-abort", + + + createdAt: <timestamp>, + + + state: { + + + status: "error", + + + code: <errorInformation.errorCode> + + + description: <errorInformation.errorDescription> + + + } + + + } + + + } + + + } + + + + + 30 + + + Publish Processing (failure) event for Payer + + + Error codes: + + + 2003 + + + + + Insert Bulk Transfer Association (with bulkProcessingState='INVALID') + + + + + 31 + + + Request to persist bulk transfer association + + + Error codes: + + + 2003 + + + + + 32 + + + Insert bulkTransferAssociation + + + + bulkTransferAssociation + + + bulkTransferStateChange + + + + + 33 + + + Return state + + diff --git a/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.2.1-prepare-handler.plantuml b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.2.1-prepare-handler.plantuml new file mode 100644 index 000000000..aee02560a --- /dev/null +++ b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.2.1-prepare-handler.plantuml @@ -0,0 +1,324 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Miguel de Barros + * Rajiv Mothilal + * Samuel Kummary + * Shashikant Hirugade + -------------- + ******'/ + +@startuml +' declate title +title 1.2.1. Prepare Handler Consume individual transfers from Bulk + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +collections "topic-\ntransfer-prepare" as TOPIC_TRANSFER_PREPARE +control "Prepare Handler" as PREP_HANDLER +collections "topic-\ntransfer-position" as TOPIC_TRANSFER_POSITION +collections "topic-\nbulk-processing" as TOPIC_BULK_PROCESSING +collections "topic-\nevent" as TOPIC_EVENTS +collections "topic-\nnotification" as TOPIC_NOTIFICATIONS +entity "Position DAO" as POS_DAO +entity "Participant DAO" as PARTICIPANT_DAO +database "Central Store" as DB + +box "Central Service" #LightYellow + participant TOPIC_TRANSFER_PREPARE + participant PREP_HANDLER + participant TOPIC_TRANSFER_POSITION + participant TOPIC_EVENTS + participant TOPIC_NOTIFICATIONS + participant TOPIC_BULK_PROCESSING + participant POS_DAO + participant PARTICIPANT_DAO + participant DB +end box + +' start flow +activate PREP_HANDLER +group Prepare Handler Consume + TOPIC_TRANSFER_PREPARE <- PREP_HANDLER: Consume Prepare event message + activate TOPIC_TRANSFER_PREPARE + deactivate TOPIC_TRANSFER_PREPARE + + break + group Validate Event + PREP_HANDLER <-> PREP_HANDLER: Validate event - Rule: type == 'prepare' && action == 'bulk-prepare'\nError codes: 2001 + end + end + + group Persist Event Information + ||| + PREP_HANDLER -> TOPIC_EVENTS: Publish event information + ref over PREP_HANDLER, TOPIC_EVENTS : Event Handler Consume\n + ||| + end + + group Validate Prepare Transfer + PREP_HANDLER <-> PREP_HANDLER: Schema validation of the incoming message + PREP_HANDLER <-> PREP_HANDLER: Verify the message's signature (to be confirmed in future requirement) + + group Validate Duplicate Check + ||| + PREP_HANDLER -> DB: Request Duplicate Check + ref over PREP_HANDLER, DB: Request Duplicate Check\n + DB --> PREP_HANDLER: Return { hasDuplicateId: Boolean, hasDuplicateHash: Boolean } + end + + alt hasDuplicateId == TRUE && hasDuplicateHash == TRUE + note right of PREP_HANDLER #lightgrey + In the context of a bulk (when compared to regular transfers), duplicate + individual transfers are now considered and reported with Modified Request, + because they could have already been handled for another bulk. + end note + break + note right of PREP_HANDLER #yellow + { + id: + from: , + to: , + type: "application/json", + content: { + headers: , + payload: { + errorInformation: { + errorCode: "3106", + errorDescription: "Modified request - Individual transfer prepare duplicate", + extensionList: { extension: [ { key: "_cause", value: } ] } + } + }, + uriParams: { id: } + }, + metadata: { + correlationId: , + event: { + type: "bulk-processing", + action: "prepare-duplicate", + createdAt: , + state: { + code: "3106", + status: "error", + description: "Modified request - Individual transfer prepare duplicate" + }, + id: , + responseTo: + } + } + end note + PREP_HANDLER -> TOPIC_BULK_PROCESSING: Publish Processing (failure) event for Payer\nError codes: 2003 + activate TOPIC_BULK_PROCESSING + deactivate TOPIC_BULK_PROCESSING + end + else hasDuplicateId == TRUE && hasDuplicateHash == FALSE + break + note right of PREP_HANDLER #yellow + { + id: + from: , + to: , + type: "application/json", + content: { + headers: , + payload: { + errorInformation: { + errorCode: "3106", + errorDescription: "Modified request", + extensionList: { extension: [ { key: "_cause", value: } ] } + } + }, + uriParams: { id: } + }, + metadata: { + correlationId: , + event: { + type: "bulk-processing", + action: "prepare-duplicate", + createdAt: , + state: { + code: "3106", + status: "error", + description: "Modified request" + }, + id: , + responseTo: + } + } + end note + PREP_HANDLER -> TOPIC_BULK_PROCESSING: Publish Processing (failure) event for Payer\nError codes: 2003 + activate TOPIC_BULK_PROCESSING + deactivate TOPIC_BULK_PROCESSING + end + else hasDuplicateId == FALSE + note right of PREP_HANDLER #lightgrey + The validation of Payer, Payee can be skipped for individual transfers in Bulk + as they should've/would've been validated already in the bulk prepare part. + However, leaving it here for now, as in the future, this can be leveraged + when bulk transfers to multiple Payees are supported by the Specification. + end note + group Validate Payer + PREP_HANDLER -> PARTICIPANT_DAO: Request to retrieve Payer Participant details (if it exists) + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Request Participant details + hnote over DB #lightyellow + participant + participantCurrency + end note + activate DB + PARTICIPANT_DAO <-- DB: Return Participant details if it exists + deactivate DB + PARTICIPANT_DAO --> PREP_HANDLER: Return Participant details if it exists + deactivate PARTICIPANT_DAO + PREP_HANDLER <-> PREP_HANDLER: Validate Payer\nError codes: 3202 + end + group Validate Payee + PREP_HANDLER -> PARTICIPANT_DAO: Request to retrieve Payee Participant details (if it exists) + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Request Participant details + hnote over DB #lightyellow + participant + participantCurrency + end note + activate DB + PARTICIPANT_DAO <-- DB: Return Participant details if it exists + deactivate DB + PARTICIPANT_DAO --> PREP_HANDLER: Return Participant details if it exists + deactivate PARTICIPANT_DAO + PREP_HANDLER <-> PREP_HANDLER: Validate Payee\nError codes: 3203 + end + + alt Validate Prepare Transfer (success) + group Persist Transfer State (with transferState='RECEIVED-PREPARE') + PREP_HANDLER -> POS_DAO: Request to persist transfer\nError codes: 2003 + activate POS_DAO + POS_DAO -> DB: Persist transfer + hnote over DB #lightyellow + transfer + transferParticipant + transferStateChange + transferExtension + ilpPacket + end note + activate DB + deactivate DB + POS_DAO --> PREP_HANDLER: Return success + deactivate POS_DAO + end + else Validate Prepare Transfer (failure) + group Persist Transfer State (with transferState='INVALID') (Introducing a new status INVALID to mark these entries) + PREP_HANDLER -> POS_DAO: Request to persist transfer\n(when Payee/Payer/crypto-condition validation fails)\nError codes: 2003 + activate POS_DAO + POS_DAO -> DB: Persist transfer + hnote over DB #lightyellow + transfer + transferParticipant + transferStateChange + transferExtension + transferError + ilpPacket + end note + activate DB + deactivate DB + POS_DAO --> PREP_HANDLER: Return success + deactivate POS_DAO + end + end + end + end + + alt Validate Prepare Transfer (success) + note right of PREP_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: "application/json", + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: "position", + action: "bulk-prepare", + createdAt: , + state: { + status: "success", + code: 0, + description:"action successful" + } + } + } + } + end note + PREP_HANDLER -> TOPIC_TRANSFER_POSITION: Route & Publish Position event for Payer\nError codes: 2003 + else Validate Prepare Transfer (failure) + note right of PREP_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: "application/json" + content: { + headers: , + payload: { + "errorInformation": { + "errorCode": + "errorDescription": "", + "extensionList": + } + }, + metadata: { + event: { + id: , + responseTo: , + type: "bulk-processing", + action: "prepare", + createdAt: , + state: { + status: 'error', + code: + description: + } + } + } + } + end note + PREP_HANDLER -> TOPIC_BULK_PROCESSING: Publish Prepare failure event to Bulk Processing Topic (for Payer) \nError codes: 2003 + end +end + +deactivate PREP_HANDLER +@enduml + diff --git a/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.2.1-prepare-handler.svg b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.2.1-prepare-handler.svg new file mode 100644 index 000000000..af0e4479c --- /dev/null +++ b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.2.1-prepare-handler.svg @@ -0,0 +1,975 @@ + + + + + + + + + + + 1.2.1. Prepare Handler Consume individual transfers from Bulk + + + + Central Service + + + + + + + + + + + + + + + + + + + + topic- + + + transfer-prepare + + + + + topic- + + + transfer-prepare + + + Prepare Handler + + + + + Prepare Handler + + + + + + + topic- + + + transfer-position + + + + + topic- + + + transfer-position + + + + + topic- + + + event + + + + + topic- + + + event + + + + + topic- + + + notification + + + + + topic- + + + notification + + + + + topic- + + + bulk-processing + + + + + topic- + + + bulk-processing + + + Position DAO + + + + + Position DAO + + + + + Participant DAO + + + + + Participant DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Prepare Handler Consume + + + + + 1 + + + Consume Prepare event message + + + + + break + + + + + Validate Event + + + + + 2 + + + Validate event - Rule: type == 'prepare' && action == 'bulk-prepare' + + + Error codes: + + + 2001 + + + + + Persist Event Information + + + + + 3 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + Validate Prepare Transfer + + + + + 4 + + + Schema validation of the incoming message + + + + + 5 + + + Verify the message's signature (to be confirmed in future requirement) + + + + + Validate Duplicate Check + + + + + 6 + + + Request Duplicate Check + + + + + ref + + + Request Duplicate Check + + + + + 7 + + + Return { hasDuplicateId: Boolean, hasDuplicateHash: Boolean } + + + + + alt + + + [hasDuplicateId == TRUE && hasDuplicateHash == TRUE] + + + + + In the context of a bulk (when compared to regular transfers), duplicate + + + individual transfers are now considered and reported with Modified Request, + + + because they could have already been handled for another bulk. + + + + + break + + + + + { + + + id: <messageId> + + + from: <ledgerName>, + + + to: <payerFspName>, + + + type: "application/json", + + + content: { + + + headers: <transferHeaders>, + + + payload: { + + + errorInformation: { + + + errorCode: "3106", + + + errorDescription: "Modified request - Individual transfer prepare duplicate", + + + extensionList: { extension: [ { key: "_cause", value: <FSPIOPError> } ] } + + + } + + + }, + + + uriParams: { id: <transferId> } + + + }, + + + metadata: { + + + correlationId: <uuid>, + + + event: { + + + type: "bulk-processing", + + + action: "prepare-duplicate", + + + createdAt: <timestamp>, + + + state: { + + + code: "3106", + + + status: "error", + + + description: "Modified request - Individual transfer prepare duplicate" + + + }, + + + id: <uuid>, + + + responseTo: <uuid> + + + } + + + } + + + + + 8 + + + Publish Processing (failure) event for Payer + + + Error codes: + + + 2003 + + + + [hasDuplicateId == TRUE && hasDuplicateHash == FALSE] + + + + + break + + + + + { + + + id: <messageId> + + + from: <ledgerName>, + + + to: <payerFspName>, + + + type: "application/json", + + + content: { + + + headers: <transferHeaders>, + + + payload: { + + + errorInformation: { + + + errorCode: "3106", + + + errorDescription: "Modified request", + + + extensionList: { extension: [ { key: "_cause", value: <FSPIOPError> } ] } + + + } + + + }, + + + uriParams: { id: <transferId> } + + + }, + + + metadata: { + + + correlationId: <uuid>, + + + event: { + + + type: "bulk-processing", + + + action: "prepare-duplicate", + + + createdAt: <timestamp>, + + + state: { + + + code: "3106", + + + status: "error", + + + description: "Modified request" + + + }, + + + id: <uuid>, + + + responseTo: <uuid> + + + } + + + } + + + + + 9 + + + Publish Processing (failure) event for Payer + + + Error codes: + + + 2003 + + + + [hasDuplicateId == FALSE] + + + + + The validation of Payer, Payee can be skipped for individual transfers in Bulk + + + as they should've/would've been validated already in the bulk prepare part. + + + However, leaving it here for now, as in the future, this can be leveraged + + + when bulk transfers to multiple Payees are supported by the Specification. + + + + + Validate Payer + + + + + 10 + + + Request to retrieve Payer Participant details (if it exists) + + + + + 11 + + + Request Participant details + + + + participant + + + participantCurrency + + + + + 12 + + + Return Participant details if it exists + + + + + 13 + + + Return Participant details if it exists + + + + + 14 + + + Validate Payer + + + Error codes: + + + 3202 + + + + + Validate Payee + + + + + 15 + + + Request to retrieve Payee Participant details (if it exists) + + + + + 16 + + + Request Participant details + + + + participant + + + participantCurrency + + + + + 17 + + + Return Participant details if it exists + + + + + 18 + + + Return Participant details if it exists + + + + + 19 + + + Validate Payee + + + Error codes: + + + 3203 + + + + + alt + + + [Validate Prepare Transfer (success)] + + + + + Persist Transfer State (with transferState='RECEIVED-PREPARE') + + + + + 20 + + + Request to persist transfer + + + Error codes: + + + 2003 + + + + + 21 + + + Persist transfer + + + + transfer + + + transferParticipant + + + transferStateChange + + + transferExtension + + + ilpPacket + + + + + 22 + + + Return success + + + + [Validate Prepare Transfer (failure)] + + + + + Persist Transfer State (with transferState='INVALID') (Introducing a new status INVALID to mark these entries) + + + + + 23 + + + Request to persist transfer + + + (when Payee/Payer/crypto-condition validation fails) + + + Error codes: + + + 2003 + + + + + 24 + + + Persist transfer + + + + transfer + + + transferParticipant + + + transferStateChange + + + transferExtension + + + transferError + + + ilpPacket + + + + + 25 + + + Return success + + + + + alt + + + [Validate Prepare Transfer (success)] + + + + + Message: + + + { + + + id: <messageId> + + + from: <payerFspName>, + + + to: <payeeFspName>, + + + type: "application/json", + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: "position", + + + action: "bulk-prepare", + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0, + + + description:"action successful" + + + } + + + } + + + } + + + } + + + + + 26 + + + Route & Publish Position event for Payer + + + Error codes: + + + 2003 + + + + [Validate Prepare Transfer (failure)] + + + + + Message: + + + { + + + id: <messageId> + + + from: <ledgerName>, + + + to: <payerFspName>, + + + type: "application/json" + + + content: { + + + headers: <transferHeaders>, + + + payload: { + + + "errorInformation": { + + + "errorCode": <possible codes: [2003, 3100, 3105, 3106, 3202, 3203, 3300, 3301]> + + + "errorDescription": "<refer to section 35.1.3 for description>", + + + "extensionList": <transferMessage.extensionList> + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: "bulk-processing", + + + action: "prepare", + + + createdAt: <timestamp>, + + + state: { + + + status: 'error', + + + code: <errorInformation.errorCode> + + + description: <errorInformation.errorDescription> + + + } + + + } + + + } + + + } + + + + + 27 + + + Publish Prepare failure event to Bulk Processing Topic (for Payer) + + + Error codes: + + + 2003 + + diff --git a/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.3.0-position-overview.plantuml b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.3.0-position-overview.plantuml new file mode 100644 index 000000000..44d640284 --- /dev/null +++ b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.3.0-position-overview.plantuml @@ -0,0 +1,116 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Miguel de Barros + * Rajiv Mothilal + * Samuel Kummary + -------------- + ******'/ + +@startuml +' declate title +title 1.3.0. Position Handler Consume individual transfers from Bulk + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +collections "topic-transfer-position" as TOPIC_TRANSFER_POSITION +control "Position Handler" as POS_HANDLER +collections "Event-Topic" as TOPIC_EVENTS +collections "Notification-Topic" as TOPIC_NOTIFICATIONS + + +box "Central Service" #LightYellow + participant TOPIC_TRANSFER_POSITION + participant POS_HANDLER + participant TOPIC_EVENTS + participant TOPIC_NOTIFICATIONS +end box + +' start flow +activate POS_HANDLER +group Position Handler Consume + alt Consume Prepare message for Payer + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume Position event message for Payer + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + break + group Validate Event + POS_HANDLER <-> POS_HANDLER: Validate event - Rule: type == 'position' && action == 'bulk-prepare'\nError codes: 2001 + end + end + group Persist Event Information + ||| + POS_HANDLER -> TOPIC_EVENTS: Publish event information + ref over POS_HANDLER, TOPIC_EVENTS: Event Handler Consume\n + ||| + end + ||| + ref over POS_HANDLER: Prepare Position Handler Consume\n + POS_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + else Consume Fulfil message for Payee + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume Position event message for Payee + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + break + group Validate Event + POS_HANDLER <-> POS_HANDLER: Validate event - Rule: type == 'position' && action == 'bulk-commit'\nError codes: 2001 + end + end + group Persist Event Information + ||| + POS_HANDLER -> TOPIC_EVENTS: Publish event information + ref over POS_HANDLER, TOPIC_EVENTS : Event Handler Consume\n + ||| + end + ||| + ref over POS_HANDLER: Fulfil Position Handler Consume\n + POS_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + else Consume Abort message + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume Position event message + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + break + group Validate Event + POS_HANDLER <-> POS_HANDLER: Validate event - Rule: type == 'position' && action == 'timeout-reserved'\nError codes: 2001 + end + end + group Persist Event Information + ||| + POS_HANDLER -> TOPIC_EVENTS: Publish event information + ref over POS_HANDLER, TOPIC_EVENTS : Event Handler Consume\n + ||| + end + ||| + ref over POS_HANDLER: Abort Position Handler Consume\n + POS_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + end + +end +deactivate POS_HANDLER +@enduml diff --git a/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.3.0-position-overview.svg b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.3.0-position-overview.svg new file mode 100644 index 000000000..a6c1ce040 --- /dev/null +++ b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.3.0-position-overview.svg @@ -0,0 +1,298 @@ + + + + + + + + + + + 1.3.0. Position Handler Consume individual transfers from Bulk + + + + Central Service + + + + + + + + + + + + + + + + + topic-transfer-position + + + + + topic-transfer-position + + + Position Handler + + + + + Position Handler + + + + + + + Event-Topic + + + + + Event-Topic + + + + + Notification-Topic + + + + + Notification-Topic + + + + + + Position Handler Consume + + + + + alt + + + [Consume Prepare message for Payer] + + + + + 1 + + + Consume Position event message for Payer + + + + + break + + + + + Validate Event + + + + + 2 + + + Validate event - Rule: type == 'position' && action == 'bulk-prepare' + + + Error codes: + + + 2001 + + + + + Persist Event Information + + + + + 3 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + ref + + + Prepare Position Handler Consume + + + + + 4 + + + Produce message + + + + [Consume Fulfil message for Payee] + + + + + 5 + + + Consume Position event message for Payee + + + + + break + + + + + Validate Event + + + + + 6 + + + Validate event - Rule: type == 'position' && action == 'bulk-commit' + + + Error codes: + + + 2001 + + + + + Persist Event Information + + + + + 7 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + ref + + + Fulfil Position Handler Consume + + + + + 8 + + + Produce message + + + + [Consume Abort message] + + + + + 9 + + + Consume Position event message + + + + + break + + + + + Validate Event + + + + + 10 + + + Validate event - Rule: type == 'position' && action == 'timeout-reserved' + + + Error codes: + + + 2001 + + + + + Persist Event Information + + + + + 11 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + ref + + + Abort Position Handler Consume + + + + + 12 + + + Produce message + + diff --git a/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.3.1-position-prepare.plantuml b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.3.1-position-prepare.plantuml new file mode 100644 index 000000000..370eaf388 --- /dev/null +++ b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.3.1-position-prepare.plantuml @@ -0,0 +1,365 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Miguel de Barros + * Rajiv Mothilal + * Samuel Kummary + -------------- + ******'/ + +@startuml +' declate title +title 1.3.1. Prepare Position Handler Consume (single message, includes individual transfers from Bulk) + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistence Store + +' declare actors +control "Position Handler" as POS_HANDLER + +entity "Position\nManagement\nFacade" as POS_MGMT +collections "topic-\nnotification" as TOPIC_NOTIFICATIONS +collections "topic-\nbulk-processing" as TOPIC_BULK_PROCESSING +entity "Position DAO" as POS_DAO +database "Central Store" as DB + +box "Central Service" #LightYellow + participant POS_HANDLER + participant TOPIC_NOTIFICATIONS + participant TOPIC_BULK_PROCESSING + participant POS_MGMT + participant POS_DAO + participant DB +end box + +' start flow +activate POS_HANDLER +group Prepare Position Handler Consume + POS_HANDLER -> POS_MGMT: Request transfers to be processed + activate POS_MGMT + POS_MGMT -> POS_MGMT: Check 1st transfer to select the Participant and Currency + group DB TRANSACTION + ' DB Trans: This is where 1st DB Transaction would start in 2 DB transacation future model for horizontal scaling + POS_MGMT -> POS_MGMT: Loop through batch and build list of transferIds and calculate sumTransfersInBatch,\nchecking all in Batch are for the correct Paricipant and Currency\nError code: 2001, 3100 + POS_MGMT -> DB: Retrieve current state of all transfers in array from DB with select whereIn\n(FYI: The two DB transaction model needs to add a mini-state step here (RECEIVED_PREPARE => RECEIVDED_PREPARE_PROCESSING) so that the transfers are left alone if processing has started) + activate DB + hnote over DB #lightyellow + transferStateChange + transferParticipant + end note + DB --> POS_MGMT: Return current state of all selected transfers from DB + deactivate DB + POS_MGMT <-> POS_MGMT: Validate current state (transferStateChange.transferStateId == 'RECEIVED_PREPARE')\nError code: 2001 against failing transfers\nBatch is not rejected as a whole. + + note right of POS_MGMT #lightgray + List of transfers used during processing + **reservedTransfers** is list of transfers to be processed in the batch + **abortedTransfers** is the list of transfers in the incorrect state going into the process. Currently the transferStateChange is set to ABORTED - this should only be done if not already in a final state (idempotency) + **processedTransfers** is the list of transfers that have gone through the position management algorithm. Both successful and failed trasnfers appear here as the order and "running position" against each is necessary for reconciliation + + Scalar intermidate values used in the algorithm + **transferAmount** = payload.amount.amount + **sumTransfersInBatch** = SUM amount against each Transfer in batch + **currentPosition** = participantPosition.value + **reservedPosition** = participantPosition.{original}reservedValue + **effectivePosition** = currentPosition + reservedPosition + **heldPosition** = effectivePosition + sumTransfersInBatch + **availablePosition** = participantLimit(NetDebitCap) - effectivePosition + **sumReserved** = SUM of transfers that have met rule criteria and processed + end note + note over POS_MGMT,DB + Going to reserve the sum of the valid transfers in the batch against the Participants Positon in the Currency of this batch + and calculate the available position for the Participant to use + end note + POS_MGMT -> DB: Select effectivePosition FOR UPDATE from DB for Payer + activate DB + hnote over DB #lightyellow + participantPosition + end note + DB --> POS_MGMT: Return effectivePosition (currentPosition and reservedPosition) from DB for Payer + deactivate DB + POS_MGMT -> POS_MGMT: Increment reservedValue to heldPosition\n(reservedValue = reservedPosition + sumTransfersInBatch) + POS_MGMT -> DB: Persist reservedValue + activate DB + hnote over DB #lightyellow + UPDATE **participantPosition** + SET reservedValue += sumTransfersInBatch + end note + deactivate DB + ' DB Trans: This is where 1st DB Transaction would end in 2 DB transacation future model for horizontal scaling + + + POS_MGMT -> DB: Request position limits for Payer Participant + activate DB + hnote over DB #lightyellow + FROM **participantLimit** + WHERE participantLimit.limitTypeId = 'NET-DEBIT-CAP' + AND participantLimit.participantId = payload.payerFsp + AND participantLimit.currencyId = payload.amount.currency + end note + DB --> POS_MGMT: Return position limits + deactivate DB + POS_MGMT <-> POS_MGMT: **availablePosition** = participantLimit(netDebitCap) - effectivePosition (same as = netDebitCap - currentPosition - reservedPosition) + note over POS_MGMT,DB + For each transfer in the batch, validate the availablility of position to meet the transfer amount + this will be as per the position algorithm documented below + end note + POS_MGMT <-> POS_MGMT: Validate availablePosition for each tranfser (see algorithm below)\nError code: 4001 + note right of POS_MGMT #lightgray + 01: sumReserved = 0 // Record the sum of the transfers we allow to progress to RESERVED + 02: sumProcessed =0 // Record the sum of the transfers already processed in this batch + 03: processedTransfers = {} // The list of processed transfers - so that we can store the additional information around the decision. Most importantly the "running" position + 04: foreach transfer in reservedTransfers + 05: sumProcessed += transfer.amount // the total processed so far **(NEED TO UPDATE IN CODE)** + 06: if availablePosition >= transfer.amount + 07: transfer.state = "RESERVED" + 08: availablePosition -= preparedTransfer.amount + 09: sumRESERVED += preparedTransfer.amount + 10: else + 11: preparedTransfer.state = "ABORTED" + 12: preparedTransfer.reason = "Net Debit Cap exceeded by this request at this time, please try again later" + 13: end if + 14: runningPosition = currentPosition + sumReserved // the initial value of the Participants position plus the total value that has been accepted in the batch so far + 15: runningReservedValue = sumTransfersInBatch - sumProcessed + reservedPosition **(NEED TO UPDATE IN CODE)** // the running down of the total reserved value at the begining of the batch. + 16: Add transfer to the processedTransfer list recording the transfer state and running position and reserved values { transferState, transfer, rawMessage, transferAmount, runningPosition, runningReservedValue } + 16: end foreach + end note + note over POS_MGMT,DB + Once the outcome for all transfers is known,update the Participant's position and remove the reserved amount associated with the batch + (If there are any alarm limits, process those returning limits in which the threshold has been breached) + Do a bulk insert of the trasnferStateChanges associated with processing, using the result to complete the participantPositionChange and bulk insert of these to persist the running position + end note + POS_MGMT->POS_MGMT: Assess any limit thresholds on the final position\nadding to alarm list if triggered + + ' DB Trans: This is where 2nd DB Transaction would start in 2 DB transacation future model for horizontal scaling + POS_MGMT->DB: Persist latest position **value** and **reservedValue** to DB for Payer + hnote over DB #lightyellow + UPDATE **participantPosition** + SET value += sumRESERVED, + reservedValue -= sumTransfersInBatch + end note + activate DB + deactivate DB + + POS_MGMT -> DB: Bulk persist transferStateChange for all processedTransfers + hnote over DB #lightyellow + batch INSERT **transferStateChange** + select for update from transfer table where transferId in ([transferBatch.transferId,...]) + build list of transferStateChanges from transferBatch + + end note + activate DB + deactivate DB + + POS_MGMT->POS_MGMT: Populate batchParticipantPositionChange from the resultant transferStateChange and the earlier processedTransfer list + + note right of POS_MGMT #lightgray + Effectively: + SET transferStateChangeId = processedTransfer.transferStateChangeId, + participantPositionId = preparedTransfer.participantPositionId, + value = preparedTransfer.positionValue, + reservedValue = preparedTransfer.positionReservedValue + end note + POS_MGMT -> DB: Bulk persist the participant position change for all processedTransfers + hnote over DB #lightyellow + batch INSERT **participantPositionChange** + end note + activate DB + deactivate DB + ' DB Trans: This is where 2nd DB Transaction would end in 2 DB transacation future model for horizontal scaling + end + POS_MGMT --> POS_HANDLER: Return a map of transferIds and their transferStateChanges + deactivate POS_MGMT + alt Calculate & Validate Latest Position Prepare (success) + POS_HANDLER -> POS_HANDLER: Notifications for Position Validation Success \nReference: Position Validation Success case (Prepare) + else Calculate & Validate Latest Position Prepare (failure) + note right of POS_HANDLER #red: Validation failure! + + group Persist Transfer State (with transferState='ABORTED' on position check fail) + POS_HANDLER -> POS_DAO: Request to persist transfer\nError code: 2003 + activate POS_DAO + note right of POS_HANDLER #lightgray + transferStateChange.state = "ABORTED", + transferStateChange.reason = "Net Debit Cap exceeded by this request at this time, please try again later" + end note + POS_DAO -> DB: Persist transfer state + hnote over DB #lightyellow + transferStateChange + end note + activate DB + deactivate DB + POS_DAO --> POS_HANDLER: Return success + deactivate POS_DAO + end + POS_HANDLER -> POS_HANDLER: Notifications for failures\nReference: Failure in Position Validation (Prepare) + end +end + + +group Reference: Failure in Position Validation (Prepare) + alt If action == 'bulk-prepare' + note right of POS_HANDLER #yellow + Message: + { + id: "" + from: , + to: , + type: "application/json" + content: { + headers: , + payload: { + "errorInformation": { + "errorCode": 4001, + "errorDescription": "Payer FSP insufficient liquidity", + "extensionList": + } + }, + metadata: { + event: { + id: , + responseTo: , + type: "bulk-processing", + action: "bulk-prepare", + createdAt: , + state: { + status: "error", + code: + description: + } + } + } + } + end note + POS_HANDLER -> TOPIC_BULK_PROCESSING: Publish Position failure event (in Prepare) to Bulk Processing Topic (for Payer) \nError codes: 2003 + activate TOPIC_BULK_PROCESSING + deactivate TOPIC_BULK_PROCESSING + else If action == 'prepare' + note right of POS_HANDLER #yellow + Message: + { + id: "" + from: , + to: , + type: "application/json" + content: { + headers: , + payload: { + "errorInformation": { + "errorCode": 4001, + "errorDescription": "Payer FSP insufficient liquidity", + "extensionList": + } + }, + metadata: { + event: { + id: , + responseTo: , + type: "notification", + action: "position", + createdAt: , + state: { + status: "error", + code: + description: + } + } + } + } + end note + POS_HANDLER -> TOPIC_NOTIFICATIONS: Publish Notification (failure) event for Payer\nError code: 2003 + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + end + +end + +group Reference: Position Validation Success case (Prepare) + alt If action == 'bulk-prepare' + note right of POS_HANDLER #yellow + Message: + { + id: "" + from: , + to: , + type: "application/json" + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: "bulk-processing", + action: "bulk-prepare", + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + POS_HANDLER -> TOPIC_BULK_PROCESSING: Publish Position Success event (in Prepare) to Bulk Processing Topic\nError codes: 2003 + activate TOPIC_BULK_PROCESSING + deactivate TOPIC_BULK_PROCESSING + else If action == 'prepare' + note right of POS_HANDLER #yellow + Message: + { + id: "" + from: , + to: , + type: "application/json" + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: "notification", + action: "abort", + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + POS_HANDLER -> TOPIC_NOTIFICATIONS: Publish Notification event\nError code: 2003 + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + end +end + +deactivate POS_HANDLER +@enduml diff --git a/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.3.1-position-prepare.svg b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.3.1-position-prepare.svg new file mode 100644 index 000000000..1403dc6ab --- /dev/null +++ b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.3.1-position-prepare.svg @@ -0,0 +1,1092 @@ + + + + + + + + + + + 1.3.1. Prepare Position Handler Consume (single message, includes individual transfers from Bulk) + + + + Central Service + + + + + + + + + + + + + + Position Handler + + + + + Position Handler + + + + + + + topic- + + + notification + + + + + topic- + + + notification + + + + + topic- + + + bulk-processing + + + + + topic- + + + bulk-processing + + + Position + + + Management + + + Facade + + + + + Position + + + Management + + + Facade + + + + + Position DAO + + + + + Position DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Prepare Position Handler Consume + + + + + 1 + + + Request transfers to be processed + + + + + 2 + + + Check 1st transfer to select the Participant and Currency + + + + + DB TRANSACTION + + + + + 3 + + + Loop through batch and build list of transferIds and calculate sumTransfersInBatch, + + + checking all in Batch are for the correct Paricipant and Currency + + + Error code: + + + 2001, 3100 + + + + + 4 + + + Retrieve current state of all transfers in array from DB with select whereIn + + + (FYI: The two DB transaction model needs to add a mini-state step here (RECEIVED_PREPARE => RECEIVDED_PREPARE_PROCESSING) so that the transfers are left alone if processing has started) + + + + transferStateChange + + + transferParticipant + + + + + 5 + + + Return current state of all selected transfers from DB + + + + + 6 + + + Validate current state (transferStateChange.transferStateId == 'RECEIVED_PREPARE') + + + Error code: + + + 2001 + + + against failing transfers + + + Batch is not rejected as a whole. + + + + + List of transfers used during processing + + + reservedTransfers + + + is list of transfers to be processed in the batch + + + abortedTransfers + + + is the list of transfers in the incorrect state going into the process. Currently the transferStateChange is set to ABORTED - this should only be done if not already in a final state (idempotency) + + + processedTransfers + + + is the list of transfers that have gone through the position management algorithm. Both successful and failed trasnfers appear here as the order and "running position" against each is necessary for reconciliation + + + Scalar intermidate values used in the algorithm + + + transferAmount + + + = payload.amount.amount + + + sumTransfersInBatch + + + = SUM amount against each Transfer in batch + + + currentPosition + + + = participantPosition.value + + + reservedPosition + + + = participantPosition.{original}reservedValue + + + effectivePosition + + + = currentPosition + reservedPosition + + + heldPosition + + + = effectivePosition + sumTransfersInBatch + + + availablePosition + + + = participantLimit(NetDebitCap) - effectivePosition + + + sumReserved + + + = SUM of transfers that have met rule criteria and processed + + + + + Going to reserve the sum of the valid transfers in the batch against the Participants Positon in the Currency of this batch + + + and calculate the available position for the Participant to use + + + + + 7 + + + Select effectivePosition FOR UPDATE from DB for Payer + + + + participantPosition + + + + + 8 + + + Return effectivePosition (currentPosition and reservedPosition) from DB for Payer + + + + + 9 + + + Increment reservedValue to heldPosition + + + (reservedValue = reservedPosition + sumTransfersInBatch) + + + + + 10 + + + Persist reservedValue + + + + UPDATE + + + participantPosition + + + SET reservedValue += sumTransfersInBatch + + + + + 11 + + + Request position limits for Payer Participant + + + + FROM + + + participantLimit + + + WHERE participantLimit.limitTypeId = 'NET-DEBIT-CAP' + + + AND participantLimit.participantId = payload.payerFsp + + + AND participantLimit.currencyId = payload.amount.currency + + + + + 12 + + + Return position limits + + + + + 13 + + + availablePosition + + + = participantLimit(netDebitCap) - effectivePosition (same as = netDebitCap - currentPosition - reservedPosition) + + + + + For each transfer in the batch, validate the availablility of position to meet the transfer amount + + + this will be as per the position algorithm documented below + + + + + 14 + + + Validate availablePosition for each tranfser (see algorithm below) + + + Error code: + + + 4001 + + + + + 01: sumReserved = 0 // Record the sum of the transfers we allow to progress to RESERVED + + + 02: sumProcessed =0 // Record the sum of the transfers already processed in this batch + + + 03: processedTransfers = {} // The list of processed transfers - so that we can store the additional information around the decision. Most importantly the "running" position + + + 04: foreach transfer in reservedTransfers + + + 05: sumProcessed += transfer.amount // the total processed so far + + + (NEED TO UPDATE IN CODE) + + + 06: if availablePosition >= transfer.amount + + + 07: transfer.state = "RESERVED" + + + 08: availablePosition -= preparedTransfer.amount + + + 09: sumRESERVED += preparedTransfer.amount + + + 10: else + + + 11: preparedTransfer.state = "ABORTED" + + + 12: preparedTransfer.reason = "Net Debit Cap exceeded by this request at this time, please try again later" + + + 13: end if + + + 14: runningPosition = currentPosition + sumReserved // the initial value of the Participants position plus the total value that has been accepted in the batch so far + + + 15: runningReservedValue = sumTransfersInBatch - sumProcessed + reservedPosition + + + (NEED TO UPDATE IN CODE) + + + // the running down of the total reserved value at the begining of the batch. + + + 16: Add transfer to the processedTransfer list recording the transfer state and running position and reserved values { transferState, transfer, rawMessage, transferAmount, runningPosition, runningReservedValue } + + + 16: end foreach + + + + + Once the outcome for all transfers is known,update the Participant's position and remove the reserved amount associated with the batch + + + (If there are any alarm limits, process those returning limits in which the threshold has been breached) + + + Do a bulk insert of the trasnferStateChanges associated with processing, using the result to complete the participantPositionChange and bulk insert of these to persist the running position + + + + + 15 + + + Assess any limit thresholds on the final position + + + adding to alarm list if triggered + + + + + 16 + + + Persist latest position + + + value + + + and + + + reservedValue + + + to DB for Payer + + + + UPDATE + + + participantPosition + + + SET value += sumRESERVED, + + + reservedValue -= sumTransfersInBatch + + + + + 17 + + + Bulk persist transferStateChange for all processedTransfers + + + + batch INSERT + + + transferStateChange + + + select for update from transfer table where transferId in ([transferBatch.transferId,...]) + + + build list of transferStateChanges from transferBatch + + + + + 18 + + + Populate batchParticipantPositionChange from the resultant transferStateChange and the earlier processedTransfer list + + + + + Effectively: + + + SET transferStateChangeId = processedTransfer.transferStateChangeId, + + + participantPositionId = preparedTransfer.participantPositionId, + + + value = preparedTransfer.positionValue, + + + reservedValue = preparedTransfer.positionReservedValue + + + + + 19 + + + Bulk persist the participant position change for all processedTransfers + + + + batch INSERT + + + participantPositionChange + + + + + 20 + + + Return a map of transferIds and their transferStateChanges + + + + + alt + + + [Calculate & Validate Latest Position Prepare (success)] + + + + + 21 + + + Notifications for Position Validation Success + + + Reference: Position Validation Success case (Prepare) + + + + [Calculate & Validate Latest Position Prepare (failure)] + + + + + Validation failure! + + + + + Persist Transfer State (with transferState='ABORTED' on position check fail) + + + + + 22 + + + Request to persist transfer + + + Error code: + + + 2003 + + + + + transferStateChange.state = "ABORTED", + + + transferStateChange.reason = "Net Debit Cap exceeded by this request at this time, please try again later" + + + + + 23 + + + Persist transfer state + + + + transferStateChange + + + + + 24 + + + Return success + + + + + 25 + + + Notifications for failures + + + Reference: Failure in Position Validation (Prepare) + + + + + Reference: Failure in Position Validation (Prepare) + + + + + alt + + + [If action == 'bulk-prepare'] + + + + + Message: + + + { + + + id: "<messageId>" + + + from: <ledgerName>, + + + to: <transferMessage.payerFsp>, + + + type: "application/json" + + + content: { + + + headers: <transferHeaders>, + + + payload: { + + + "errorInformation": { + + + "errorCode": 4001, + + + "errorDescription": "Payer FSP insufficient liquidity", + + + "extensionList": <transferMessage.extensionList> + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: "bulk-processing", + + + action: "bulk-prepare", + + + createdAt: <timestamp>, + + + state: { + + + status: "error", + + + code: <errorInformation.errorCode> + + + description: <errorInformation.errorDescription> + + + } + + + } + + + } + + + } + + + + + 26 + + + Publish Position failure event (in Prepare) to Bulk Processing Topic (for Payer) + + + Error codes: + + + 2003 + + + + [If action == 'prepare'] + + + + + Message: + + + { + + + id: "<messageId>" + + + from: <ledgerName>, + + + to: <transferMessage.payerFsp>, + + + type: "application/json" + + + content: { + + + headers: <transferHeaders>, + + + payload: { + + + "errorInformation": { + + + "errorCode": 4001, + + + "errorDescription": "Payer FSP insufficient liquidity", + + + "extensionList": <transferMessage.extensionList> + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: "notification", + + + action: "position", + + + createdAt: <timestamp>, + + + state: { + + + status: "error", + + + code: <errorInformation.errorCode> + + + description: <errorInformation.errorDescription> + + + } + + + } + + + } + + + } + + + + + 27 + + + Publish Notification (failure) event for Payer + + + Error code: + + + 2003 + + + + + Reference: Position Validation Success case (Prepare) + + + + + alt + + + [If action == 'bulk-prepare'] + + + + + Message: + + + { + + + id: "<messageId>" + + + from: <transferMessage.payerFsp>, + + + to: <transferMessage.payeeFsp>, + + + type: "application/json" + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: "bulk-processing", + + + action: "bulk-prepare", + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 28 + + + Publish Position Success event (in Prepare) to Bulk Processing Topic + + + Error codes: + + + 2003 + + + + [If action == 'prepare'] + + + + + Message: + + + { + + + id: "<messageId>" + + + from: <transferMessage.payerFsp>, + + + to: <transferMessage.payeeFsp>, + + + type: "application/json" + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: "notification", + + + action: "abort", + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 29 + + + Publish Notification event + + + Error code: + + + 2003 + + diff --git a/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.4.1-bulk-processing-handler.plantuml b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.4.1-bulk-processing-handler.plantuml new file mode 100644 index 000000000..35108f2bf --- /dev/null +++ b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.4.1-bulk-processing-handler.plantuml @@ -0,0 +1,332 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + -------------- + ******'/ + +@startuml +' declare title +title 1.4.0. Bulk Processing Handler Consume + +autonumber + +/'***** + Diagram notes + -------------- + RECEIVED/RECEIVED + from: prepare-handler , action: prepare-duplicate/success, result: PENDING_PREPARE/ACCEPTED & RECEIVED_DUPLICATE + from: prepare-handler , action: prepare-duplicate/error , result: PENDING_PREPARE/ACCEPTED & RECEIVED_DUPLICATE + from: prepare-handler , action: prepare/error , result: PENDING_PREPARE/ACCEPTED & RECEIVED_INVALID + from: position-handler, action: prepare/error , result: PENDING_PREPARE/ACCEPTED & RECEIVED_INVALID + from: position-handler, action: prepare/success , result: PENDING_PREPARE/ACCEPTED & ACCEPTED + from: timeout-handler , action: timeout-received/error , result: unchanged/COMPLETED & EXPIRED + -------------- + ACCEPTED/ACCEPTED + from: position-handler, action: timeout-reserved/error , result: unchanged/COMPLETED & EXPIRED + -------------- + PROCESSING/ACCEPTED + from: fulfil-handler , action: fulfil-duplicate/success , result: PENDING_FULFIL/COMPLETED & FULFIL_DUPLICATE + from: fulfil-handler , action: fulfil-duplicate/error , result: PENDING_FULFIL/COMPLETED & FULFIL_DUPLICATE + from: position-handler, action: commit/success , result: PENDING_FULFIL/COMPLETED & COMPLETED + from: position-handler, action: reject/success , result: PENDING_FULFIL/COMPLETED & REJECTED + from: position-handler, action: abort/error , result: PENDING_FULFIL/COMPLETED & FULFIL_INVALID + from: fulfil-handler , action: commit/error , result: PENDING_FULFIL/COMPLETED & FULFIL_INVALID + from: position-handler, action: timeout-reserved/error , result: unchanged/COMPLETED & EXPIRED + -------------- + COMPLETED/EXPIRED + -------------- + ******'/ + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +collections "topic-bulk-\nprocessing" as TOPIC_BULK_PROCESSING +control "Bulk Processing\nHandler" as BULK_PROC_HANDLER +collections "topic-event" as TOPIC_EVENTS +collections "mojaloop-\nobject-store\n(**MLOS**)" as OBJECT_STORE +collections "topic-notification" as TOPIC_NOTIFICATION +entity "Bulk DAO" as BULK_DAO +database "Central Store" as DB + +box "Central Service" #LightYellow + participant TOPIC_BULK_PROCESSING + participant BULK_PROC_HANDLER + participant TOPIC_EVENTS + participant OBJECT_STORE + participant TOPIC_NOTIFICATION + participant BULK_DAO + participant DB +end box + +' start flow +activate BULK_PROC_HANDLER +group Bulk Processing Handler Consume + TOPIC_BULK_PROCESSING <- BULK_PROC_HANDLER: Consume message + activate TOPIC_BULK_PROCESSING + deactivate TOPIC_BULK_PROCESSING + + break + group Validate Event + BULK_PROC_HANDLER <-> BULK_PROC_HANDLER: Validate event - Rule:\ntype == 'bulk-processing' && action IN\n['prepare-duplicate', 'bulk-prepare',\n'bulk-timeout-received', 'fulfil-duplicate',\n'bulk-commit', 'bulk-timeout-reserved']\nError codes: 2001 + end + end + + group Persist Event Information + ||| + BULK_PROC_HANDLER -> TOPIC_EVENTS: Publish event information + ref over BULK_PROC_HANDLER, TOPIC_EVENTS: Event Handler Consume\n + ||| + end + + group Process Message + BULK_PROC_HANDLER -> BULK_DAO: Retrieve current state of Bulk Transfer + activate BULK_DAO + BULK_DAO -> DB: Retrieve current state of Bulk Transfer + activate DB + hnote over DB #lightyellow + bulkTransfer + bulkTransferStateChange + end note + BULK_DAO <-- DB: Return **bulkTransferInfo** + deactivate DB + BULK_PROC_HANDLER <-- BULK_DAO: Return **bulkTransferInfo** + deactivate BULK_DAO + + group Validate Bulk Transfer State + note right of BULK_PROC_HANDLER #lightgrey + **Initialize variables**: + let criteriaState + let incompleteBulkState + let completedBulkState + let bulkTransferState + let processingState + let errorCode, errorMessage + let produceNotification = false + end note + alt bulkTransferInfo.bulkTransferState IN ['RECEIVED', 'PENDING_PREPARE'] + note right of BULK_PROC_HANDLER #lightgrey + criteriaState = 'RECEIVED' + incompleteBulkState = 'PENDING_PREPARE' + completedBulkState = 'ACCEPTED' + end note + alt action == 'prepare-duplicate' AND state.status == 'error' + note right of BULK_PROC_HANDLER #lightgrey + processingState = 'RECEIVED_DUPLICATE' + errorCode = payload.errorInformation.errorCode + errorDescription = payload.errorInformation.errorDescription + end note + else action == 'bulk-prepare' AND state.status == 'error' + note right of BULK_PROC_HANDLER #lightgrey + processingState = 'RECEIVED_INVALID' + errorCode = payload.errorInformation.errorCode + errorDescription = payload.errorInformation.errorDescription + end note + else action == 'bulk-prepare' AND state.status == 'success' + note right of BULK_PROC_HANDLER #lightgrey + processingState = 'ACCEPTED' + end note + else action IN ['bulk-timeout-received', 'bulk-timeout-reserved'] + note right of BULK_PROC_HANDLER #lightgrey + incompleteBulkState = 'EXPIRING' + completedBulkState = 'COMPLETED' + processingState = 'EXPIRED' + errorCode = payload.errorInformation.errorCode + errorDescription = payload.errorInformation.errorDescription + end note + else all other actions + note right of BULK_PROC_HANDLER #lightgrey + throw ErrorHandler.Factory.createFSPIOPError(INTERNAL_SERVER_ERROR) + end note + end + else bulkTransferInfo.bulkTransferState IN ['ACCEPTED'] + alt action == 'bulk-timeout-reserved' + note right of BULK_PROC_HANDLER #lightgrey + criteriaState = 'ACCEPTED' + incompleteBulkState = 'EXPIRING' + completedBulkState = 'COMPLETED' + processingState = 'EXPIRED' + end note + else all other actions + note right of BULK_PROC_HANDLER #lightgrey + throw ErrorHandler.Factory.createFSPIOPError(INTERNAL_SERVER_ERROR) + end note + end + else bulkTransferInfo.bulkTransferState IN ['PROCESSING', 'PENDING_FULFIL', 'EXPIRING'] + note right of BULK_PROC_HANDLER #lightgrey + criteriaState = 'PROCESSING' + incompleteBulkState = 'PENDING_FULFIL' + completedBulkState = 'COMPLETED' + end note + alt action == 'fulfil-duplicate' + note right of BULK_PROC_HANDLER #lightgrey + processingState = 'FULFIL_DUPLICATE' + end note + else action == 'bulk-commit' AND state.status == 'success' + note right of BULK_PROC_HANDLER #lightgrey + processingState = 'COMPLETED' + end note + else action == 'reject' AND state.status == 'success' + note right of BULK_PROC_HANDLER #lightgrey + processingState = 'REJECTED' + end note + else action IN ['commit', 'abort'] AND state.status == 'error' + note right of BULK_PROC_HANDLER #lightgrey + processingState = 'FULFIL_INVALID' + end note + else action == 'bulk-timeout-reserved' + note right of BULK_PROC_HANDLER #lightgrey + incompleteBulkState = 'EXPIRING' + completedBulkState = 'COMPLETED' + processingState = 'EXPIRED' + errorCode = payload.errorInformation.errorCode + errorDescription = payload.errorInformation.errorDescription + end note + else all other actions + note right of BULK_PROC_HANDLER #lightgrey + throw ErrorHandler.Factory.createFSPIOPError(INTERNAL_SERVER_ERROR) + end note + end + else all other ['PENDING_INVALID', 'COMPLETED', 'REJECTED', 'INVALID'] + note right of BULK_PROC_HANDLER #lightgrey + throw ErrorHandler.Factory.createFSPIOPError(INTERNAL_SERVER_ERROR) + end note + end + end + + BULK_PROC_HANDLER -> BULK_DAO: Persist individual transfer processing state + activate BULK_DAO + BULK_DAO -> DB: Persist individual transfer processing state\n-- store errorCode/errorMessage when\nstate.status == 'error' + activate DB + hnote over DB #lightyellow + bulkTransferAssociation + end note + deactivate DB + BULK_PROC_HANDLER <-- BULK_DAO: Return success + deactivate BULK_DAO + + BULK_PROC_HANDLER -> BULK_DAO: Check previously defined completion criteria + activate BULK_DAO + BULK_DAO -> DB: Select EXISTS (LIMIT 1) in criteriaState + activate DB + hnote over DB #lightyellow + bulkTransferAssociation + end note + BULK_DAO <-- DB: Return **existingIndividualTransfer** + deactivate DB + BULK_PROC_HANDLER <-- BULK_DAO: Return **existingIndividualTransfer** + deactivate BULK_DAO + + alt individual transfer exists + note right of BULK_PROC_HANDLER #lightgrey + bulkTransferState = incompleteBulkState + end note + else no transfer in criteriaState exists + note right of BULK_PROC_HANDLER #lightgrey + bulkTransferState = completedBulkState + produceNotification = true + end note + end + + BULK_PROC_HANDLER -> BULK_DAO: Persist bulkTransferState from previous step + activate BULK_DAO + BULK_DAO -> DB: Persist bulkTransferState + activate DB + deactivate DB + hnote over DB #lightyellow + bulkTransferStateChange + end note + BULK_PROC_HANDLER <-- BULK_DAO: Return success + deactivate BULK_DAO + + + alt produceNotification == true + BULK_PROC_HANDLER -> BULK_DAO: Request to retrieve all bulk transfer and individual transfer results + activate BULK_DAO + BULK_DAO -> DB: Get bulkTransferResult + activate DB + hnote over DB #lightyellow + bulkTransfer + bulkTransferStateChange + bulkTransferAssociation + end note + BULK_DAO <-- DB: Return **bulkTransferResult** + deactivate DB + BULK_PROC_HANDLER <-- BULK_DAO: Return **bulkTransferResult** + deactivate BULK_DAO + + group Send Bulk Notification(s) + note right of BULK_PROC_HANDLER #lightgrey + Depending on the action decide where to + send notification: payer, payee OR both + end note + + BULK_PROC_HANDLER -> OBJECT_STORE: Generate & Persist bulk message to object store:\n**MLOS.bulkTransferResults** by destination + activate OBJECT_STORE + OBJECT_STORE --> BULK_PROC_HANDLER: Return reference to the stored object(s)\n**MLOS.bulkTransferResults.messageId** + deactivate OBJECT_STORE + note right of BULK_PROC_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: "application/json" + content: { + headers: , + payload: { + bulkTransferId: , + bulkTransferState: + } + }, + metadata: { + event: { + id: , + responseTo: , + type: "notification", + action: "bulk-[prepare | commit | abort | processing]", + createdAt: , + state: { + status: state.status, + code: state.code + } + } + } + } + end note + + BULK_PROC_HANDLER -> TOPIC_NOTIFICATION: Publish Notification event for Payer/Payee\nError codes: 2003 + activate TOPIC_NOTIFICATION + deactivate TOPIC_NOTIFICATION + end + else produceNotification == false + note right of BULK_PROC_HANDLER #lightgrey + Do nothing (awaitAllTransfers) + end note + end + end +end +deactivate BULK_PROC_HANDLER +@enduml diff --git a/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.4.1-bulk-processing-handler.svg b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.4.1-bulk-processing-handler.svg new file mode 100644 index 000000000..fa4186d7d --- /dev/null +++ b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-1.4.1-bulk-processing-handler.svg @@ -0,0 +1,860 @@ + + + + + + + + + + + 1.4.0. Bulk Processing Handler Consume + + + + Central Service + + + + + + + + + + + + + + + + + + + + + + + + + topic-bulk- + + + processing + + + + + topic-bulk- + + + processing + + + Bulk Processing + + + Handler + + + + + Bulk Processing + + + Handler + + + + + + + topic-event + + + + + topic-event + + + + + mojaloop- + + + object-store + + + ( + + + MLOS + + + ) + + + + + mojaloop- + + + object-store + + + ( + + + MLOS + + + ) + + + + + topic-notification + + + + + topic-notification + + + Bulk DAO + + + + + Bulk DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Bulk Processing Handler Consume + + + + + 1 + + + Consume message + + + + + break + + + + + Validate Event + + + + + 2 + + + Validate event - Rule: + + + type == 'bulk-processing' && action IN + + + ['prepare-duplicate', 'bulk-prepare', + + + 'bulk-timeout-received', 'fulfil-duplicate', + + + 'bulk-commit', 'bulk-timeout-reserved'] + + + Error codes: + + + 2001 + + + + + Persist Event Information + + + + + 3 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + Process Message + + + + + 4 + + + Retrieve current state of Bulk Transfer + + + + + 5 + + + Retrieve current state of Bulk Transfer + + + + bulkTransfer + + + bulkTransferStateChange + + + + + 6 + + + Return + + + bulkTransferInfo + + + + + 7 + + + Return + + + bulkTransferInfo + + + + + Validate Bulk Transfer State + + + + + Initialize variables + + + : + + + let criteriaState + + + let incompleteBulkState + + + let completedBulkState + + + let bulkTransferState + + + let processingState + + + let errorCode, errorMessage + + + let produceNotification = false + + + + + alt + + + [bulkTransferInfo.bulkTransferState IN ['RECEIVED', 'PENDING_PREPARE']] + + + + + criteriaState = 'RECEIVED' + + + incompleteBulkState = 'PENDING_PREPARE' + + + completedBulkState = 'ACCEPTED' + + + + + alt + + + [action == 'prepare-duplicate' AND state.status == 'error'] + + + + + processingState = 'RECEIVED_DUPLICATE' + + + errorCode = payload.errorInformation.errorCode + + + errorDescription = payload.errorInformation.errorDescription + + + + [action == 'bulk-prepare' AND state.status == 'error'] + + + + + processingState = 'RECEIVED_INVALID' + + + errorCode = payload.errorInformation.errorCode + + + errorDescription = payload.errorInformation.errorDescription + + + + [action == 'bulk-prepare' AND state.status == 'success'] + + + + + processingState = 'ACCEPTED' + + + + [action IN ['bulk-timeout-received', 'bulk-timeout-reserved']] + + + + + incompleteBulkState = 'EXPIRING' + + + completedBulkState = 'COMPLETED' + + + processingState = 'EXPIRED' + + + errorCode = payload.errorInformation.errorCode + + + errorDescription = payload.errorInformation.errorDescription + + + + [all other actions] + + + + + throw + + + ErrorHandler.Factory.createFSPIOPError(INTERNAL_SERVER_ERROR) + + + + [bulkTransferInfo.bulkTransferState IN ['ACCEPTED']] + + + + + alt + + + [action == 'bulk-timeout-reserved'] + + + + + criteriaState = 'ACCEPTED' + + + incompleteBulkState = 'EXPIRING' + + + completedBulkState = 'COMPLETED' + + + processingState = 'EXPIRED' + + + + [all other actions] + + + + + throw + + + ErrorHandler.Factory.createFSPIOPError(INTERNAL_SERVER_ERROR) + + + + [bulkTransferInfo.bulkTransferState IN ['PROCESSING', 'PENDING_FULFIL', 'EXPIRING']] + + + + + criteriaState = 'PROCESSING' + + + incompleteBulkState = 'PENDING_FULFIL' + + + completedBulkState = 'COMPLETED' + + + + + alt + + + [action == 'fulfil-duplicate'] + + + + + processingState = 'FULFIL_DUPLICATE' + + + + [action == 'bulk-commit' AND state.status == 'success'] + + + + + processingState = 'COMPLETED' + + + + [action == 'reject' AND state.status == 'success'] + + + + + processingState = 'REJECTED' + + + + [action IN ['commit', 'abort'] AND state.status == 'error'] + + + + + processingState = 'FULFIL_INVALID' + + + + [action == 'bulk-timeout-reserved'] + + + + + incompleteBulkState = 'EXPIRING' + + + completedBulkState = 'COMPLETED' + + + processingState = 'EXPIRED' + + + errorCode = payload.errorInformation.errorCode + + + errorDescription = payload.errorInformation.errorDescription + + + + [all other actions] + + + + + throw + + + ErrorHandler.Factory.createFSPIOPError(INTERNAL_SERVER_ERROR) + + + + [all other ['PENDING_INVALID', 'COMPLETED', 'REJECTED', 'INVALID']] + + + + + throw + + + ErrorHandler.Factory.createFSPIOPError(INTERNAL_SERVER_ERROR) + + + + + 8 + + + Persist individual transfer processing state + + + + + 9 + + + Persist individual transfer processing state + + + -- store errorCode/errorMessage when + + + state.status == 'error' + + + + bulkTransferAssociation + + + + + 10 + + + Return success + + + + + 11 + + + Check previously defined completion criteria + + + + + 12 + + + Select EXISTS (LIMIT 1) in criteriaState + + + + bulkTransferAssociation + + + + + 13 + + + Return + + + existingIndividualTransfer + + + + + 14 + + + Return + + + existingIndividualTransfer + + + + + alt + + + [individual transfer exists] + + + + + bulkTransferState = incompleteBulkState + + + + [no transfer in criteriaState exists] + + + + + bulkTransferState = completedBulkState + + + produceNotification = true + + + + + 15 + + + Persist bulkTransferState from previous step + + + + + 16 + + + Persist bulkTransferState + + + + bulkTransferStateChange + + + + + 17 + + + Return success + + + + + alt + + + [produceNotification == true] + + + + + 18 + + + Request to retrieve all bulk transfer and individual transfer results + + + + + 19 + + + Get bulkTransferResult + + + + bulkTransfer + + + bulkTransferStateChange + + + bulkTransferAssociation + + + + + 20 + + + Return + + + bulkTransferResult + + + + + 21 + + + Return + + + bulkTransferResult + + + + + Send Bulk Notification(s) + + + + + Depending on the action decide where to + + + send notification: payer, payee OR both + + + + + 22 + + + Generate & Persist bulk message to object store: + + + MLOS.bulkTransferResults + + + by destination + + + + + 23 + + + Return reference to the stored object(s) + + + MLOS.bulkTransferResults.messageId + + + + + Message: + + + { + + + id: <messageId> + + + from: <source>, + + + to: <destination>, + + + type: "application/json" + + + content: { + + + headers: <bulkTransferHeaders>, + + + payload: { + + + bulkTransferId: <uuid>, + + + bulkTransferState: <string> + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: "notification", + + + action: "bulk-[prepare | commit | abort | processing]", + + + createdAt: <timestamp>, + + + state: { + + + status: state.status, + + + code: state.code + + + } + + + } + + + } + + + } + + + + + 24 + + + Publish Notification event for Payer/Payee + + + Error codes: + + + 2003 + + + + [produceNotification == false] + + + + + Do nothing (awaitAllTransfers) + + diff --git a/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.1.0-bulk-fulfil-overview.plantuml b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.1.0-bulk-fulfil-overview.plantuml new file mode 100644 index 000000000..01e413e4d --- /dev/null +++ b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.1.0-bulk-fulfil-overview.plantuml @@ -0,0 +1,226 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + -------------- + ******'/ + +@startuml +' declate title +title 2.1.0. DFSP2 sends a Bulk Fulfil Success Transfer request + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +actor "DFSP1\nPayer" as DFSP1 +actor "DFSP2\nPayee" as DFSP2 +boundary "ML API Adapter" as MLAPI +control "ML API \nNotification Handler" as NOTIFY_HANDLER +collections "mongo-\nobject-store" as OBJECT_STORE +boundary "Central Service API" as CSAPI +collections "topic-\nbulk-fulfil" as TOPIC_BULK_FULFIL +control "Bulk Fulfil\nHandler" as BULK_FULFIL_HANDLER +collections "topic-\nfulfil" as TOPIC_FULFIL +control "Fulfil \nHandler" as FULF_HANDLER +collections "topic-\ntransfer-position" as TOPIC_TRANSFER_POSITION +control "Position \nHandler" as POS_HANDLER +collections "topic-\nbulk-processing" as TOPIC_BULK_PROCESSING +control "Bulk Processing\nHandler" as BULK_PROC_HANDLER +collections "topic-\nnotification" as TOPIC_NOTIFICATIONS + +box "Financial Service Providers" #lightGray + participant DFSP1 + participant DFSP2 +end box + +box "ML API Adapter Service" #LightBlue + participant MLAPI + participant NOTIFY_HANDLER +end box + +box "Central Service" #LightYellow + participant OBJECT_STORE + participant CSAPI + participant TOPIC_BULK_FULFIL + participant BULK_FULFIL_HANDLER + participant TOPIC_FULFIL + participant FULF_HANDLER + participant TOPIC_TRANSFER_POSITION + participant POS_HANDLER + participant TOPIC_BULK_PROCESSING + participant BULK_PROC_HANDLER + participant TOPIC_NOTIFICATIONS +end box + +' start flow +activate NOTIFY_HANDLER +activate BULK_FULFIL_HANDLER +activate FULF_HANDLER +activate POS_HANDLER +activate BULK_PROC_HANDLER +group DFSP2 sends a Bulk Fulfil Success Transfer request to DFSP1 + note right of DFSP2 #yellow + Headers - transferHeaders: { + Content-Length: , + Content-Type: , + Date: , + FSPIOP-Source: , + FSPIOP-Destination: , + FSPIOP-Encryption: , + FSPIOP-Signature: , + FSPIOP-URI: , + FSPIOP-HTTP-Method: + } + + Payload - bulkTransferMessage: + { + bulkTransferState: , + completedTimestamp: , + individualTransferResults: + [ + { + transferId: , + fulfilment: , + extensionList: { extension: [ + { key: , value: } + ] } + } + ], + extensionList: { extension: [ + { key: , value: } + ] } + } + end note + DFSP2 ->> MLAPI: PUT - /bulkTransfers/ + activate MLAPI + MLAPI -> MLAPI: Validate incoming message\nError codes: 3000-3002, 3100-3107 + MLAPI -> OBJECT_STORE: Persist incoming bulk message to\nobject store: **MLOS.individualTransferFulfils** + activate OBJECT_STORE + OBJECT_STORE --> MLAPI: Return messageId reference to the stored object(s) + deactivate OBJECT_STORE + note right of MLAPI #yellow + Message: + { + id: , + from: , + to: , + type: "application/json", + content: { + headers: , + payload: { + bulkTransferId: , + bulkTransferState: "COMPLETED", + completedTimestamp: , + extensionList: { extension: [ + { key: , value: } + ] }, + count: , + hash: + } + }, + metadata: { + event: { + id: , + type: "bulk-fulfil", + action: "bulk-commit", + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + MLAPI -> TOPIC_BULK_FULFIL: Route & Publish Bulk Fulfil event for Payee\nError code: 2003 + activate TOPIC_BULK_FULFIL + TOPIC_BULK_FULFIL <-> TOPIC_BULK_FULFIL: Ensure event is replicated \nas configured (ACKS=all)\nError code: 2003 + TOPIC_BULK_FULFIL --> MLAPI: Respond replication acknowledgements \nhave been received + deactivate TOPIC_BULK_FULFIL + MLAPI -->> DFSP2: Respond HTTP - 200 (OK) + deactivate MLAPI + TOPIC_BULK_FULFIL <- BULK_FULFIL_HANDLER: Consume message + BULK_FULFIL_HANDLER -> OBJECT_STORE: Retrieve individual transfers by key:\n**MLOS.individualTransferFulfils.messageId** + activate OBJECT_STORE + OBJECT_STORE --> BULK_FULFIL_HANDLER: Stream bulk's individual transfers + deactivate OBJECT_STORE + ref over TOPIC_BULK_FULFIL, TOPIC_FULFIL: Bulk Prepare Handler Consume \n + alt Success + BULK_FULFIL_HANDLER -> TOPIC_FULFIL: Produce (stream) single transfer message\nfor each individual transfer [loop] + else Failure + BULK_FULFIL_HANDLER --> TOPIC_NOTIFICATIONS: Produce single message for the entire bulk + end + ||| + TOPIC_FULFIL <- FULF_HANDLER: Consume message + ref over TOPIC_FULFIL, TOPIC_TRANSFER_POSITION: Fulfil Handler Consume (Success)\n + alt Success + FULF_HANDLER -> TOPIC_TRANSFER_POSITION: Produce message + else Failure + FULF_HANDLER --> TOPIC_BULK_PROCESSING: Produce message + end + ||| + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume message + ref over TOPIC_TRANSFER_POSITION, TOPIC_BULK_PROCESSING: Position Handler Consume (Success)\n + POS_HANDLER -> TOPIC_BULK_PROCESSING: Produce message + ||| + TOPIC_BULK_PROCESSING <- BULK_PROC_HANDLER: Consume message + ref over TOPIC_BULK_PROCESSING, TOPIC_NOTIFICATIONS: Bulk Processing Handler Consume (Success)\n + BULK_PROC_HANDLER -> OBJECT_STORE: Persist bulk message by destination to the\nobject store: **MLOS.bulkTransferResults** + activate OBJECT_STORE + OBJECT_STORE --> BULK_PROC_HANDLER: Return the reference to the stored \nnotification object(s): **messageId** + deactivate OBJECT_STORE + BULK_PROC_HANDLER -> TOPIC_NOTIFICATIONS: Send Bulk Commit notification + ||| + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message + NOTIFY_HANDLER -> OBJECT_STORE: Retrieve bulk notification(s) by reference & destination:\n**MLOS.bulkTransferResults.messageId + destination** + activate OBJECT_STORE + OBJECT_STORE --> NOTIFY_HANDLER: Return notification payload + deactivate OBJECT_STORE + opt action == 'bulk-commit' + ||| + ref over DFSP1, TOPIC_NOTIFICATIONS: Send notification to Participant (Payer)\n + NOTIFY_HANDLER -> DFSP1: Send callback notification + end + ||| + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message + NOTIFY_HANDLER -> OBJECT_STORE: Retrieve bulk notification(s) by reference & destination:\n**MLOS.bulkTransferResults.messageId + destination** + activate OBJECT_STORE + OBJECT_STORE --> NOTIFY_HANDLER: Return notification payload + deactivate OBJECT_STORE + opt action == 'bulk-commit' + ||| + ref over DFSP2, TOPIC_NOTIFICATIONS: Send notification to Participant (Payee)\n + NOTIFY_HANDLER -> DFSP2: Send callback notification + end + ||| +end +deactivate POS_HANDLER +activate BULK_FULFIL_HANDLER +deactivate FULF_HANDLER +deactivate BULK_PROC_HANDLER +deactivate NOTIFY_HANDLER +@enduml diff --git a/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.1.0-bulk-fulfil-overview.svg b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.1.0-bulk-fulfil-overview.svg new file mode 100644 index 000000000..90d6889fc --- /dev/null +++ b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.1.0-bulk-fulfil-overview.svg @@ -0,0 +1,835 @@ + + + + + + + + + + + 2.1.0. DFSP2 sends a Bulk Fulfil Success Transfer request + + + + Financial Service Providers + + + + ML API Adapter Service + + + + Central Service + + + + + + + + + + + DFSP1 + + + Payer + + + + + DFSP1 + + + Payer + + + + + DFSP2 + + + Payee + + + + + DFSP2 + + + Payee + + + + + ML API Adapter + + + + + ML API Adapter + + + + + ML API + + + Notification Handler + + + + + ML API + + + Notification Handler + + + + + + + mongo- + + + object-store + + + + + mongo- + + + object-store + + + Central Service API + + + + + Central Service API + + + + + + + topic- + + + bulk-fulfil + + + + + topic- + + + bulk-fulfil + + + Bulk Fulfil + + + Handler + + + + + Bulk Fulfil + + + Handler + + + + + + + topic- + + + fulfil + + + + + topic- + + + fulfil + + + Fulfil + + + Handler + + + + + Fulfil + + + Handler + + + + + + + topic- + + + transfer-position + + + + + topic- + + + transfer-position + + + Position + + + Handler + + + + + Position + + + Handler + + + + + + + topic- + + + bulk-processing + + + + + topic- + + + bulk-processing + + + Bulk Processing + + + Handler + + + + + Bulk Processing + + + Handler + + + + + + + topic- + + + notification + + + + + topic- + + + notification + + + + + + DFSP2 sends a Bulk Fulfil Success Transfer request to DFSP1 + + + + + Headers - transferHeaders: { + + + Content-Length: <int>, + + + Content-Type: <string>, + + + Date: <date>, + + + FSPIOP-Source: <string>, + + + FSPIOP-Destination: <string>, + + + FSPIOP-Encryption: <string>, + + + FSPIOP-Signature: <string>, + + + FSPIOP-URI: <uri>, + + + FSPIOP-HTTP-Method: <string> + + + } + + + Payload - bulkTransferMessage: + + + { + + + bulkTransferState: <bulkTransferState>, + + + completedTimestamp: <completedTimeStamp>, + + + individualTransferResults: + + + [ + + + { + + + transferId: <uuid>, + + + fulfilment: <ilpCondition>, + + + extensionList: { extension: [ + + + { key: <string>, value: <string> } + + + ] } + + + } + + + ], + + + extensionList: { extension: [ + + + { key: <string>, value: <string> } + + + ] } + + + } + + + + 1 + + + PUT - /bulkTransfers/<ID> + + + + + 2 + + + Validate incoming message + + + Error codes: + + + 3000-3002, 3100-3107 + + + + + 3 + + + Persist incoming bulk message to + + + object store: + + + MLOS.individualTransferFulfils + + + + + 4 + + + Return messageId reference to the stored object(s) + + + + + Message: + + + { + + + id: <messageId>, + + + from: <payeeFspName>, + + + to: <payerFspName>, + + + type: "application/json", + + + content: { + + + headers: <bulkTransferHeaders>, + + + payload: { + + + bulkTransferId: <uuid>, + + + bulkTransferState: "COMPLETED", + + + completedTimestamp: <timestamp>, + + + extensionList: { extension: [ + + + { key: <string>, value: <string> } + + + ] }, + + + count: <int>, + + + hash: <string> + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + type: "bulk-fulfil", + + + action: "bulk-commit", + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 5 + + + Route & Publish Bulk Fulfil event for Payee + + + Error code: + + + 2003 + + + + + 6 + + + Ensure event is replicated + + + as configured (ACKS=all) + + + Error code: + + + 2003 + + + + + 7 + + + Respond replication acknowledgements + + + have been received + + + + + 8 + + + Respond HTTP - 200 (OK) + + + + + 9 + + + Consume message + + + + + 10 + + + Retrieve individual transfers by key: + + + MLOS.individualTransferFulfils.messageId + + + + + 11 + + + Stream bulk's individual transfers + + + + + ref + + + Bulk Prepare Handler Consume + + + + + alt + + + [Success] + + + + + 12 + + + Produce (stream) single transfer message + + + for each individual transfer [loop] + + + + [Failure] + + + + + 13 + + + Produce single message for the entire bulk + + + + + 14 + + + Consume message + + + + + ref + + + Fulfil Handler Consume (Success) + + + + + alt + + + [Success] + + + + + 15 + + + Produce message + + + + [Failure] + + + + + 16 + + + Produce message + + + + + 17 + + + Consume message + + + + + ref + + + Position Handler Consume (Success) + + + + + 18 + + + Produce message + + + + + 19 + + + Consume message + + + + + ref + + + Bulk Processing Handler Consume (Success) + + + + + 20 + + + Persist bulk message by destination to the + + + object store: + + + MLOS.bulkTransferResults + + + + + 21 + + + Return the reference to the stored + + + notification object(s): + + + messageId + + + + + 22 + + + Send Bulk Commit notification + + + + + 23 + + + Consume message + + + + + 24 + + + Retrieve bulk notification(s) by reference & destination: + + + MLOS.bulkTransferResults.messageId + destination + + + + + 25 + + + Return notification payload + + + + + opt + + + [action == 'bulk-commit'] + + + + + ref + + + Send notification to Participant (Payer) + + + + + 26 + + + Send callback notification + + + + + 27 + + + Consume message + + + + + 28 + + + Retrieve bulk notification(s) by reference & destination: + + + MLOS.bulkTransferResults.messageId + destination + + + + + 29 + + + Return notification payload + + + + + opt + + + [action == 'bulk-commit'] + + + + + ref + + + Send notification to Participant (Payee) + + + + + 30 + + + Send callback notification + + diff --git a/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.1.1-bulk-fulfil-handler.plantuml b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.1.1-bulk-fulfil-handler.plantuml new file mode 100644 index 000000000..b5b87dfc6 --- /dev/null +++ b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.1.1-bulk-fulfil-handler.plantuml @@ -0,0 +1,311 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + -------------- + ******'/ + +@startuml +' declare title +title 2.1.1. Bulk Fulfil Handler Consume + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +collections "mongo-\nobject-store" as OBJECT_STORE +collections "topic-bulk-\nfulfil" as TOPIC_BULK_FULFIL +collections "topic-bulk-\nprocessing" as TOPIC_BULK_PROCESSING +control "Bulk Fulfil\nHandler" as BULK_FULF_HANDLER +collections "topic-transfer-\nfulfil" as TOPIC_TRANSFER_FULFIL +collections "topic-event" as TOPIC_EVENTS +collections "topic-notification" as TOPIC_NOTIFICATION +entity "Bulk DAO" as BULK_DAO +database "Central Store" as DB + +box "Central Service" #LightYellow + participant OBJECT_STORE + participant TOPIC_BULK_FULFIL + participant BULK_FULF_HANDLER + participant TOPIC_TRANSFER_FULFIL + participant TOPIC_BULK_PROCESSING + participant TOPIC_EVENTS + participant TOPIC_NOTIFICATION + participant BULK_DAO + participant DB +end box + +' start flow +activate BULK_FULF_HANDLER +group Bulk Fulfil Handler Consume + TOPIC_BULK_FULFIL <- BULK_FULF_HANDLER: Consume message + activate TOPIC_BULK_FULFIL + deactivate TOPIC_BULK_FULFIL + + break + group Validate Event + BULK_FULF_HANDLER <-> BULK_FULF_HANDLER: Validate event - Rule:\ntype == 'bulk-fulfil' && action == 'bulk-commit'\nError codes: 2001 + end + end + + group Persist Event Information + ||| + BULK_FULF_HANDLER -> TOPIC_EVENTS: Publish event information + ref over BULK_FULF_HANDLER, TOPIC_EVENTS: Event Handler Consume \n + ||| + end + + group Validate FSPIOP-Signature + ||| + ref over BULK_FULF_HANDLER, TOPIC_NOTIFICATION: Validate message.content.headers.**FSPIOP-Signature**\nError codes: 3105/3106\n + ||| + end + + group Validate Bulk Fulfil Transfer + BULK_FULF_HANDLER <-> BULK_FULF_HANDLER: Schema validation of the incoming message + BULK_FULF_HANDLER <-> BULK_FULF_HANDLER: Verify the message's signature\n(to be confirmed in future requirement) + note right of BULK_FULF_HANDLER #lightgrey + The above validation steps are already handled by the + Bulk-API-Adapter for the open source implementation. + It may need to be added in future for custom adapters. + end note + + group Validate Duplicate Check + ||| + BULK_FULF_HANDLER -> DB: Request Duplicate Check + ref over BULK_FULF_HANDLER, DB: Request Duplicate Check\n + DB --> BULK_FULF_HANDLER: Return { hasDuplicateId: Boolean, hasDuplicateHash: Boolean } + end + + alt hasDuplicateId == TRUE && hasDuplicateHash == TRUE + break + BULK_FULF_HANDLER -> BULK_DAO: Request to retrieve Bulk Transfer state & completedTimestamp\nError code: 2003 + activate BULK_DAO + BULK_DAO -> DB: Query database + hnote over DB #lightyellow + bulkTransfer + bulkTransferFulfilment + bulkTransferStateChange + end note + activate DB + BULK_DAO <-- DB: Return resultset + deactivate DB + BULK_DAO --> BULK_FULF_HANDLER: Return **bulkTransferStateId** & **completedTimestamp** (not null when completed) + deactivate BULK_DAO + + note right of BULK_FULF_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: { + bulkTransferState: , + completedTimestamp: + } + }, + metadata: { + event: { + id: , + responseTo: , + type: "notification", + action: "bulk-fulfil-duplicate", + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + BULK_FULF_HANDLER -> TOPIC_NOTIFICATION: Publish Notification event for Payee + activate TOPIC_NOTIFICATION + deactivate TOPIC_NOTIFICATION + end + else hasDuplicateId == TRUE && hasDuplicateHash == FALSE + note right of BULK_FULF_HANDLER #yellow + { + id: , + from: , + type: "application/json", + content: { + headers: , + payload: { + errorInformation: { + errorCode: "3106", + errorDescription: "Modified request", + extensionList: { + extension: [ + { + key: "_cause", + value: + } + ] + } + }, + uriParams: { + id: + } + } + }, + metadata: { + correlationId: , + event: { + id: , + type: "notification", + action: "bulk-commit", + createdAt: , + state: { + status: "error", + code: "3106", + description: "Modified request" + }, + responseTo: + } + } + } + end note + BULK_FULF_HANDLER -> TOPIC_NOTIFICATION: Publish Notification (failure) event for Payer\nError codes: 3106 + activate TOPIC_NOTIFICATION + deactivate TOPIC_NOTIFICATION + else hasDuplicateId == FALSE + alt Validate Bulk Transfer Fulfil (success) + group Persist Bulk Transfer State (with bulktransferState='PROCESSING') + BULK_FULF_HANDLER -> BULK_DAO: Request to persist bulk transfer fulfil\nError codes: 2003 + activate BULK_DAO + BULK_DAO -> DB: Persist bulkTransferFulfilment + hnote over DB #lightyellow + bulkTransferFulfilment + bulkTransferStateChange + bulkTransferExtension + end note + activate DB + deactivate DB + BULK_DAO --> BULK_FULF_HANDLER: Return success + deactivate BULK_DAO + end + else Validate Bulk Transfer Fulfil (failure) + group Persist Bulk Transfer State (with bulkTransferState='INVALID/REJECTED') + BULK_FULF_HANDLER -> BULK_DAO: Request to persist bulk\ntransfer fulfil failure\nError codes: 2003 + activate BULK_DAO + BULK_DAO -> DB: Persist transfer + hnote over DB #lightyellow + bulkTransferFulfilment + bulkTransferStateChange + bulkTransferExtension + bulkTransferError + end note + activate DB + deactivate DB + BULK_DAO --> BULK_FULF_HANDLER: Return success + deactivate BULK_DAO + end + end + end + end + alt Validate Bulk Transfer Fulfil (success) + loop for every individual transfer in the bulk fulfil list + BULK_FULF_HANDLER -> OBJECT_STORE: Retrieve individual transfers from the bulk using\nreference: **MLOS.individualTransferFulfils.messageId** + activate OBJECT_STORE + OBJECT_STORE --> BULK_FULF_HANDLER: Stream bulk's individual transfer fulfils + deactivate OBJECT_STORE + + note right of BULK_FULF_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: "application/json" + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: "fulfil", + action: "bulk-commit", + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + BULK_FULF_HANDLER -> TOPIC_TRANSFER_FULFIL: Route & Publish Prepare event to the Payer for the Individual Transfer\nError codes: 2003 + activate TOPIC_TRANSFER_FULFIL + deactivate TOPIC_TRANSFER_FULFIL + end + else Validate Bulk Transfer Fulfil (failure) + note right of BULK_FULF_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: "application/json" + content: { + headers: , + payload: { + "errorInformation": { + "errorCode": + "errorDescription": "", + "extensionList": + } + }, + metadata: { + event: { + id: , + responseTo: , + type: "notification", + action: "bulk-abort", + createdAt: , + state: { + status: 'error', + code: + description: + } + } + } + } + end note + BULK_FULF_HANDLER -> TOPIC_NOTIFICATION: Publish Notification (failure) event for Payer\nError codes: 2003 + activate TOPIC_NOTIFICATION + deactivate TOPIC_NOTIFICATION + end +end +deactivate BULK_FULF_HANDLER +@enduml + diff --git a/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.1.1-bulk-fulfil-handler.svg b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.1.1-bulk-fulfil-handler.svg new file mode 100644 index 000000000..bb328dce5 --- /dev/null +++ b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.1.1-bulk-fulfil-handler.svg @@ -0,0 +1,954 @@ + + + + + + + + + + + 2.1.1. Bulk Fulfil Handler Consume + + + + Central Service + + + + + + + + + + + + + + + + + + + mongo- + + + object-store + + + + + mongo- + + + object-store + + + + + topic-bulk- + + + fulfil + + + + + topic-bulk- + + + fulfil + + + Bulk Fulfil + + + Handler + + + + + Bulk Fulfil + + + Handler + + + + + + + topic-transfer- + + + fulfil + + + + + topic-transfer- + + + fulfil + + + + + topic-bulk- + + + processing + + + + + topic-bulk- + + + processing + + + + + topic-event + + + + + topic-event + + + + + topic-notification + + + + + topic-notification + + + Bulk DAO + + + + + Bulk DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Bulk Fulfil Handler Consume + + + + + 1 + + + Consume message + + + + + break + + + + + Validate Event + + + + + 2 + + + Validate event - Rule: + + + type == 'bulk-fulfil' && action == 'bulk-commit' + + + Error codes: + + + 2001 + + + + + Persist Event Information + + + + + 3 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + Validate FSPIOP-Signature + + + + + ref + + + Validate message.content.headers. + + + FSPIOP-Signature + + + Error codes: + + + 3105/3106 + + + + + Validate Bulk Fulfil Transfer + + + + + 4 + + + Schema validation of the incoming message + + + + + 5 + + + Verify the message's signature + + + (to be confirmed in future requirement) + + + + + The above validation steps are already handled by the + + + Bulk-API-Adapter for the open source implementation. + + + It may need to be added in future for custom adapters. + + + + + Validate Duplicate Check + + + + + 6 + + + Request Duplicate Check + + + + + ref + + + Request Duplicate Check + + + + + 7 + + + Return { hasDuplicateId: Boolean, hasDuplicateHash: Boolean } + + + + + alt + + + [hasDuplicateId == TRUE && hasDuplicateHash == TRUE] + + + + + break + + + + + 8 + + + Request to retrieve Bulk Transfer state & completedTimestamp + + + Error code: + + + 2003 + + + + + 9 + + + Query database + + + + bulkTransfer + + + bulkTransferFulfilment + + + bulkTransferStateChange + + + + + 10 + + + Return resultset + + + + + 11 + + + Return + + + bulkTransferStateId + + + & + + + completedTimestamp + + + (not null when completed) + + + + + Message: + + + { + + + id: <messageId> + + + from: <ledgerName>, + + + to: <payeeFspName>, + + + type: application/json + + + content: { + + + headers: <bulkTransferHeaders>, + + + payload: { + + + bulkTransferState: <string>, + + + completedTimestamp: <optional> + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: "notification", + + + action: "bulk-fulfil-duplicate", + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 12 + + + Publish Notification event for Payee + + + + [hasDuplicateId == TRUE && hasDuplicateHash == FALSE] + + + + + { + + + id: <messageId>, + + + from: <ledgerName", + + + to: <payeeFspName>, + + + type: "application/json", + + + content: { + + + headers: <bulkTransferHeaders>, + + + payload: { + + + errorInformation: { + + + errorCode: "3106", + + + errorDescription: "Modified request", + + + extensionList: { + + + extension: [ + + + { + + + key: "_cause", + + + value: <FSPIOPError> + + + } + + + ] + + + } + + + }, + + + uriParams: { + + + id: <bulkTransferId> + + + } + + + } + + + }, + + + metadata: { + + + correlationId: <uuid>, + + + event: { + + + id: <uuid>, + + + type: "notification", + + + action: "bulk-commit", + + + createdAt: <timestamp>, + + + state: { + + + status: "error", + + + code: "3106", + + + description: "Modified request" + + + }, + + + responseTo: <uuid> + + + } + + + } + + + } + + + + + 13 + + + Publish Notification (failure) event for Payer + + + Error codes: + + + 3106 + + + + [hasDuplicateId == FALSE] + + + + + alt + + + [Validate Bulk Transfer Fulfil (success)] + + + + + Persist Bulk Transfer State (with bulktransferState='PROCESSING') + + + + + 14 + + + Request to persist bulk transfer fulfil + + + Error codes: + + + 2003 + + + + + 15 + + + Persist bulkTransferFulfilment + + + + bulkTransferFulfilment + + + bulkTransferStateChange + + + bulkTransferExtension + + + + + 16 + + + Return success + + + + [Validate Bulk Transfer Fulfil (failure)] + + + + + Persist Bulk Transfer State (with bulkTransferState='INVALID/REJECTED') + + + + + 17 + + + Request to persist bulk + + + transfer fulfil failure + + + Error codes: + + + 2003 + + + + + 18 + + + Persist transfer + + + + bulkTransferFulfilment + + + bulkTransferStateChange + + + bulkTransferExtension + + + bulkTransferError + + + + + 19 + + + Return success + + + + + alt + + + [Validate Bulk Transfer Fulfil (success)] + + + + + loop + + + [for every individual transfer in the bulk fulfil list] + + + + + 20 + + + Retrieve individual transfers from the bulk using + + + reference: + + + MLOS.individualTransferFulfils.messageId + + + + + 21 + + + Stream bulk's individual transfer fulfils + + + + + Message: + + + { + + + id: <messageId> + + + from: <payeeFspName>, + + + to: <payerFspName>, + + + type: "application/json" + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: "fulfil", + + + action: "bulk-commit", + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 22 + + + Route & Publish Prepare event to the Payer for the Individual Transfer + + + Error codes: + + + 2003 + + + + [Validate Bulk Transfer Fulfil (failure)] + + + + + Message: + + + { + + + id: <messageId> + + + from: <ledgerName>, + + + to: <payerFspName>, + + + type: "application/json" + + + content: { + + + headers: <bulkTransferHeaders>, + + + payload: { + + + "errorInformation": { + + + "errorCode": <possible codes: [2003, 3100, 3105, 3106, 3202, 3203, 3300, 3301]> + + + "errorDescription": "<refer to section 35.1.3 for description>", + + + "extensionList": <transferMessage.extensionList> + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: "notification", + + + action: "bulk-abort", + + + createdAt: <timestamp>, + + + state: { + + + status: 'error', + + + code: <errorInformation.errorCode> + + + description: <errorInformation.errorDescription> + + + } + + + } + + + } + + + } + + + + + 23 + + + Publish Notification (failure) event for Payer + + + Error codes: + + + 2003 + + diff --git a/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.2.1-fulfil-handler-commit.plantuml b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.2.1-fulfil-handler-commit.plantuml new file mode 100644 index 000000000..b53afd2e5 --- /dev/null +++ b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.2.1-fulfil-handler-commit.plantuml @@ -0,0 +1,236 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Rajiv Mothilal + * Sam Kummary + -------------- + ******'/ + +@startuml +' declate title +title 2.2.1. Fulfil Handler Consume (Success) individual transfers from Bulk + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store +' declare actors +collections "Fulfil-Topic" as TOPIC_FULFIL +control "Fulfil Handler" as FULF_HANDLER +collections "topic-\nevent" as TOPIC_EVENT +collections "topic-\ntransfer-position" as TOPIC_TRANSFER_POSITION +collections "topic-\nnotification" as TOPIC_NOTIFICATIONS +collections "topic-\nbulk-processing" as TOPIC_BULK_PROCESSING +entity "Position DAO" as POS_DAO +database "Central Store" as DB +box "Central Service" #LightYellow + participant TOPIC_FULFIL + participant FULF_HANDLER + participant TOPIC_TRANSFER_POSITION + participant TOPIC_EVENT + participant TOPIC_BULK_PROCESSING + participant TOPIC_NOTIFICATIONS + participant POS_DAO + participant DB +end box +' start flow +activate FULF_HANDLER +group Fulfil Handler Consume (Success) + TOPIC_FULFIL <- FULF_HANDLER: Consume Fulfil event message for Payer + activate TOPIC_FULFIL + deactivate TOPIC_FULFIL + break + group Validate Event + FULF_HANDLER <-> FULF_HANDLER: Validate event - Rule: type == 'fulfil' && action == 'bulk-commit'\nError codes: 2001 + end + end + group Persist Event Information + FULF_HANDLER -> TOPIC_EVENT: Publish event information + ref over FULF_HANDLER, TOPIC_EVENT: Event Handler Consume\n + end + group Validate FSPIOP-Signature + ||| + ref over FULF_HANDLER, TOPIC_NOTIFICATIONS: Validate message.content.headers.**FSPIOP-Signature**\nError codes: 3105/3106\n + ||| + end + + group Validate Duplicate Check + ||| + FULF_HANDLER -> DB: Request Duplicate Check + ref over FULF_HANDLER, DB: Request Duplicate Check\n + DB --> FULF_HANDLER: Return { hasDuplicateId: Boolean, hasDuplicateHash: Boolean } + end + + alt hasDuplicateId == TRUE && hasDuplicateHash == TRUE + break + FULF_HANDLER -> FULF_HANDLER: stateRecord = await getTransferState(transferId) + alt endStateList.includes(stateRecord.transferStateId) + ||| + ref over FULF_HANDLER, TOPIC_NOTIFICATIONS: getTransfer callback\n + FULF_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + else + note right of FULF_HANDLER #lightgrey + Ignore - resend in progress + end note + end + end + else hasDuplicateId == TRUE && hasDuplicateHash == FALSE + note right of FULF_HANDLER #lightgrey + Validate Prepare Transfer (failure) - Modified Request + end note + else hasDuplicateId == FALSE + + end + + group Validate and persist Transfer Fulfilment + FULF_HANDLER -> POS_DAO: Request information for the validate checks\nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Fetch from database + activate DB + hnote over DB #lightyellow + transfer + end note + DB --> POS_DAO + deactivate DB + FULF_HANDLER <-- POS_DAO: Return transfer + deactivate POS_DAO + FULF_HANDLER ->FULF_HANDLER: Validate that Transfer.ilpCondition = SHA-256 (content.payload.fulfilment)\nError code: 2001 + FULF_HANDLER -> FULF_HANDLER: Validate expirationDate\nError code: 3303 + + opt Transfer.ilpCondition validate successful + group Request current Settlement Window + FULF_HANDLER -> POS_DAO: Request to retrieve current/latest transfer settlement window\nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Fetch settlementWindowId + activate DB + hnote over DB #lightyellow + settlementWindow + end note + DB --> POS_DAO + deactivate DB + FULF_HANDLER <-- POS_DAO: Return settlementWindowId to be appended during transferFulfilment insert\n**TODO**: During settlement design make sure transfers in 'RECEIVED-FULFIL'\nstate are updated to the next settlement window + deactivate POS_DAO + end + end + + group Persist fulfilment + FULF_HANDLER -> POS_DAO: Persist fulfilment with the result of the above check (transferFulfilment.isValid)\nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Persist to database + activate DB + deactivate DB + hnote over DB #lightyellow + transferFulfilment + transferExtension + end note + FULF_HANDLER <-- POS_DAO: Return success + deactivate POS_DAO + end + + alt Transfer.ilpCondition validate successful + group Persist Transfer State (with transferState='RECEIVED-FULFIL') + FULF_HANDLER -> POS_DAO: Request to persist transfer state\nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Persist transfer state + activate DB + hnote over DB #lightyellow + transferStateChange + end note + deactivate DB + POS_DAO --> FULF_HANDLER: Return success + deactivate POS_DAO + end + + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: "application/json", + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: "position", + action: "bulk-commit", + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_TRANSFER_POSITION: Route & Publish Position event for Payee + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + else Validate Fulfil Transfer not successful + break + FULF_HANDLER -> FULF_HANDLER: Route & Publish Notification event for Payee\nReference: Failure in validation + end + end + end +end + +group Reference: Failure in validation + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: "application/json", + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: "bulk-processing", + action: "bulk-commit", + createdAt: , + state: { + status: "error", + code: 1 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_BULK_PROCESSING: Publish Notification event for Payee to Bulk Processing Topic\nError codes: 2003 + activate TOPIC_BULK_PROCESSING + deactivate TOPIC_BULK_PROCESSING +end + +deactivate FULF_HANDLER +@enduml diff --git a/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.2.1-fulfil-handler-commit.svg b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.2.1-fulfil-handler-commit.svg new file mode 100644 index 000000000..b89824971 --- /dev/null +++ b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.2.1-fulfil-handler-commit.svg @@ -0,0 +1,726 @@ + + + + + + + + + + + 2.2.1. Fulfil Handler Consume (Success) individual transfers from Bulk + + + + Central Service + + + + + + + + + + + + + + + + + + + Fulfil-Topic + + + + + Fulfil-Topic + + + Fulfil Handler + + + + + Fulfil Handler + + + + + + + topic- + + + transfer-position + + + + + topic- + + + transfer-position + + + + + topic- + + + event + + + + + topic- + + + event + + + + + topic- + + + bulk-processing + + + + + topic- + + + bulk-processing + + + + + topic- + + + notification + + + + + topic- + + + notification + + + Position DAO + + + + + Position DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Fulfil Handler Consume (Success) + + + + + 1 + + + Consume Fulfil event message for Payer + + + + + break + + + + + Validate Event + + + + + 2 + + + Validate event - Rule: type == 'fulfil' && action == 'bulk-commit' + + + Error codes: + + + 2001 + + + + + Persist Event Information + + + + + 3 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + Validate FSPIOP-Signature + + + + + ref + + + Validate message.content.headers. + + + FSPIOP-Signature + + + Error codes: + + + 3105/3106 + + + + + Validate Duplicate Check + + + + + 4 + + + Request Duplicate Check + + + + + ref + + + Request Duplicate Check + + + + + 5 + + + Return { hasDuplicateId: Boolean, hasDuplicateHash: Boolean } + + + + + alt + + + [hasDuplicateId == TRUE && hasDuplicateHash == TRUE] + + + + + break + + + + + 6 + + + stateRecord = await getTransferState(transferId) + + + + + alt + + + [endStateList.includes(stateRecord.transferStateId)] + + + + + ref + + + getTransfer callback + + + + + 7 + + + Produce message + + + + + + Ignore - resend in progress + + + + [hasDuplicateId == TRUE && hasDuplicateHash == FALSE] + + + + + Validate Prepare Transfer (failure) - Modified Request + + + + [hasDuplicateId == FALSE] + + + + + Validate and persist Transfer Fulfilment + + + + + 8 + + + Request information for the validate checks + + + Error code: + + + 2003 + + + + + 9 + + + Fetch from database + + + + transfer + + + + + 10 + + + + + 11 + + + Return transfer + + + + + 12 + + + Validate that Transfer.ilpCondition = SHA-256 (content.payload.fulfilment) + + + Error code: + + + 2001 + + + + + 13 + + + Validate expirationDate + + + Error code: + + + 3303 + + + + + opt + + + [Transfer.ilpCondition validate successful] + + + + + Request current Settlement Window + + + + + 14 + + + Request to retrieve current/latest transfer settlement window + + + Error code: + + + 2003 + + + + + 15 + + + Fetch settlementWindowId + + + + settlementWindow + + + + + 16 + + + + + 17 + + + Return settlementWindowId to be appended during transferFulfilment insert + + + TODO + + + : During settlement design make sure transfers in 'RECEIVED-FULFIL' + + + state are updated to the next settlement window + + + + + Persist fulfilment + + + + + 18 + + + Persist fulfilment with the result of the above check (transferFulfilment.isValid) + + + Error code: + + + 2003 + + + + + 19 + + + Persist to database + + + + transferFulfilment + + + transferExtension + + + + + 20 + + + Return success + + + + + alt + + + [Transfer.ilpCondition validate successful] + + + + + Persist Transfer State (with transferState='RECEIVED-FULFIL') + + + + + 21 + + + Request to persist transfer state + + + Error code: + + + 2003 + + + + + 22 + + + Persist transfer state + + + + transferStateChange + + + + + 23 + + + Return success + + + + + Message: + + + { + + + id: <messageId>, + + + from: <payeeFspName>, + + + to: <payerFspName>, + + + type: "application/json", + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: "position", + + + action: "bulk-commit", + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 24 + + + Route & Publish Position event for Payee + + + + [Validate Fulfil Transfer not successful] + + + + + break + + + + + 25 + + + Route & Publish Notification event for Payee + + + Reference: Failure in validation + + + + + Reference: Failure in validation + + + + + Message: + + + { + + + id: <messageId>, + + + from: <ledgerName>, + + + to: <payeeFspName>, + + + type: "application/json", + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: "bulk-processing", + + + action: "bulk-commit", + + + createdAt: <timestamp>, + + + state: { + + + status: "error", + + + code: 1 + + + } + + + } + + + } + + + } + + + + + 26 + + + Publish Notification event for Payee to Bulk Processing Topic + + + Error codes: + + + 2003 + + diff --git a/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.2.2-fulfil-handler-abort.plantuml b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.2.2-fulfil-handler-abort.plantuml new file mode 100644 index 000000000..a90928354 --- /dev/null +++ b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.2.2-fulfil-handler-abort.plantuml @@ -0,0 +1,616 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Rajiv Mothilal + * Sam Kummary + -------------- + ******'/ + +@startuml +' declate title +title 2.2.2. Fulfil Handler Consume (Reject/Abort) (single message, includes individual transfers from Bulk) + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store +' declare actors +collections "topic-\nfulfil" as TOPIC_FULFIL +control "Fulfil Handler" as FULF_HANDLER +collections "topic-\nevent" as TOPIC_EVENT +collections "topic-\ntransfer-position" as TOPIC_TRANSFER_POSITION +collections "topic-\nnotification" as TOPIC_NOTIFICATIONS +collections "topic-\nbulk-processing" as TOPIC_BULK_PROCESSING +'entity "Transfer Duplicate Facade" as DUP_FACADE +entity "Transfer DAO" as TRANS_DAO +database "Central Store" as DB +box "Central Service" #LightYellow + participant TOPIC_FULFIL + participant FULF_HANDLER + participant TOPIC_TRANSFER_POSITION + participant TOPIC_EVENT + participant TOPIC_BULK_PROCESSING + participant TOPIC_NOTIFICATIONS + participant TRANS_DAO + participant DB +end box +' start flow +activate FULF_HANDLER +group Fulfil Handler Consume (Failure) + alt Consume Single Message + TOPIC_FULFIL <- FULF_HANDLER: Consume Fulfil event message for Payer + activate TOPIC_FULFIL + deactivate TOPIC_FULFIL + break + group Validate Event + FULF_HANDLER <-> FULF_HANDLER: Validate event - Rule: type IN ['fulfil','bulk-fulfil'] && ( action IN ['reject','abort'] )\nError codes: 2001 + end + end + group Persist Event Information + FULF_HANDLER -> TOPIC_EVENT: Publish event information + ref over FULF_HANDLER, TOPIC_EVENT: Event Handler Consume\n + end + group Validate FSPIOP-Signature + ||| + ref over FULF_HANDLER, TOPIC_NOTIFICATIONS: Validate message.content.headers.**FSPIOP-Signature**\nError codes: 2001 + end + group Validate Transfer Fulfil Duplicate Check + FULF_HANDLER -> FULF_HANDLER: Generate transferFulfilmentId uuid + FULF_HANDLER -> TRANS_DAO: Request to retrieve transfer fulfilment hashes by transferId\nError code: 2003 + activate TRANS_DAO + TRANS_DAO -> DB: Request Transfer fulfilment \nduplicate message hashes + hnote over DB #lightyellow + SELET transferId, hash + FROM **transferFulfilmentDuplicateCheck** + WHERE transferId = request.params.id + end note + activate DB + TRANS_DAO <-- DB: Return existing hashes + deactivate DB + TRANS_DAO --> FULF_HANDLER: Return (list of) transfer fulfil messages hash(es) + deactivate TRANS_DAO + FULF_HANDLER -> FULF_HANDLER: Loop the list of returned hashes & compare \neach entry with the calculated message hash + alt Hash matched + ' Need to check what respond with same results if finalised then resend, else ignore and wait for response + FULF_HANDLER -> TRANS_DAO: Request to retrieve Transfer Fulfilment & Transfer state\nError code: 2003 + activate TRANS_DAO + TRANS_DAO -> DB: Request to retrieve \ntransferFulfilment & transferState + hnote over DB #lightyellow + transferFulfilment + transferStateChange + end note + activate DB + TRANS_DAO <-- DB: Return transferFulfilment & \ntransferState + deactivate DB + TRANS_DAO --> FULF_HANDLER: Return Transfer Fulfilment & Transfer state + deactivate TRANS_DAO + alt transferFulfilment.isValid == 0 + break + alt If type == 'fulfil' + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: notification, + action: fulfil-duplicate, + createdAt: , + state: { + status: "error", + code: 1 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_NOTIFICATIONS: Publish Notification event for Payee - Modified Request\nError codes: 3106 + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + else If type == 'bulk-fulfil' + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: bulk-processing, + action: fulfil-duplicate, + createdAt: , + state: { + status: "error", + code: 1 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_BULK_PROCESSING: Publish Notification event for Payee - Modified Request \n3106 to Bulk Processing Topic\nError codes: 3106 + activate TOPIC_BULK_PROCESSING + deactivate TOPIC_BULK_PROCESSING + end + end + else transferState IN ['COMMITTED', 'ABORTED'] + break + alt If type == 'fulfil' + ref over FULF_HANDLER, TOPIC_NOTIFICATIONS: Send notification to Participant (Payee)\n + else If type == 'bulk-fulfil' + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: bulk-processing, + action: fulfil-duplicate, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_BULK_PROCESSING: Publish Notification event for Payee to Bulk Processing Topic\nError codes: 2003 + activate TOPIC_BULK_PROCESSING + deactivate TOPIC_BULK_PROCESSING + end + end + else transferState NOT 'RESERVED' + break + FULF_HANDLER <-> FULF_HANDLER: Reference: Failure in validation\nError code: 2001 + end + else + break + alt If type == 'fulfil' + FULF_HANDLER <-> FULF_HANDLER: Allow previous request to complete + else If type == 'bulk-fulfil' + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: bulk-processing, + action: fulfil-duplicate, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_BULK_PROCESSING: Publish Notification event for Payee to Bulk Processing Topic\nError codes: 2003 + activate TOPIC_BULK_PROCESSING + deactivate TOPIC_BULK_PROCESSING + end + end + end + else Hash not matched + FULF_HANDLER -> TRANS_DAO: Request to persist transfer hash\nError codes: 2003 + activate TRANS_DAO + TRANS_DAO -> DB: Persist hash + hnote over DB #lightyellow + transferFulfilmentDuplicateCheck + end note + activate DB + deactivate DB + TRANS_DAO --> FULF_HANDLER: Return success + deactivate TRANS_DAO + end + end + alt action=='reject' call made on PUT /transfers/{ID} + FULF_HANDLER -> TRANS_DAO: Request information for the validate checks\nError code: 2003 + activate TRANS_DAO + TRANS_DAO -> DB: Fetch from database + activate DB + hnote over DB #lightyellow + transfer + end note + DB --> TRANS_DAO + deactivate DB + FULF_HANDLER <-- TRANS_DAO: Return transfer + deactivate TRANS_DAO + + alt Fulfilment present in the PUT /transfers/{ID} message + FULF_HANDLER ->FULF_HANDLER: Validate that Transfer.ilpCondition = SHA-256 (content.payload.fulfilment)\nError code: 2001 + + group Persist fulfilment + FULF_HANDLER -> TRANS_DAO: Persist fulfilment with the result of the above check (transferFulfilment.isValid)\nError code: 2003 + activate TRANS_DAO + TRANS_DAO -> DB: Persist to database + activate DB + deactivate DB + hnote over DB #lightyellow + transferFulfilment + transferExtension + end note + FULF_HANDLER <-- TRANS_DAO: Return success + deactivate TRANS_DAO + end + else Fulfilment NOT present in the PUT /transfers/{ID} message + FULF_HANDLER ->FULF_HANDLER: Validate that transfer fulfilment message to Abort is valid\nError code: 2001 + group Persist extensions + FULF_HANDLER -> TRANS_DAO: Persist extensionList elements\nError code: 2003 + activate TRANS_DAO + TRANS_DAO -> DB: Persist to database + activate DB + deactivate DB + hnote over DB #lightyellow + transferExtension + end note + FULF_HANDLER <-- TRANS_DAO: Return success + deactivate TRANS_DAO + end + end + + alt Transfer.ilpCondition validate successful OR generic validation successful + group Persist Transfer State (with transferState='RECEIVED_REJECT') + FULF_HANDLER -> TRANS_DAO: Request to persist transfer state\nError code: 2003 + activate TRANS_DAO + TRANS_DAO -> DB: Persist transfer state + activate DB + hnote over DB #lightyellow + transferStateChange + end note + deactivate DB + TRANS_DAO --> FULF_HANDLER: Return success + end + + FULF_HANDLER -> FULF_HANDLER: Route & Publish Position event for Payer\nReference: Publish Position Reject event for Payer + + else Validate Fulfil Transfer not successful or Generic validation failed + break + FULF_HANDLER -> FULF_HANDLER: Publish event for Payee\nReference: Failure in validation + end + end + else action=='abort' Error callback + alt Validation successful + group Persist Transfer State (with transferState='RECEIVED_ERROR') + FULF_HANDLER -> TRANS_DAO: Request to persist transfer state & Error\nError code: 2003 + activate TRANS_DAO + TRANS_DAO -> DB: Persist transfer state & Error + activate DB + hnote over DB #lightyellow + transferStateChange + transferError + transferExtension + end note + deactivate DB + TRANS_DAO --> FULF_HANDLER: Return success + end + + FULF_HANDLER -> FULF_HANDLER: Error callback validated\nReference: Produce message for validated error callback + + else Validate Transfer Error Message not successful + break + FULF_HANDLER -> FULF_HANDLER: Notifications for failures\nReference: Validate Transfer Error Message not successful + end + end + end + else Consume Batch Messages + note left of FULF_HANDLER #lightblue + To be delivered by future story + end note + end +end + +group Reference: Validate Transfer Error Message not successful + alt If type == 'bulk-fulfil' + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: bulk-processing, + action: abort, + createdAt: , + state: { + status: "error", + code: 1 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_BULK_PROCESSING: Publish Processing event for Payee to Bulk Processing Topic\nError codes: 2003 + activate TOPIC_BULK_PROCESSING + deactivate TOPIC_BULK_PROCESSING + else If type == 'fulfil' + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: fulfil, + action: abort, + createdAt: , + state: { + status: "error", + code: 1 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_NOTIFICATIONS: Route & Publish Notification event for Payee + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + end +end + +group Reference: Produce message for validated error callback + alt If type == 'bulk-fulfil' + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: bulk-position, + action: abort, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_TRANSFER_POSITION: Route & Publish Position event for Payer + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + else If type == 'fulfil' + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: position, + action: abort, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_TRANSFER_POSITION: Route & Publish Position event for Payer + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + end +end + +group Reference: Failure in validation + alt If type == 'bulk-fulfil' + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: bulk-processing, + action: reject, + createdAt: , + state: { + status: "error", + code: 1 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_BULK_PROCESSING: Publish processing event to the Bulk Processing Topic\nError codes: 2003 + activate TOPIC_BULK_PROCESSING + deactivate TOPIC_BULK_PROCESSING + else If type == 'fulfil' + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: fulfil, + action: reject, + createdAt: , + state: { + status: "error", + code: 1 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_NOTIFICATIONS: Route & Publish Notification event for Payee + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + end +end + +group Reference: Publish Position Reject event for Payer + alt If type == 'bulk-fulfil' + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: bulk-position, + action: reject, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_TRANSFER_POSITION: Route & Publish Position event for Payer + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + else If type == 'fulfil' + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: position, + action: reject, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_TRANSFER_POSITION: Route & Publish Position event for Payer + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + end +end + +deactivate FULF_HANDLER +@enduml diff --git a/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.2.2-fulfil-handler-abort.svg b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.2.2-fulfil-handler-abort.svg new file mode 100644 index 000000000..1b64285dd --- /dev/null +++ b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.2.2-fulfil-handler-abort.svg @@ -0,0 +1,1975 @@ + + + + + + + + + + + 2.2.2. Fulfil Handler Consume (Reject/Abort) (single message, includes individual transfers from Bulk) + + + + Central Service + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + topic- + + + fulfil + + + + + topic- + + + fulfil + + + Fulfil Handler + + + + + Fulfil Handler + + + + + + + topic- + + + transfer-position + + + + + topic- + + + transfer-position + + + + + topic- + + + event + + + + + topic- + + + event + + + + + topic- + + + bulk-processing + + + + + topic- + + + bulk-processing + + + + + topic- + + + notification + + + + + topic- + + + notification + + + Transfer DAO + + + + + Transfer DAO + + + + + Central Store + + + + + Central Store + + + + + + + + + Fulfil Handler Consume (Failure) + + + + + alt + + + [Consume Single Message] + + + + + 1 + + + Consume Fulfil event message for Payer + + + + + break + + + + + Validate Event + + + + + 2 + + + Validate event - Rule: type IN ['fulfil','bulk-fulfil'] && ( action IN ['reject','abort'] ) + + + Error codes: + + + 2001 + + + + + Persist Event Information + + + + + 3 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + Validate FSPIOP-Signature + + + + + ref + + + Validate message.content.headers. + + + FSPIOP-Signature + + + Error codes: + + + 2001 + + + + + Validate Transfer Fulfil Duplicate Check + + + + + 4 + + + Generate transferFulfilmentId uuid + + + + + 5 + + + Request to retrieve transfer fulfilment hashes by transferId + + + Error code: + + + 2003 + + + + + 6 + + + Request Transfer fulfilment + + + duplicate message hashes + + + + SELET transferId, hash + + + FROM + + + transferFulfilmentDuplicateCheck + + + WHERE transferId = request.params.id + + + + + 7 + + + Return existing hashes + + + + + 8 + + + Return (list of) transfer fulfil messages hash(es) + + + + + 9 + + + Loop the list of returned hashes & compare + + + each entry with the calculated message hash + + + + + alt + + + [Hash matched] + + + + + 10 + + + Request to retrieve Transfer Fulfilment & Transfer state + + + Error code: + + + 2003 + + + + + 11 + + + Request to retrieve + + + transferFulfilment & transferState + + + + transferFulfilment + + + transferStateChange + + + + + 12 + + + Return transferFulfilment & + + + transferState + + + + + 13 + + + Return Transfer Fulfilment & Transfer state + + + + + alt + + + [transferFulfilment.isValid == 0] + + + + + break + + + + + alt + + + [If type == 'fulfil'] + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: notification, + + + action: fulfil-duplicate, + + + createdAt: <timestamp>, + + + state: { + + + status: "error", + + + code: 1 + + + } + + + } + + + } + + + } + + + + + 14 + + + Publish Notification event for Payee - Modified Request + + + Error codes: + + + 3106 + + + + [If type == 'bulk-fulfil'] + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: bulk-processing, + + + action: fulfil-duplicate, + + + createdAt: <timestamp>, + + + state: { + + + status: "error", + + + code: 1 + + + } + + + } + + + } + + + } + + + + + 15 + + + Publish Notification event for Payee - Modified Request + + + 3106 to Bulk Processing Topic + + + Error codes: + + + 3106 + + + + [transferState IN ['COMMITTED', 'ABORTED']] + + + + + break + + + + + alt + + + [If type == 'fulfil'] + + + + + ref + + + Send notification to Participant (Payee) + + + + [If type == 'bulk-fulfil'] + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: bulk-processing, + + + action: fulfil-duplicate, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 16 + + + Publish Notification event for Payee to Bulk Processing Topic + + + Error codes: + + + 2003 + + + + [transferState NOT 'RESERVED'] + + + + + break + + + + + 17 + + + Reference: Failure in validation + + + Error code: + + + 2001 + + + + + + break + + + + + alt + + + [If type == 'fulfil'] + + + + + 18 + + + Allow previous request to complete + + + + [If type == 'bulk-fulfil'] + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: bulk-processing, + + + action: fulfil-duplicate, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 19 + + + Publish Notification event for Payee to Bulk Processing Topic + + + Error codes: + + + 2003 + + + + [Hash not matched] + + + + + 20 + + + Request to persist transfer hash + + + Error codes: + + + 2003 + + + + + 21 + + + Persist hash + + + + transferFulfilmentDuplicateCheck + + + + + 22 + + + Return success + + + + + alt + + + [action=='reject' call made on PUT /transfers/{ID}] + + + + + 23 + + + Request information for the validate checks + + + Error code: + + + 2003 + + + + + 24 + + + Fetch from database + + + + transfer + + + + + 25 + + + + + 26 + + + Return transfer + + + + + alt + + + [Fulfilment present in the PUT /transfers/{ID} message] + + + + + 27 + + + Validate that Transfer.ilpCondition = SHA-256 (content.payload.fulfilment) + + + Error code: + + + 2001 + + + + + Persist fulfilment + + + + + 28 + + + Persist fulfilment with the result of the above check (transferFulfilment.isValid) + + + Error code: + + + 2003 + + + + + 29 + + + Persist to database + + + + transferFulfilment + + + transferExtension + + + + + 30 + + + Return success + + + + [Fulfilment NOT present in the PUT /transfers/{ID} message] + + + + + 31 + + + Validate that transfer fulfilment message to Abort is valid + + + Error code: + + + 2001 + + + + + Persist extensions + + + + + 32 + + + Persist extensionList elements + + + Error code: + + + 2003 + + + + + 33 + + + Persist to database + + + + transferExtension + + + + + 34 + + + Return success + + + + + alt + + + [Transfer.ilpCondition validate successful OR generic validation successful] + + + + + Persist Transfer State (with transferState='RECEIVED_REJECT') + + + + + 35 + + + Request to persist transfer state + + + Error code: + + + 2003 + + + + + 36 + + + Persist transfer state + + + + transferStateChange + + + + + 37 + + + Return success + + + + + 38 + + + Route & Publish Position event for Payer + + + Reference: Publish Position Reject event for Payer + + + + [Validate Fulfil Transfer not successful or Generic validation failed] + + + + + break + + + + + 39 + + + Publish event for Payee + + + Reference: Failure in validation + + + + [action=='abort' Error callback] + + + + + alt + + + [Validation successful] + + + + + Persist Transfer State (with transferState='RECEIVED_ERROR') + + + + + 40 + + + Request to persist transfer state & Error + + + Error code: + + + 2003 + + + + + 41 + + + Persist transfer state & Error + + + + transferStateChange + + + transferError + + + transferExtension + + + + + 42 + + + Return success + + + + + 43 + + + Error callback validated + + + Reference: Produce message for validated error callback + + + + [Validate Transfer Error Message not successful] + + + + + break + + + + + 44 + + + Notifications for failures + + + Reference: Validate Transfer Error Message not successful + + + + [Consume Batch Messages] + + + + + To be delivered by future story + + + + + Reference: Validate Transfer Error Message not successful + + + + + alt + + + [If type == 'bulk-fulfil'] + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: bulk-processing, + + + action: abort, + + + createdAt: <timestamp>, + + + state: { + + + status: "error", + + + code: 1 + + + } + + + } + + + } + + + } + + + + + 45 + + + Publish Processing event for Payee to Bulk Processing Topic + + + Error codes: + + + 2003 + + + + [If type == 'fulfil'] + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: fulfil, + + + action: abort, + + + createdAt: <timestamp>, + + + state: { + + + status: "error", + + + code: 1 + + + } + + + } + + + } + + + } + + + + + 46 + + + Route & Publish Notification event for Payee + + + + + Reference: Produce message for validated error callback + + + + + alt + + + [If type == 'bulk-fulfil'] + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: bulk-position, + + + action: abort, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 47 + + + Route & Publish Position event for Payer + + + + [If type == 'fulfil'] + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: position, + + + action: abort, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 48 + + + Route & Publish Position event for Payer + + + + + Reference: Failure in validation + + + + + alt + + + [If type == 'bulk-fulfil'] + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: bulk-processing, + + + action: reject, + + + createdAt: <timestamp>, + + + state: { + + + status: "error", + + + code: 1 + + + } + + + } + + + } + + + } + + + + + 49 + + + Publish processing event to the Bulk Processing Topic + + + Error codes: + + + 2003 + + + + [If type == 'fulfil'] + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: fulfil, + + + action: reject, + + + createdAt: <timestamp>, + + + state: { + + + status: "error", + + + code: 1 + + + } + + + } + + + } + + + } + + + + + 50 + + + Route & Publish Notification event for Payee + + + + + Reference: Publish Position Reject event for Payer + + + + + alt + + + [If type == 'bulk-fulfil'] + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: bulk-position, + + + action: reject, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 51 + + + Route & Publish Position event for Payer + + + + [If type == 'fulfil'] + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: position, + + + action: reject, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 52 + + + Route & Publish Position event for Payer + + diff --git a/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.3.1-position-fulfil.plantuml b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.3.1-position-fulfil.plantuml new file mode 100644 index 000000000..f992f9284 --- /dev/null +++ b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.3.1-position-fulfil.plantuml @@ -0,0 +1,176 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Miguel de Barros + * Rajiv Mothilal + * Sam Kummary + -------------- + ******'/ + +@startuml +' declate title +title 2.3.1. Fulfil Position Handler Consume (single message, includes individual transfers from Bulk) + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistence Store + +' declare actors +control "Position Handler" as POS_HANDLER +collections "topic-\nnotifications" as TOPIC_NOTIFICATIONS +collections "topic-\nbulk-processing" as TOPIC_BULK_PROCESSING +entity "Position Facade" as POS_FACADE +entity "Position DAO" as POS_DAO +database "Central Store" as DB + +box "Central Service" #LightYellow + participant POS_HANDLER + participant TOPIC_NOTIFICATIONS + participant TOPIC_BULK_PROCESSING + participant POS_DAO + participant POS_FACADE + participant DB +end box + +' start flow +activate POS_HANDLER +group Fulfil Position Handler Consume + POS_HANDLER -> POS_DAO: Request current state of transfer from DB \nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Retrieve current state of transfer from DB + activate DB + hnote over DB #lightyellow + transferStateChange + transferParticipant + end note + DB --> POS_DAO: Return current state of transfer from DB + deactivate DB + POS_DAO --> POS_HANDLER: Return current state of transfer from DB + deactivate POS_DAO + POS_HANDLER <-> POS_HANDLER: Validate current state (transferState is 'RECEIVED-FULFIL')\nError code: 2001 + group Persist Position change and Transfer State (with transferState='COMMITTED' on position check pass) + POS_HANDLER -> POS_FACADE: Request to persist latest position and state to DB\nError code: 2003 + group DB TRANSACTION + activate POS_FACADE + POS_FACADE -> DB: Select participantPosition.value FOR UPDATE from DB for Payee + activate DB + hnote over DB #lightyellow + participantPosition + end note + DB --> POS_FACADE: Return participantPosition.value from DB for Payee + deactivate DB + POS_FACADE <-> POS_FACADE: **latestPosition** = participantPosition.value - payload.amount.amount + POS_FACADE->DB: Persist latestPosition to DB for Payee + hnote over DB #lightyellow + UPDATE **participantPosition** + SET value = latestPosition + end note + activate DB + deactivate DB + POS_FACADE -> DB: Persist transfer state and participant position change + hnote over DB #lightyellow + INSERT **transferStateChange** transferStateId = 'COMMITTED' + + INSERT **participantPositionChange** + SET participantPositionId = participantPosition.participantPositionId, + transferStateChangeId = transferStateChange.transferStateChangeId, + value = latestPosition, + reservedValue = participantPosition.reservedValue + createdDate = new Date() + end note + activate DB + deactivate DB + deactivate POS_DAO + end + POS_FACADE --> POS_HANDLER: Return success + deactivate POS_FACADE + end + + alt If type == 'bulk-position' + note right of POS_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: bulk-processing, + action: bulk-commit, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + POS_HANDLER -> TOPIC_BULK_PROCESSING: Publish Transfer event to Bulk Processing Topic\nError codes: 2003 + activate TOPIC_BULK_PROCESSING + deactivate TOPIC_BULK_PROCESSING + else If type == 'position' + note right of POS_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: notification, + action: commit, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + POS_HANDLER -> TOPIC_NOTIFICATIONS: Publish Transfer event\nError code: 2003 + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + end + +end +deactivate POS_HANDLER +@enduml diff --git a/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.3.1-position-fulfil.svg b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.3.1-position-fulfil.svg new file mode 100644 index 000000000..a50bd3d57 --- /dev/null +++ b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.3.1-position-fulfil.svg @@ -0,0 +1,468 @@ + + + + + + + + + + + 2.3.1. Fulfil Position Handler Consume (single message, includes individual transfers from Bulk) + + + + Central Service + + + + + + + + + Position Handler + + + + + Position Handler + + + + + + + topic- + + + notifications + + + + + topic- + + + notifications + + + + + topic- + + + bulk-processing + + + + + topic- + + + bulk-processing + + + Position DAO + + + + + Position DAO + + + + + Position Facade + + + + + Position Facade + + + + + Central Store + + + + + Central Store + + + + + + + + Fulfil Position Handler Consume + + + + + 1 + + + Request current state of transfer from DB + + + Error code: + + + 2003 + + + + + 2 + + + Retrieve current state of transfer from DB + + + + transferStateChange + + + transferParticipant + + + + + 3 + + + Return current state of transfer from DB + + + + + 4 + + + Return current state of transfer from DB + + + + + 5 + + + Validate current state (transferState is 'RECEIVED-FULFIL') + + + Error code: + + + 2001 + + + + + Persist Position change and Transfer State (with transferState='COMMITTED' on position check pass) + + + + + 6 + + + Request to persist latest position and state to DB + + + Error code: + + + 2003 + + + + + DB TRANSACTION + + + + + 7 + + + Select participantPosition.value FOR UPDATE from DB for Payee + + + + participantPosition + + + + + 8 + + + Return participantPosition.value from DB for Payee + + + + + 9 + + + latestPosition + + + = participantPosition.value - payload.amount.amount + + + + + 10 + + + Persist latestPosition to DB for Payee + + + + UPDATE + + + participantPosition + + + SET value = latestPosition + + + + + 11 + + + Persist transfer state and participant position change + + + + INSERT + + + transferStateChange + + + transferStateId = 'COMMITTED' + + + INSERT + + + participantPositionChange + + + SET participantPositionId = participantPosition.participantPositionId, + + + transferStateChangeId = transferStateChange.transferStateChangeId, + + + value = latestPosition, + + + reservedValue = participantPosition.reservedValue + + + createdDate = new Date() + + + + + 12 + + + Return success + + + + + alt + + + [If type == 'bulk-position'] + + + + + Message: + + + { + + + id: <transferMessage.transferId> + + + from: <transferMessage.payerFsp>, + + + to: <transferMessage.payeeFsp>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: bulk-processing, + + + action: bulk-commit, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 13 + + + Publish Transfer event to Bulk Processing Topic + + + Error codes: + + + 2003 + + + + [If type == 'position'] + + + + + Message: + + + { + + + id: <transferMessage.transferId> + + + from: <transferMessage.payerFsp>, + + + to: <transferMessage.payeeFsp>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: notification, + + + action: commit, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 14 + + + Publish Transfer event + + + Error code: + + + 2003 + + diff --git a/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.3.2-position-abort.plantuml b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.3.2-position-abort.plantuml new file mode 100644 index 000000000..467666a01 --- /dev/null +++ b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.3.2-position-abort.plantuml @@ -0,0 +1,419 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Rajiv Mothilal + * Sam Kummary + ------------- + ******'/ + +@startuml +' declate title +title 2.3.2. Abort Position Handler Consume (single message, includes individual transfers from Bulk) + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistence Store + +' declare actors +control "Position Handler" as POS_HANDLER +entity "Position DAO" as POS_DAO +collections "topic-\nnotification" as TOPIC_NOTIFICATIONS +collections "topic-\nbulk-processing" as TOPIC_BULK_PROCESSING +database "Central Store" as DB + +box "Central Service" #LightYellow + participant POS_HANDLER + participant TOPIC_NOTIFICATIONS + participant TOPIC_BULK_PROCESSING + participant POS_DAO + participant DB +end box + +' start flow +activate POS_HANDLER +group Abort Position Handler Consume + opt type IN ['position','bulk-position'] && action == 'timeout-reserved' + POS_HANDLER -> POS_DAO: Request current state of transfer from DB\nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Retrieve current state of transfer from DB + activate DB + hnote over DB #lightyellow + transferStateChange + transferParticipant + end note + DB --> POS_DAO: Return current state of transfer from DB + deactivate DB + POS_DAO --> POS_HANDLER: Return current state of transfer from DB + deactivate POS_DAO + POS_HANDLER <-> POS_HANDLER: Validate current state \n(transferStateChange.transferStateId == 'RESERVED_TIMEOUT')\nError code: 2001 + + group Persist Position change and Transfer state + POS_HANDLER -> POS_HANDLER: **transferStateId** = 'EXPIRED_RESERVED' + POS_HANDLER -> POS_DAO: Request to persist latest position and state to DB\nError code: 2003 + group DB TRANSACTION IMPLEMENTATION + activate POS_DAO + POS_DAO -> DB: Select participantPosition.value FOR UPDATE for payerCurrencyId + activate DB + hnote over DB #lightyellow + participantPosition + end note + DB --> POS_DAO: Return participantPosition + deactivate DB + POS_DAO <-> POS_DAO: **latestPosition** = participantPosition - payload.amount.amount + POS_DAO->DB: Persist latestPosition to DB for Payer + hnote over DB #lightyellow + UPDATE **participantPosition** + SET value = latestPosition + end note + activate DB + deactivate DB + POS_DAO -> DB: Persist participant position change and state change + hnote over DB #lightyellow + INSERT **transferStateChange** + VALUES (transferStateId) + + INSERT **participantPositionChange** + SET participantPositionId = participantPosition.participantPositionId, + transferStateChangeId = transferStateChange.transferStateChangeId, + value = latestPosition, + reservedValue = participantPosition.reservedValue + createdDate = new Date() + end note + activate DB + deactivate DB + end + POS_DAO --> POS_HANDLER: Return success + deactivate POS_DAO + end + alt If type == 'bulk-position' + note right of POS_HANDLER #yellow + Message: { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: { + "errorInformation": { + "errorCode": 3300, + "errorDescription": "Transfer expired", + "extensionList": + } + } + }, + metadata: { + event: { + id: , + responseTo: , + type: bulk-processing, + action: abort, + createdAt: , + state: { + status: 'error', + code: + description: + } + } + } + } + end note + POS_HANDLER -> TOPIC_BULK_PROCESSING: Publish Transfer event to Bulk Processing Topic (for Payer) \nError codes: 2003 + activate TOPIC_BULK_PROCESSING + deactivate TOPIC_BULK_PROCESSING + else If type == 'position' + note right of POS_HANDLER #yellow + Message: { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: { + "errorInformation": { + "errorCode": 3300, + "errorDescription": "Transfer expired", + "extensionList": + } + } + }, + metadata: { + event: { + id: , + responseTo: , + type: notification, + action: abort, + createdAt: , + state: { + status: 'error', + code: + description: + } + } + } + } + end note + POS_HANDLER -> TOPIC_NOTIFICATIONS: Publish Notification event\nError code: 2003 + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + end + end + opt type IN ['position','bulk-position'] && (action IN ['reject', 'abort']) + POS_HANDLER -> POS_DAO: Request current state of transfer from DB\nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Retrieve current state of transfer from DB + activate DB + hnote over DB #lightyellow + transferStateChange + end note + DB --> POS_DAO: Return current state of transfer from DB + deactivate DB + POS_DAO --> POS_HANDLER: Return current state of transfer from DB + deactivate POS_DAO + POS_HANDLER <-> POS_HANDLER: Validate current state \n(transferStateChange.transferStateId IN ['RECEIVED_REJECT', 'RECEIVED_ERROR'])\nError code: 2001 + + group Persist Position change and Transfer state + POS_HANDLER -> POS_HANDLER: **transferStateId** = (action == 'reject' ? 'ABORTED_REJECTED' : 'ABORTED_ERROR' ) + POS_HANDLER -> POS_DAO: Request to persist latest position and state to DB\nError code: 2003 + group Refer to DB TRANSACTION IMPLEMENTATION above + activate POS_DAO + POS_DAO -> DB: Persist to database + activate DB + deactivate DB + hnote over DB #lightyellow + participantPosition + transferStateChange + participantPositionChange + end note + end + POS_DAO --> POS_HANDLER: Return success + deactivate POS_DAO + end + alt If action == 'reject' + alt If type == 'position' + note right of POS_HANDLER #yellow + Message: { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: notification, + action: reject, + createdAt: , + state: { + status: "success", + code: 0, + description: "action successful" + } + } + } + } + end note + POS_HANDLER -> TOPIC_NOTIFICATIONS: Publish Notification event\nError code: 2003 + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + else If type == 'bulk-position' + note right of POS_HANDLER #yellow + Message: { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: bulk-processing, + action: reject, + createdAt: , + state: { + status: "success", + code: 0, + description: "action successful" + } + } + } + } + end note + POS_HANDLER -> TOPIC_BULK_PROCESSING: Publish Notification event\nError code: 2003 + activate TOPIC_BULK_PROCESSING + deactivate TOPIC_BULK_PROCESSING + end + else action == 'abort' + note right of POS_HANDLER #yellow + Message: { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: notification, + action: abort, + createdAt: , + state: { + status: 'error', + code: + description: + } + } + } + } + end note + POS_HANDLER -> TOPIC_NOTIFICATIONS: Publish Notification event\nError code: 2003 + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + end + end + + ' TODO: We do not see how this scenario will be triggered + opt type IN ['position','bulk-position'] && action == 'fail' (Unable to currently trigger this scenario) + POS_HANDLER -> POS_DAO: Request current state of transfer from DB\nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Retrieve current state of transfer from DB + activate DB + hnote over DB #lightyellow + transferStateChange + end note + DB --> POS_DAO: Return current state of transfer from DB + deactivate DB + POS_DAO --> POS_HANDLER: Return current state of transfer from DB + deactivate POS_DAO + POS_HANDLER <-> POS_HANDLER: Validate current state (transferStateChange.transferStateId == 'FAILED') + + group Persist Position change and Transfer state + POS_HANDLER -> POS_HANDLER: **transferStateId** = 'FAILED' + POS_HANDLER -> POS_DAO: Request to persist latest position and state to DB\nError code: 2003 + group Refer to DB TRANSACTION IMPLEMENTATION above + activate POS_DAO + POS_DAO -> DB: Persist to database + activate DB + deactivate DB + hnote over DB #lightyellow + participantPosition + transferStateChange + participantPositionChange + end note + end + POS_DAO --> POS_HANDLER: Return success + deactivate POS_DAO + end + alt If type =='position' + note right of POS_HANDLER #yellow + Message: { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: { + "errorInformation": { + "errorCode": 3100, + "errorDescription": "Transfer failed", + "extensionList": + } + } + }, + metadata: { + event: { + id: , + responseTo: , + type: notification, + action: abort, + createdAt: , + state: { + status: 'error', + code: + description: + } + } + } + } + end note + POS_HANDLER -> TOPIC_NOTIFICATIONS: Publish Notification event\nError code: 2003 + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + else If type =='bulk-position' + note right of POS_HANDLER #yellow + Message: { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: { + "errorInformation": { + "errorCode": 3100, + "errorDescription": "Transfer failed", + "extensionList": + } + } + }, + metadata: { + event: { + id: , + responseTo: , + type: bulk-processing, + action: abort, + createdAt: , + state: { + status: 'error', + code: + description: + } + } + } + } + end note + POS_HANDLER -> TOPIC_BULK_PROCESSING: Publish Notification event\nError code: 2003 + activate TOPIC_BULK_PROCESSING + deactivate TOPIC_BULK_PROCESSING + end + end +end +deactivate POS_HANDLER +@enduml diff --git a/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.3.2-position-abort.svg b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.3.2-position-abort.svg new file mode 100644 index 000000000..9ebfd3c26 --- /dev/null +++ b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-2.3.2-position-abort.svg @@ -0,0 +1,1297 @@ + + + + + + + + + + + 2.3.2. Abort Position Handler Consume (single message, includes individual transfers from Bulk) + + + + Central Service + + + + + + + + + + + + + + + + + + + Position Handler + + + + + Position Handler + + + + + + + topic- + + + notification + + + + + topic- + + + notification + + + + + topic- + + + bulk-processing + + + + + topic- + + + bulk-processing + + + Position DAO + + + + + Position DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Abort Position Handler Consume + + + + + opt + + + [type IN ['position','bulk-position'] && action == 'timeout-reserved'] + + + + + 1 + + + Request current state of transfer from DB + + + Error code: + + + 2003 + + + + + 2 + + + Retrieve current state of transfer from DB + + + + transferStateChange + + + transferParticipant + + + + + 3 + + + Return current state of transfer from DB + + + + + 4 + + + Return current state of transfer from DB + + + + + 5 + + + Validate current state + + + (transferStateChange.transferStateId == 'RESERVED_TIMEOUT') + + + Error code: + + + 2001 + + + + + Persist Position change and Transfer state + + + + + 6 + + + transferStateId + + + = 'EXPIRED_RESERVED' + + + + + 7 + + + Request to persist latest position and state to DB + + + Error code: + + + 2003 + + + + + DB TRANSACTION IMPLEMENTATION + + + + + 8 + + + Select participantPosition.value FOR UPDATE for payerCurrencyId + + + + participantPosition + + + + + 9 + + + Return participantPosition + + + + + 10 + + + latestPosition + + + = participantPosition - payload.amount.amount + + + + + 11 + + + Persist latestPosition to DB for Payer + + + + UPDATE + + + participantPosition + + + SET value = latestPosition + + + + + 12 + + + Persist participant position change and state change + + + + INSERT + + + transferStateChange + + + VALUES (transferStateId) + + + INSERT + + + participantPositionChange + + + SET participantPositionId = participantPosition.participantPositionId, + + + transferStateChangeId = transferStateChange.transferStateChangeId, + + + value = latestPosition, + + + reservedValue = participantPosition.reservedValue + + + createdDate = new Date() + + + + + 13 + + + Return success + + + + + alt + + + [If type == 'bulk-position'] + + + + + Message: { + + + id: <transferMessage.transferId> + + + from: <transferMessage.payerFsp>, + + + to: <transferMessage.payeeFsp>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: { + + + "errorInformation": { + + + "errorCode": 3300, + + + "errorDescription": "Transfer expired", + + + "extensionList": <transferMessage.extensionList> + + + } + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: bulk-processing, + + + action: abort, + + + createdAt: <timestamp>, + + + state: { + + + status: 'error', + + + code: <errorInformation.errorCode> + + + description: <errorInformation.errorDescription> + + + } + + + } + + + } + + + } + + + + + 14 + + + Publish Transfer event to Bulk Processing Topic (for Payer) + + + Error codes: + + + 2003 + + + + [If type == 'position'] + + + + + Message: { + + + id: <transferMessage.transferId> + + + from: <transferMessage.payerFsp>, + + + to: <transferMessage.payeeFsp>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: { + + + "errorInformation": { + + + "errorCode": 3300, + + + "errorDescription": "Transfer expired", + + + "extensionList": <transferMessage.extensionList> + + + } + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: notification, + + + action: abort, + + + createdAt: <timestamp>, + + + state: { + + + status: 'error', + + + code: <errorInformation.errorCode> + + + description: <errorInformation.errorDescription> + + + } + + + } + + + } + + + } + + + + + 15 + + + Publish Notification event + + + Error code: + + + 2003 + + + + + opt + + + [type IN ['position','bulk-position'] && (action IN ['reject', 'abort'])] + + + + + 16 + + + Request current state of transfer from DB + + + Error code: + + + 2003 + + + + + 17 + + + Retrieve current state of transfer from DB + + + + transferStateChange + + + + + 18 + + + Return current state of transfer from DB + + + + + 19 + + + Return current state of transfer from DB + + + + + 20 + + + Validate current state + + + (transferStateChange.transferStateId IN ['RECEIVED_REJECT', 'RECEIVED_ERROR']) + + + Error code: + + + 2001 + + + + + Persist Position change and Transfer state + + + + + 21 + + + transferStateId + + + = (action == 'reject' ? 'ABORTED_REJECTED' : 'ABORTED_ERROR' ) + + + + + 22 + + + Request to persist latest position and state to DB + + + Error code: + + + 2003 + + + + + Refer to + + + DB TRANSACTION IMPLEMENTATION + + + above + + + + + 23 + + + Persist to database + + + + participantPosition + + + transferStateChange + + + participantPositionChange + + + + + 24 + + + Return success + + + + + alt + + + [If action == 'reject'] + + + + + alt + + + [If type == 'position'] + + + + + Message: { + + + id: <transferMessage.transferId> + + + from: <transferMessage.payerFsp>, + + + to: <transferMessage.payeeFsp>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: notification, + + + action: reject, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0, + + + description: "action successful" + + + } + + + } + + + } + + + } + + + + + 25 + + + Publish Notification event + + + Error code: + + + 2003 + + + + [If type == 'bulk-position'] + + + + + Message: { + + + id: <transferMessage.transferId> + + + from: <transferMessage.payerFsp>, + + + to: <transferMessage.payeeFsp>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: bulk-processing, + + + action: reject, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0, + + + description: "action successful" + + + } + + + } + + + } + + + } + + + + + 26 + + + Publish Notification event + + + Error code: + + + 2003 + + + + [action == 'abort'] + + + + + Message: { + + + id: <transferMessage.transferId> + + + from: <transferMessage.payerFsp>, + + + to: <transferMessage.payeeFsp>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: notification, + + + action: abort, + + + createdAt: <timestamp>, + + + state: { + + + status: 'error', + + + code: <payload.errorInformation.errorCode || 5000> + + + description: <payload.errorInformation.errorDescription> + + + } + + + } + + + } + + + } + + + + + 27 + + + Publish Notification event + + + Error code: + + + 2003 + + + + + opt + + + [type IN ['position','bulk-position'] && action == 'fail' (Unable to currently trigger this scenario)] + + + + + 28 + + + Request current state of transfer from DB + + + Error code: + + + 2003 + + + + + 29 + + + Retrieve current state of transfer from DB + + + + transferStateChange + + + + + 30 + + + Return current state of transfer from DB + + + + + 31 + + + Return current state of transfer from DB + + + + + 32 + + + Validate current state (transferStateChange.transferStateId == 'FAILED') + + + + + Persist Position change and Transfer state + + + + + 33 + + + transferStateId + + + = 'FAILED' + + + + + 34 + + + Request to persist latest position and state to DB + + + Error code: + + + 2003 + + + + + Refer to + + + DB TRANSACTION IMPLEMENTATION + + + above + + + + + 35 + + + Persist to database + + + + participantPosition + + + transferStateChange + + + participantPositionChange + + + + + 36 + + + Return success + + + + + alt + + + [If type =='position'] + + + + + Message: { + + + id: <transferMessage.transferId> + + + from: <transferMessage.payerFsp>, + + + to: <transferMessage.payeeFsp>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: { + + + "errorInformation": { + + + "errorCode": 3100, + + + "errorDescription": "Transfer failed", + + + "extensionList": <transferMessage.extensionList> + + + } + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: notification, + + + action: abort, + + + createdAt: <timestamp>, + + + state: { + + + status: 'error', + + + code: <errorInformation.errorCode> + + + description: <errorInformation.errorDescription> + + + } + + + } + + + } + + + } + + + + + 37 + + + Publish Notification event + + + Error code: + + + 2003 + + + + [If type =='bulk-position'] + + + + + Message: { + + + id: <transferMessage.transferId> + + + from: <transferMessage.payerFsp>, + + + to: <transferMessage.payeeFsp>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: { + + + "errorInformation": { + + + "errorCode": 3100, + + + "errorDescription": "Transfer failed", + + + "extensionList": <transferMessage.extensionList> + + + } + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: bulk-processing, + + + action: abort, + + + createdAt: <timestamp>, + + + state: { + + + status: 'error', + + + code: <errorInformation.errorCode> + + + description: <errorInformation.errorDescription> + + + } + + + } + + + } + + + } + + + + + 38 + + + Publish Notification event + + + Error code: + + + 2003 + + diff --git a/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-3.1.0-timeout-overview.plantuml b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-3.1.0-timeout-overview.plantuml new file mode 100644 index 000000000..478074f80 --- /dev/null +++ b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-3.1.0-timeout-overview.plantuml @@ -0,0 +1,120 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + -------------- + ******'/ + +@startuml +' declate title +title 3.1.0. Transfer Timeout (incl. Bulk Transfer) + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +actor "DFSP1\nPayer" as DFSP1 +actor "DFSP2\nPayee" as DFSP2 +boundary "ML API\nAdapter" as MLAPI +control "ML API Notification\nEvent Handler" as NOTIFY_HANDLER +control "Transfer Timeout\nHandler" as EXP_HANDLER +collections "topic-\ntransfer-position" as TOPIC_TRANSFER_POSITION +control "Position Event\nHandler" as POS_HANDLER +control "Bulk Processing\nHandler" as BULK_PROCESSING_HANDLER +collections "topic-\nnotification" as TOPIC_NOTIFICATIONS +collections "topic-event" as TOPIC_EVENT +collections "topic-\nbulk-processing" as BULK_PROCESSING_TOPIC + +box "Financial Service Providers" #lightGray + participant DFSP1 + participant DFSP2 +end box + +box "ML API Adapter Service" #LightBlue + participant MLAPI + participant NOTIFY_HANDLER +end box + +box "Central Service" #LightYellow + participant EXP_HANDLER + participant TOPIC_TRANSFER_POSITION + participant TOPIC_EVENT + participant POS_HANDLER + participant TOPIC_NOTIFICATIONS + participant BULK_PROCESSING_HANDLER + participant BULK_PROCESSING_TOPIC +end box + +' start flow +activate NOTIFY_HANDLER +activate EXP_HANDLER +activate POS_HANDLER +activate BULK_PROCESSING_HANDLER +group Transfer Expiry + ||| + ref over EXP_HANDLER, TOPIC_EVENT : Timeout Handler Consume\n + alt transferStateId == 'RECEIVED_PREPARE' + alt Regular Transfer + EXP_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + else Individual Transfer from a Bulk + EXP_HANDLER -> BULK_PROCESSING_TOPIC: Produce message + end + else transferStateId == 'RESERVED' + EXP_HANDLER -> TOPIC_TRANSFER_POSITION: Produce message + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume message + ref over TOPIC_TRANSFER_POSITION, TOPIC_NOTIFICATIONS : Position Hander Consume (Timeout)\n + alt Regular Transfer + POS_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + else Individual Transfer from a Bulk + POS_HANDLER -> BULK_PROCESSING_TOPIC: Produce message + end + end + opt action IN ['bulk-timeout-received', 'bulk-timeout-reserved'] + ||| + BULK_PROCESSING_TOPIC <- BULK_PROCESSING_HANDLER: Consume message + ref over TOPIC_NOTIFICATIONS, BULK_PROCESSING_TOPIC : Bulk Processing Consume\n + BULK_PROCESSING_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + end + ||| + opt action IN ['timeout-received', 'timeout-reserved', 'bulk-timeout-received', 'bulk-timeout-reserved'] + ||| + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message + ref over DFSP1, TOPIC_NOTIFICATIONS : Send notification to Participant (Payer)\n + NOTIFY_HANDLER -> DFSP1: Send callback notification + end + ||| + opt action IN ['timeout-reserved', 'bulk-timeout-reserved'] + ||| + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message + ref over DFSP2, TOPIC_NOTIFICATIONS : Send notification to Participant (Payee)\n + NOTIFY_HANDLER -> DFSP2: Send callback notification + end +end +deactivate BULK_PROCESSING_HANDLER +deactivate POS_HANDLER +deactivate EXP_HANDLER +deactivate NOTIFY_HANDLER +@enduml diff --git a/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-3.1.0-timeout-overview.svg b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-3.1.0-timeout-overview.svg new file mode 100644 index 000000000..20faf4b81 --- /dev/null +++ b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-3.1.0-timeout-overview.svg @@ -0,0 +1,406 @@ + + + + + + + + + + + 3.1.0. Transfer Timeout (incl. Bulk Transfer) + + + + Financial Service Providers + + + + ML API Adapter Service + + + + Central Service + + + + + + + + + + + + DFSP1 + + + Payer + + + + + DFSP1 + + + Payer + + + + + DFSP2 + + + Payee + + + + + DFSP2 + + + Payee + + + + + ML API + + + Adapter + + + + + ML API + + + Adapter + + + + + ML API Notification + + + Event Handler + + + + + ML API Notification + + + Event Handler + + + + + Transfer Timeout + + + Handler + + + + + Transfer Timeout + + + Handler + + + + + + + topic- + + + transfer-position + + + + + topic- + + + transfer-position + + + + + topic-event + + + + + topic-event + + + Position Event + + + Handler + + + + + Position Event + + + Handler + + + + + + + topic- + + + notification + + + + + topic- + + + notification + + + Bulk Processing + + + Handler + + + + + Bulk Processing + + + Handler + + + + + + + topic- + + + bulk-processing + + + + + topic- + + + bulk-processing + + + + + + Transfer Expiry + + + + + ref + + + Timeout Handler Consume + + + + + alt + + + [transferStateId == 'RECEIVED_PREPARE'] + + + + + alt + + + [Regular Transfer] + + + + + 1 + + + Produce message + + + + [Individual Transfer from a Bulk] + + + + + 2 + + + Produce message + + + + [transferStateId == 'RESERVED'] + + + + + 3 + + + Produce message + + + + + 4 + + + Consume message + + + + + ref + + + Position Hander Consume (Timeout) + + + + + alt + + + [Regular Transfer] + + + + + 5 + + + Produce message + + + + [Individual Transfer from a Bulk] + + + + + 6 + + + Produce message + + + + + opt + + + [action IN ['bulk-timeout-received', 'bulk-timeout-reserved']] + + + + + 7 + + + Consume message + + + + + ref + + + Bulk Processing Consume + + + + + 8 + + + Produce message + + + + + opt + + + [action IN ['timeout-received', 'timeout-reserved', 'bulk-timeout-received', 'bulk-timeout-reserved']] + + + + + 9 + + + Consume message + + + + + ref + + + Send notification to Participant (Payer) + + + + + 10 + + + Send callback notification + + + + + opt + + + [action IN ['timeout-reserved', 'bulk-timeout-reserved']] + + + + + 11 + + + Consume message + + + + + ref + + + Send notification to Participant (Payee) + + + + + 12 + + + Send callback notification + + diff --git a/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-3.1.1-timeout-handler.plantuml b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-3.1.1-timeout-handler.plantuml new file mode 100644 index 000000000..40caba5ae --- /dev/null +++ b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-3.1.1-timeout-handler.plantuml @@ -0,0 +1,420 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Rajiv Mothilal + -------------- + ******'/ + +@startuml +' declare title +title 3.1.1. Timeout Handler Consume (incl. Bulk Transfer) + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +control "Transfer Timeout\nHandler" as TIMEOUT_HANDLER +collections "topic-\ntransfer-position" as TOPIC_TRANSFER_POSITION +collections "topic-\nnotification" as NOTIFICATIONS_TOPIC +collections "topic-event" as EVENT_TOPIC +collections "topic-\nbulk-processing" as BULK_PROCESSING_TOPIC +entity "Segment DAO" as SEGMENT_DAO +entity "Position DAO" as POS_DAO +database "Central Store" as DB + +box "Central Service" #LightYellow + participant TIMEOUT_HANDLER + participant TOPIC_TRANSFER_POSITION + participant NOTIFICATIONS_TOPIC + participant EVENT_TOPIC + participant BULK_PROCESSING_TOPIC + participant POS_DAO + participant SEGMENT_DAO + participant DB +end box + +' start flow + +group Timeout Handler Consume + activate TIMEOUT_HANDLER + group Persist Event Information + TIMEOUT_HANDLER -> EVENT_TOPIC: Publish event information + ref over TIMEOUT_HANDLER, EVENT_TOPIC : Event Handler Consume\n + end + + group Get previous checkpoint of last record processed (Lower limit for inclusion) + TIMEOUT_HANDLER -> SEGMENT_DAO: Get last segment as @intervalMin + activate SEGMENT_DAO + SEGMENT_DAO -> DB: Get last segment as @intervalMin + hnote over DB #lightyellow + SELECT value INTO @intervalMin + FROM **segment** + WHERE segmentType = 'timeout' + AND enumeration = 0 + AND tableName = 'transferStateChange' + end note + activate DB + DB --> SEGMENT_DAO: Return @intervalMin + deactivate DB + SEGMENT_DAO --> TIMEOUT_HANDLER: Return @intervalMin + deactivate SEGMENT_DAO + opt @intervalMin IS NULL => segment record NOT FOUND + TIMEOUT_HANDLER->TIMEOUT_HANDLER: Set @intervalMin = 0 + end + end + + group Do Cleanup + TIMEOUT_HANDLER -> POS_DAO: Clean up transferTimeout from finalised transfers + activate POS_DAO + POS_DAO -> DB: Clean up transferTimeout from finalised transfers + hnote over DB #lightyellow + DELETE tt + FROM **transferTimeout** AS tt + JOIN (SELECT tsc.transferId, MAX(tsc.transferStateChangeId) maxTransferStateChangeId + FROM **transferTimeout** tt1 + JOIN **transferStateChange** tsc + ON tsc.transferId = tt1.transferId + GROUP BY transferId) ts + ON ts.transferId = tt.transferId + JOIN **transferStateChange** tsc + ON tsc.transferStateChangeId = ts.maxTransferStateChangeId + WHERE tsc.transferStateId IN ('RECEIVED_FULFIL', 'COMMITTED', 'FAILED' + , 'EXPIRED', 'REJECTED', 'EXPIRED_PREPARED', 'EXPIRED_RESERVED', 'ABORTED') + end note + activate DB + deactivate DB + POS_DAO --> TIMEOUT_HANDLER: Return success + deactivate POS_DAO + end + + group Determine IntervalMax (Upper limit for inclusion) + TIMEOUT_HANDLER -> POS_DAO: Get last transferStateChangeId as @intervalMax + activate POS_DAO + POS_DAO -> DB: Get last transferStateChangeId as @intervalMax + hnote over DB #lightyellow + SELECT MAX(transferStateChangeId) INTO @intervalMax + FROM **transferStateChange** + end note + activate DB + DB --> POS_DAO: Return @intervalMax + deactivate DB + POS_DAO --> TIMEOUT_HANDLER: Return @intervalMax + deactivate POS_DAO + end + + + group Prepare data and return the list for expiration + TIMEOUT_HANDLER -> POS_DAO: Prepare data and get transfers to be expired + activate POS_DAO + group DB TRANSACTION + POS_DAO <-> POS_DAO: **transactionTimestamp** = now() + POS_DAO -> DB: Insert all new transfers still in processing state + hnote over DB #lightyellow + INSERT INTO **transferTimeout**(transferId, expirationDate) + SELECT t.transferId, t.expirationDate + FROM **transfer** t + JOIN (SELECT transferId, MAX(transferStateChangeId) maxTransferStateChangeId + FROM **transferStateChange** + WHERE transferStateChangeId > @intervalMin + AND transferStateChangeId <= @intervalMax + GROUP BY transferId) ts + ON ts.transferId = t.transferId + JOIN **transferStateChange** tsc + ON tsc.transferStateChangeId = ts.maxTransferStateChangeId + WHERE tsc.transferStateId IN ('RECEIVED_PREPARE', 'RESERVED') + end note + activate DB + deactivate DB + + POS_DAO -> DB: Insert transfer state ABORTED for\nexpired RECEIVED_PREPARE transfers + hnote over DB #lightyellow + INSERT INTO **transferStateChange** + SELECT tt.transferId, 'EXPIRED_PREPARED' AS transferStateId, 'Aborted by Timeout Handler' AS reason + FROM **transferTimeout** tt + JOIN ( -- Following subquery is reused 3 times and may be optimized if needed + SELECT tsc1.transferId, MAX(tsc1.transferStateChangeId) maxTransferStateChangeId + FROM **transferStateChange** tsc1 + JOIN **transferTimeout** tt1 + ON tt1.transferId = tsc1.transferId + GROUP BY tsc1.transferId) ts + ON ts.transferId = tt.transferId + JOIN **transferStateChange** tsc + ON tsc.transferStateChangeId = ts.maxTransferStateChangeId + WHERE tt.expirationDate < {transactionTimestamp} + AND tsc.transferStateId = 'RECEIVED_PREPARE' + end note + activate DB + deactivate DB + + POS_DAO -> DB: Insert transfer state EXPIRED for\nexpired RESERVED transfers + hnote over DB #lightyellow + INSERT INTO **transferStateChange** + SELECT tt.transferId, 'RESERVED_TIMEOUT' AS transferStateId, 'Expired by Timeout Handler' AS reason + FROM **transferTimeout** tt + JOIN (SELECT tsc1.transferId, MAX(tsc1.transferStateChangeId) maxTransferStateChangeId + FROM **transferStateChange** tsc1 + JOIN **transferTimeout** tt1 + ON tt1.transferId = tsc1.transferId + GROUP BY tsc1.transferId) ts + ON ts.transferId = tt.transferId + JOIN **transferStateChange** tsc + ON tsc.transferStateChangeId = ts.maxTransferStateChangeId + WHERE tt.expirationDate < {transactionTimestamp} + AND tsc.transferStateId = 'RESERVED' + end note + activate DB + deactivate DB + + POS_DAO -> DB: Update segment table to be used for the next run + hnote over DB #lightyellow + IF @intervalMin = 0 + INSERT + INTO **segment**(segmentType, enumeration, tableName, value) + VALUES ('timeout', 0, 'transferStateChange', @intervalMax) + ELSE + UPDATE **segment** + SET value = @intervalMax + WHERE segmentType = 'timeout' + AND enumeration = 0 + AND tableName = 'transferStateChange' + end note + activate DB + deactivate DB + end + + POS_DAO -> DB: Get list of transfers to be expired with current state + hnote over DB #lightyellow + SELECT tt.*, tsc.transferStateId, tp1.participantCurrencyId payerParticipantId, + tp2.participantCurrencyId payeeParticipantId, bta.bulkTransferId + FROM **transferTimeout** tt + JOIN (SELECT tsc1.transferId, MAX(tsc1.transferStateChangeId) maxTransferStateChangeId + FROM **transferStateChange** tsc1 + JOIN **transferTimeout** tt1 + ON tt1.transferId = tsc1.transferId + GROUP BY tsc1.transferId) ts + ON ts.transferId = tt.transferId + JOIN **transferStateChange** tsc + ON tsc.transferStateChangeId = ts.maxTransferStateChangeId + JOIN **transferParticipant** tp1 + ON tp1.transferId = tt.transferId + AND tp1.transferParticipantRoleTypeId = {PAYER_DFSP} + AND tp1.ledgerEntryTypeId = {PRINCIPLE_VALUE} + JOIN **transferParticipant** tp2 + ON tp2.transferId = tt.transferId + AND tp2.transferParticipantRoleTypeId = {PAYEE_DFSP} + AND tp2.ledgerEntryTypeId = {PRINCIPLE_VALUE} + LEFT JOIN **bulkTransferAssociation** bta + ON bta.transferId = tt.transferId + WHERE tt.expirationDate < {transactionTimestamp} + end note + activate DB + POS_DAO <-- DB: Return **transferTimeoutList** + deactivate DB + POS_DAO --> TIMEOUT_HANDLER: Return **transferTimeoutList** + deactivate POS_DAO + end + + loop for each transfer in the list + ||| + alt transferTimeoutList.bulkTransferId == NULL (Regular Transfer) + alt transferStateId == 'RECEIVED_PREPARE' + note right of TIMEOUT_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: { + Content-Length: , + Content-Type: , + Date: , + X-Forwarded-For: , + FSPIOP-Source: , + FSPIOP-Destination: , + FSPIOP-Encryption: , + FSPIOP-Signature: , + FSPIOP-URI: , + FSPIOP-HTTP-Method: + }, + payload: { + "errorInformation": { + "errorCode": 3300, + "errorDescription": "Generic expired error", + "extensionList": + } + } + }, + metadata: { + event: { + id: , + type: notification, + action: timeout-received, + createdAt: , + state: { + status: 'error', + code: + description: + } + } + } + } + end note + TIMEOUT_HANDLER -> NOTIFICATIONS_TOPIC: Publish Notification event + activate NOTIFICATIONS_TOPIC + deactivate NOTIFICATIONS_TOPIC + else transferStateId == 'RESERVED' + note right of TIMEOUT_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: { + Content-Length: , + Content-Type: , + Date: , + X-Forwarded-For: , + FSPIOP-Source: , + FSPIOP-Destination: , + FSPIOP-Encryption: , + FSPIOP-Signature: , + FSPIOP-URI: , + FSPIOP-HTTP-Method: + }, + payload: { + "errorInformation": { + "errorCode": 3300, + "errorDescription": "Generic expired error", + "extensionList": + } + } + }, + metadata: { + event: { + id: , + type: position, + action: timeout-reserved, + createdAt: , + state: { + status: 'error', + code: + description: + } + } + } + } + end note + TIMEOUT_HANDLER -> TOPIC_TRANSFER_POSITION: Route & Publish Position event + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + end + else Individual Transfer from a Bulk + alt transferStateId == 'RECEIVED_PREPARE' + note right of TIMEOUT_HANDLER #yellow + Message: + { + id: , + transferId: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: { + "errorInformation": { + "errorCode": 3300, + "errorDescription": "Generic expired error", + "extensionList": + } + } + }, + metadata: { + event: { + id: , + type: bulk-processing, + action: bulk-timeout-received, + createdAt: , + state: { + status: 'error', + code: + description: + } + } + } + } + end note + TIMEOUT_HANDLER -> BULK_PROCESSING_TOPIC: Publish to Bulk Processing topic + activate BULK_PROCESSING_TOPIC + deactivate BULK_PROCESSING_TOPIC + else transferStateId == 'RESERVED' + note right of TIMEOUT_HANDLER #yellow + Message: + { + id: , + transferId: , + from: , + to: , + type: application/json, + content: { + headers: ,, + payload: { + "errorInformation": { + "errorCode": 3300, + "errorDescription": "Generic expired error", + "extensionList": + } + } + }, + metadata: { + event: { + id: , + type: position, + action: bulk-timeout-reserved, + createdAt: , + state: { + status: 'error', + code: + description: + } + } + } + } + end note + TIMEOUT_HANDLER -> TOPIC_TRANSFER_POSITION: Route & Publish Position event + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + end + end + end + + deactivate TIMEOUT_HANDLER +end +@enduml diff --git a/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-3.1.1-timeout-handler.svg b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-3.1.1-timeout-handler.svg new file mode 100644 index 000000000..4f687da29 --- /dev/null +++ b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-3.1.1-timeout-handler.svg @@ -0,0 +1,1340 @@ + + + + + + + + + + + 3.1.1. Timeout Handler Consume (incl. Bulk Transfer) + + + + Central Service + + + + + + + + + + + + + + Transfer Timeout + + + Handler + + + + + Transfer Timeout + + + Handler + + + + + + + topic- + + + transfer-position + + + + + topic- + + + transfer-position + + + + + topic- + + + notification + + + + + topic- + + + notification + + + + + topic-event + + + + + topic-event + + + + + topic- + + + bulk-processing + + + + + topic- + + + bulk-processing + + + Position DAO + + + + + Position DAO + + + + + Segment DAO + + + + + Segment DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Timeout Handler Consume + + + + + Persist Event Information + + + + + 1 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + Get previous checkpoint of last record processed (Lower limit for inclusion) + + + + + 2 + + + Get last segment as @intervalMin + + + + + 3 + + + Get last segment as @intervalMin + + + + SELECT value INTO @intervalMin + + + FROM + + + segment + + + WHERE segmentType = 'timeout' + + + AND enumeration = 0 + + + AND tableName = 'transferStateChange' + + + + + 4 + + + Return @intervalMin + + + + + 5 + + + Return @intervalMin + + + + + opt + + + [@intervalMin IS NULL => segment record NOT FOUND] + + + + + 6 + + + Set @intervalMin = 0 + + + + + Do Cleanup + + + + + 7 + + + Clean up transferTimeout from finalised transfers + + + + + 8 + + + Clean up transferTimeout from finalised transfers + + + + DELETE tt + + + FROM + + + transferTimeout + + + AS tt + + + JOIN (SELECT tsc.transferId, MAX(tsc.transferStateChangeId) maxTransferStateChangeId + + + FROM + + + transferTimeout + + + tt1 + + + JOIN + + + transferStateChange + + + tsc + + + ON tsc.transferId = tt1.transferId + + + GROUP BY transferId) ts + + + ON ts.transferId = tt.transferId + + + JOIN + + + transferStateChange + + + tsc + + + ON tsc.transferStateChangeId = ts.maxTransferStateChangeId + + + WHERE tsc.transferStateId IN ('RECEIVED_FULFIL', 'COMMITTED', 'FAILED' + + + , 'EXPIRED', 'REJECTED', 'EXPIRED_PREPARED', 'EXPIRED_RESERVED', 'ABORTED') + + + + + 9 + + + Return success + + + + + Determine IntervalMax (Upper limit for inclusion) + + + + + 10 + + + Get last transferStateChangeId as @intervalMax + + + + + 11 + + + Get last transferStateChangeId as @intervalMax + + + + SELECT MAX(transferStateChangeId) INTO @intervalMax + + + FROM + + + transferStateChange + + + + + 12 + + + Return @intervalMax + + + + + 13 + + + Return @intervalMax + + + + + Prepare data and return the list for expiration + + + + + 14 + + + Prepare data and get transfers to be expired + + + + + DB TRANSACTION + + + + + 15 + + + transactionTimestamp + + + = now() + + + + + 16 + + + Insert all new transfers still in processing state + + + + INSERT INTO + + + transferTimeout + + + (transferId, expirationDate) + + + SELECT t.transferId, t.expirationDate + + + FROM + + + transfer + + + t + + + JOIN (SELECT transferId, MAX(transferStateChangeId) maxTransferStateChangeId + + + FROM + + + transferStateChange + + + WHERE transferStateChangeId > @intervalMin + + + AND transferStateChangeId <= @intervalMax + + + GROUP BY transferId) ts + + + ON ts.transferId = t.transferId + + + JOIN + + + transferStateChange + + + tsc + + + ON tsc.transferStateChangeId = ts.maxTransferStateChangeId + + + WHERE tsc.transferStateId IN ('RECEIVED_PREPARE', 'RESERVED') + + + + + 17 + + + Insert transfer state ABORTED for + + + expired RECEIVED_PREPARE transfers + + + + INSERT INTO + + + transferStateChange + + + SELECT tt.transferId, 'EXPIRED_PREPARED' AS transferStateId, 'Aborted by Timeout Handler' AS reason + + + FROM + + + transferTimeout + + + tt + + + JOIN ( + + + -- Following subquery is reused 3 times and may be optimized if needed + + + SELECT tsc1.transferId, MAX(tsc1.transferStateChangeId) maxTransferStateChangeId + + + FROM + + + transferStateChange + + + tsc1 + + + JOIN + + + transferTimeout + + + tt1 + + + ON tt1.transferId = tsc1.transferId + + + GROUP BY tsc1.transferId) ts + + + ON ts.transferId = tt.transferId + + + JOIN + + + transferStateChange + + + tsc + + + ON tsc.transferStateChangeId = ts.maxTransferStateChangeId + + + WHERE tt.expirationDate < {transactionTimestamp} + + + AND tsc.transferStateId = 'RECEIVED_PREPARE' + + + + + 18 + + + Insert transfer state EXPIRED for + + + expired RESERVED transfers + + + + INSERT INTO + + + transferStateChange + + + SELECT tt.transferId, 'RESERVED_TIMEOUT' AS transferStateId, 'Expired by Timeout Handler' AS reason + + + FROM + + + transferTimeout + + + tt + + + JOIN (SELECT tsc1.transferId, MAX(tsc1.transferStateChangeId) maxTransferStateChangeId + + + FROM + + + transferStateChange + + + tsc1 + + + JOIN + + + transferTimeout + + + tt1 + + + ON tt1.transferId = tsc1.transferId + + + GROUP BY tsc1.transferId) ts + + + ON ts.transferId = tt.transferId + + + JOIN + + + transferStateChange + + + tsc + + + ON tsc.transferStateChangeId = ts.maxTransferStateChangeId + + + WHERE tt.expirationDate < {transactionTimestamp} + + + AND tsc.transferStateId = 'RESERVED' + + + + + 19 + + + Update segment table to be used for the next run + + + + IF @intervalMin = 0 + + + INSERT + + + INTO + + + segment + + + (segmentType, enumeration, tableName, value) + + + VALUES ('timeout', 0, 'transferStateChange', @intervalMax) + + + ELSE + + + UPDATE + + + segment + + + SET value = @intervalMax + + + WHERE segmentType = 'timeout' + + + AND enumeration = 0 + + + AND tableName = 'transferStateChange' + + + + + 20 + + + Get list of transfers to be expired with current state + + + + SELECT tt.*, tsc.transferStateId, tp1.participantCurrencyId payerParticipantId, + + + tp2.participantCurrencyId payeeParticipantId, bta.bulkTransferId + + + FROM + + + transferTimeout + + + tt + + + JOIN (SELECT tsc1.transferId, MAX(tsc1.transferStateChangeId) maxTransferStateChangeId + + + FROM + + + transferStateChange + + + tsc1 + + + JOIN + + + transferTimeout + + + tt1 + + + ON tt1.transferId = tsc1.transferId + + + GROUP BY tsc1.transferId) ts + + + ON ts.transferId = tt.transferId + + + JOIN + + + transferStateChange + + + tsc + + + ON tsc.transferStateChangeId = ts.maxTransferStateChangeId + + + JOIN + + + transferParticipant + + + tp1 + + + ON tp1.transferId = tt.transferId + + + AND tp1.transferParticipantRoleTypeId = {PAYER_DFSP} + + + AND tp1.ledgerEntryTypeId = {PRINCIPLE_VALUE} + + + JOIN + + + transferParticipant + + + tp2 + + + ON tp2.transferId = tt.transferId + + + AND tp2.transferParticipantRoleTypeId = {PAYEE_DFSP} + + + AND tp2.ledgerEntryTypeId = {PRINCIPLE_VALUE} + + + LEFT JOIN + + + bulkTransferAssociation + + + bta + + + ON bta.transferId = tt.transferId + + + WHERE tt.expirationDate < {transactionTimestamp} + + + + + 21 + + + Return + + + transferTimeoutList + + + + + 22 + + + Return + + + transferTimeoutList + + + + + loop + + + [for each transfer in the list] + + + + + alt + + + [transferTimeoutList.bulkTransferId == NULL (Regular Transfer)] + + + + + alt + + + [transferStateId == 'RECEIVED_PREPARE'] + + + + + Message: + + + { + + + id: <transferId>, + + + from: <payerParticipantId>, + + + to: <payeeParticipantId>, + + + type: application/json, + + + content: { + + + headers: { + + + Content-Length: <Content-Length>, + + + Content-Type: <Content-Type>, + + + Date: <Date>, + + + X-Forwarded-For: <X-Forwarded-For>, + + + FSPIOP-Source: <FSPIOP-Source>, + + + FSPIOP-Destination: <FSPIOP-Destination>, + + + FSPIOP-Encryption: <FSPIOP-Encryption>, + + + FSPIOP-Signature: <FSPIOP-Signature>, + + + FSPIOP-URI: <FSPIOP-URI>, + + + FSPIOP-HTTP-Method: <FSPIOP-HTTP-Method> + + + }, + + + payload: { + + + "errorInformation": { + + + "errorCode": 3300, + + + "errorDescription": "Generic expired error", + + + "extensionList": <transferMessage.extensionList> + + + } + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + type: notification, + + + action: timeout-received, + + + createdAt: <timestamp>, + + + state: { + + + status: 'error', + + + code: <errorInformation.errorCode> + + + description: <errorInformation.errorDescription> + + + } + + + } + + + } + + + } + + + + + 23 + + + Publish Notification event + + + + [transferStateId == 'RESERVED'] + + + + + Message: + + + { + + + id: <transferId>, + + + from: <payerParticipantId>, + + + to: <payeeParticipantId>, + + + type: application/json, + + + content: { + + + headers: { + + + Content-Length: <Content-Length>, + + + Content-Type: <Content-Type>, + + + Date: <Date>, + + + X-Forwarded-For: <X-Forwarded-For>, + + + FSPIOP-Source: <FSPIOP-Source>, + + + FSPIOP-Destination: <FSPIOP-Destination>, + + + FSPIOP-Encryption: <FSPIOP-Encryption>, + + + FSPIOP-Signature: <FSPIOP-Signature>, + + + FSPIOP-URI: <FSPIOP-URI>, + + + FSPIOP-HTTP-Method: <FSPIOP-HTTP-Method> + + + }, + + + payload: { + + + "errorInformation": { + + + "errorCode": 3300, + + + "errorDescription": "Generic expired error", + + + "extensionList": <transferMessage.extensionList> + + + } + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + type: position, + + + action: timeout-reserved, + + + createdAt: <timestamp>, + + + state: { + + + status: 'error', + + + code: <errorInformation.errorCode> + + + description: <errorInformation.errorDescription> + + + } + + + } + + + } + + + } + + + + + 24 + + + Route & Publish Position event + + + + [Individual Transfer from a Bulk] + + + + + alt + + + [transferStateId == 'RECEIVED_PREPARE'] + + + + + Message: + + + { + + + id + + + : <transferTimeoutList.bulkTransferId>, + + + transferId + + + : <transferTimeoutList.transferId>, + + + from: <payerParticipantId>, + + + to: <payeeParticipantId>, + + + type: application/json, + + + content: { + + + headers: <bulkTransferHeaders>, + + + payload: { + + + "errorInformation": { + + + "errorCode": 3300, + + + "errorDescription": "Generic expired error", + + + "extensionList": <transferMessage.extensionList> + + + } + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + type: bulk-processing, + + + action: bulk-timeout-received, + + + createdAt: <timestamp>, + + + state: { + + + status: 'error', + + + code: <errorInformation.errorCode> + + + description: <errorInformation.errorDescription> + + + } + + + } + + + } + + + } + + + + + 25 + + + Publish to Bulk Processing topic + + + + [transferStateId == 'RESERVED'] + + + + + Message: + + + { + + + id + + + : <transferTimeoutList.bulkTransferId>, + + + transferId + + + : <transferTimeoutList.transferId>, + + + from: <payerParticipantId>, + + + to: <payeeParticipantId>, + + + type: application/json, + + + content: { + + + headers: <bulkTransferHeaders>,, + + + payload: { + + + "errorInformation": { + + + "errorCode": 3300, + + + "errorDescription": "Generic expired error", + + + "extensionList": <transferMessage.extensionList> + + + } + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + type: position, + + + action: bulk-timeout-reserved, + + + createdAt: <timestamp>, + + + state: { + + + status: 'error', + + + code: <errorInformation.errorCode> + + + description: <errorInformation.errorDescription> + + + } + + + } + + + } + + + } + + + + + 26 + + + Route & Publish Position event + + diff --git a/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-4.1.0-abort-overview.plantuml b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-4.1.0-abort-overview.plantuml new file mode 100644 index 000000000..e02a15142 --- /dev/null +++ b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-4.1.0-abort-overview.plantuml @@ -0,0 +1,233 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Steven Oderayi + -------------- + ******'/ + +@startuml +' declare title +title 4.1.0. Bulk Transfer Abort + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +actor "DFSP1\nPayer" as DFSP1 +actor "DFSP2\nPayee" as DFSP2 +boundary "Bulk API Adapter" as BULKAPI +control "Bulk API Notification Event Handler" as NOTIFY_HANDLER +boundary "Central Service API" as CSAPI +collections "Bulk-Fulfil-Topic" as TOPIC_BULK_FULFIL +collections "Fulfil-Topic" as TOPIC_FULFIL +control "Bulk Fulfil Event Handler" as BULK_FULFIL_HANDLER +control "Fulfil Event Handler" as FULFIL_HANDLER +collections "topic-transfer-position" as TOPIC_POSITION +control "Position Event Handler" as POS_HANDLER +collections "topic-bulk-processing" as TOPIC_BULK_PROCESSING +control "Bulk Processing Event Handler" as BULK_PROCESSING_HANDLER +collections "Event-Topic" as TOPIC_EVENTS +collections "Notification-Topic" as TOPIC_NOTIFICATIONS +collections "mojaloop-\nobject-store\n(**MLOS**)" as OBJECT_STORE +database "Central Services DB" as DB + +box "Financial Service Providers" #lightGray + participant DFSP1 + participant DFSP2 +end box + +box "Bulk API Adapter Service" #LightBlue + participant BULKAPI + participant NOTIFY_HANDLER +end box + +box "Central Service" #LightYellow + participant CSAPI + participant TOPIC_BULK_FULFIL + participant TOPIC_FULFIL + participant BULK_FULFIL_HANDLER + participant FULFIL_HANDLER + participant TOPIC_POSITION + participant TOPIC_EVENTS + participant POS_HANDLER + participant TOPIC_BULK_PROCESSING + participant BULK_PROCESSING_HANDLER + participant TOPIC_NOTIFICATIONS + participant OBJECT_STORE + participant DB +end box + +' start flow +activate NOTIFY_HANDLER +activate BULK_FULFIL_HANDLER +activate FULFIL_HANDLER +activate FULFIL_HANDLER +activate BULK_PROCESSING_HANDLER +activate POS_HANDLER + +group DFSP2 sends a Fulfil Abort Transfer request + note right of DFSP2 #lightblue + **Note**: In the payload for PUT /bulkTransfers//error + only the **errorInformation** field is **required** + end note + note right of DFSP2 #yellow + Headers - transferHeaders: { + Content-Length: , + Content-Type: , + Date: , + X-Forwarded-For: , + FSPIOP-Source: , + FSPIOP-Destination: , + FSPIOP-Encryption: , + FSPIOP-Signature: , + FSPIOP-URI: , + FSPIOP-HTTP-Method: + } + Payload - errorMessage: + { + "errorInformation": { + "errorCode": , + "errorDescription": , + "extensionList": { + "extension": [ + { + "key": , + "value": + } + ] + } + } + } + end note + DFSP2 ->> BULKAPI: **PUT - /bulkTransfers//error** + activate BULKAPI + + BULKAPI -> OBJECT_STORE: Persist request payload with messageId in cache + activate OBJECT_STORE + note right of BULKAPI #yellow + Message: { + messageId: , + bulkTransferId: , + payload: + } + end note + hnote over OBJECT_STORE #lightyellow + individualTransferFulfils + end hnote + BULKAPI <- OBJECT_STORE: Response of save operation + deactivate OBJECT_STORE + note right of BULKAPI #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + type: fulfil, + action: reject, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + BULKAPI -> TOPIC_BULK_FULFIL: Produce bulk-fulfil message + BULKAPI -->> DFSP2: Respond HTTP - 200 (OK) + TOPIC_BULK_FULFIL <- BULK_FULFIL_HANDLER: Consume bulk-fulfil message + BULK_FULFIL_HANDLER -> BULK_FULFIL_HANDLER: Perform duplicate check + BULK_FULFIL_HANDLER -> BULK_FULFIL_HANDLER: Validate request + loop n times, n = number of individual transfers + note right of BULK_FULFIL_HANDLER + Message: { + transferId: , + bulkTransferId< , + bulkTransferAssociationRecord: { + transferId: , + bulkTransferId: , + bulkProcessingStateId: , + errorCode: , + errorDescription: + } + } + end note + BULK_FULFIL_HANDLER -> DB: Update bulkTransferAssociation table + activate DB + hnote over DB #lightyellow + bulkTransferAssociation + end hnote + deactivate DB + BULK_FULFIL_HANDLER -> TOPIC_FULFIL: Produce fulfil message with action bulk-abort for each individual transfer + end + ||| + loop n times, n = number of individual transfers + TOPIC_FULFIL <- FULFIL_HANDLER: Consume message + ref over TOPIC_FULFIL, TOPIC_EVENTS: Fulfil Handler Consume (bulk-abort)\n + FULFIL_HANDLER -> TOPIC_POSITION: Produce message + end + ||| + loop n times, n = number of individual transfers + TOPIC_POSITION <- POS_HANDLER: Consume message + ref over TOPIC_POSITION, BULK_PROCESSING_HANDLER: Position Handler Consume (bulk-abort)\n + POS_HANDLER -> TOPIC_BULK_PROCESSING: Produce message + end + ||| + loop n times, n = number of individual transfers + TOPIC_BULK_PROCESSING <- BULK_PROCESSING_HANDLER: Consume individual transfer message + ref over TOPIC_BULK_PROCESSING, TOPIC_NOTIFICATIONS: Bulk Processing Handler Consume (bulk-abort)\n + end + BULK_PROCESSING_HANDLER -> TOPIC_NOTIFICATIONS: Produce message (Payer) + BULK_PROCESSING_HANDLER -> TOPIC_NOTIFICATIONS: Produce message (Payee) + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message (Payer) + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message (Payee) + opt action == 'bulk-abort' + ||| + ref over DFSP1, TOPIC_NOTIFICATIONS: Notification Handler (Payer)\n + NOTIFY_HANDLER -> DFSP1: Send callback notification + end + ||| + opt action == 'bulk-abort' + ||| + ref over DFSP2, TOPIC_NOTIFICATIONS: Notification Handler (Payee)\n + NOTIFY_HANDLER -> DFSP2: Send callback notification + end + ||| +end +activate POS_HANDLER +activate FULFIL_HANDLER +activate FULFIL_HANDLER +activate NOTIFY_HANDLER +@enduml + diff --git a/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-4.1.0-abort-overview.svg b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-4.1.0-abort-overview.svg new file mode 100644 index 000000000..65d6a65a7 --- /dev/null +++ b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-4.1.0-abort-overview.svg @@ -0,0 +1,732 @@ + + + + + + + + + + + 4.1.0. Bulk Transfer Abort + + + + Financial Service Providers + + + + Bulk API Adapter Service + + + + Central Service + + + + + + + + DFSP1 + + + Payer + + + + + DFSP1 + + + Payer + + + + + DFSP2 + + + Payee + + + + + DFSP2 + + + Payee + + + + + Bulk API Adapter + + + + + Bulk API Adapter + + + + + Bulk API Notification Event Handler + + + + + Bulk API Notification Event Handler + + + + + Central Service API + + + + + Central Service API + + + + + + + Bulk-Fulfil-Topic + + + + + Bulk-Fulfil-Topic + + + + + Fulfil-Topic + + + + + Fulfil-Topic + + + Bulk Fulfil Event Handler + + + + + Bulk Fulfil Event Handler + + + + + Fulfil Event Handler + + + + + Fulfil Event Handler + + + + + + + topic-transfer-position + + + + + topic-transfer-position + + + + + Event-Topic + + + + + Event-Topic + + + Position Event Handler + + + + + Position Event Handler + + + + + + + topic-bulk-processing + + + + + topic-bulk-processing + + + Bulk Processing Event Handler + + + + + Bulk Processing Event Handler + + + + + + + Notification-Topic + + + + + Notification-Topic + + + + + mojaloop- + + + object-store + + + ( + + + MLOS + + + ) + + + + + mojaloop- + + + object-store + + + ( + + + MLOS + + + ) + + + Central Services DB + + + + + Central Services DB + + + + + + + + + DFSP2 sends a Fulfil Abort Transfer request + + + + + Note + + + : In the payload for PUT /bulkTransfers/<ID>/error + + + only the + + + errorInformation + + + field is + + + required + + + + + Headers - transferHeaders: { + + + Content-Length: <Content-Length>, + + + Content-Type: <Content-Type>, + + + Date: <Date>, + + + X-Forwarded-For: <X-Forwarded-For>, + + + FSPIOP-Source: <FSPIOP-Source>, + + + FSPIOP-Destination: <FSPIOP-Destination>, + + + FSPIOP-Encryption: <FSPIOP-Encryption>, + + + FSPIOP-Signature: <FSPIOP-Signature>, + + + FSPIOP-URI: <FSPIOP-URI>, + + + FSPIOP-HTTP-Method: <FSPIOP-HTTP-Method> + + + } + + + Payload - errorMessage: + + + { + + + "errorInformation": { + + + "errorCode": <string>, + + + "errorDescription": <string>, + + + "extensionList": { + + + "extension": [ + + + { + + + "key": <string>, + + + "value": <string> + + + } + + + ] + + + } + + + } + + + } + + + + 1 + + + PUT - /bulkTransfers/<ID>/error + + + + + 2 + + + Persist request payload with messageId in cache + + + + + Message: { + + + messageId: <string>, + + + bulkTransferId: <string>, + + + payload: <object> + + + } + + + + individualTransferFulfils + + + + + 3 + + + Response of save operation + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + type: fulfil, + + + action: reject, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 4 + + + Produce bulk-fulfil message + + + + + 5 + + + Respond HTTP - 200 (OK) + + + + + 6 + + + Consume bulk-fulfil message + + + + + 7 + + + Perform duplicate check + + + + + 8 + + + Validate request + + + + + loop + + + [n times, n = number of individual transfers] + + + + + Message: { + + + transferId: <string>, + + + bulkTransferId< <string>, + + + bulkTransferAssociationRecord: { + + + transferId: <string>, + + + bulkTransferId: <string>, + + + bulkProcessingStateId: <string>, + + + errorCode: <string>, + + + errorDescription: <string> + + + } + + + } + + + + + 9 + + + Update bulkTransferAssociation table + + + + bulkTransferAssociation + + + + + 10 + + + Produce fulfil message with action bulk-abort for each individual transfer + + + + + loop + + + [n times, n = number of individual transfers] + + + + + 11 + + + Consume message + + + + + ref + + + Fulfil Handler Consume (bulk-abort) + + + + + 12 + + + Produce message + + + + + loop + + + [n times, n = number of individual transfers] + + + + + 13 + + + Consume message + + + + + ref + + + Position Handler Consume (bulk-abort) + + + + + 14 + + + Produce message + + + + + loop + + + [n times, n = number of individual transfers] + + + + + 15 + + + Consume individual transfer message + + + + + ref + + + Bulk Processing Handler Consume (bulk-abort) + + + + + 16 + + + Produce message (Payer) + + + + + 17 + + + Produce message (Payee) + + + + + 18 + + + Consume message (Payer) + + + + + 19 + + + Consume message (Payee) + + + + + opt + + + [action == 'bulk-abort'] + + + + + ref + + + Notification Handler (Payer) + + + + + 20 + + + Send callback notification + + + + + opt + + + [action == 'bulk-abort'] + + + + + ref + + + Notification Handler (Payee) + + + + + 21 + + + Send callback notification + + diff --git a/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-5.1.0-get-overview.plantuml b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-5.1.0-get-overview.plantuml new file mode 100644 index 000000000..e219f2465 --- /dev/null +++ b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-5.1.0-get-overview.plantuml @@ -0,0 +1,209 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Steven Oderayi + -------------- + ******'/ + +@startuml +' declate title +title 5.1.0. Request Bulk Transfer Status + +autonumber + +' declare actors +actor "DFSP(n)\nParticipant" as DFSP +control "Bulk API Notification Event Handler" as NOTIFY_HANDLER +boundary "Bulk API Adapter" as BULKAPI +collections "Topic-Transfer-Get" as TOPIC_GET +control "GET Event Handler" as GET_HANDLER +entity "Bulk Transfer DAO" as BULK_TRANSFER_DAO +database "Central Store" as DB + +box "Financial Service Provider" #lightGray + participant DFSP +end box +box "Bulk API Adapter Service" #LightBlue + participant BULKAPI + participant NOTIFY_HANDLER +end box +box "Central Ledger" #LightYellow + participant TOPIC_GET + participant GET_HANDLER + participant BULK_TRANSFER_DAO + participant DB +end box + +' start flow +group Request Bulk transfer status + activate DFSP + DFSP -> BULKAPI: Request bulk transfer status - GET - /bulkTransfers/{ID} + activate BULKAPI + ||| + BULKAPI -> TOPIC_GET: Publish event information + deactivate BULKAPI + activate TOPIC_GET + ||| + deactivate GET_HANDLER + + DFSP <-- BULKAPI: Respond HTTP - 200 (OK) + deactivate DFSP + deactivate BULKAPI + GET_HANDLER -> TOPIC_GET: Consume message + ||| + ref over TOPIC_GET, GET_HANDLER : GET Handler Consume\n + ||| + deactivate TOPIC_GET + + GET_HANDLER -> BULK_TRANSFER_DAO: Request bulk transfer participants + activate GET_HANDLER + activate BULK_TRANSFER_DAO + BULK_TRANSFER_DAO -> DB: Fetch bulk transfer participants + activate DB + hnote over DB #lightYellow + bulkTransfer + participant + end hnote + BULK_TRANSFER_DAO <-- DB: Return query result + deactivate DB + GET_HANDLER <-- BULK_TRANSFER_DAO: Return bulk transfer participants + deactivate BULK_TRANSFER_DAO + alt Is request not from bulk transfer Payer or Payee FSP? + note left of NOTIFY_HANDLER #yellow + { + "errorInformation": { + "errorCode": 3210, + "errorDescription": "Bulk transfer ID not found" + } + } + end note + GET_HANDLER -> NOTIFY_HANDLER: Publish notification event (404) + deactivate GET_HANDLER + activate NOTIFY_HANDLER + DFSP <- NOTIFY_HANDLER: callback PUT on /bulkTransfers/{ID}/error + deactivate NOTIFY_HANDLER + end + GET_HANDLER -> BULK_TRANSFER_DAO: Request bulk transfer status + activate GET_HANDLER + activate BULK_TRANSFER_DAO + BULK_TRANSFER_DAO -> DB: Fetch bulk transfer status + + activate DB + hnote over DB #lightyellow + bulkTransferStateChange + bulkTransferState + bulkTransferError + bulkTransferExtension + transferStateChange + transferState + transferFulfilment + transferError + transferExtension + ilpPacket + end hnote + BULK_TRANSFER_DAO <-- DB: Return query result + deactivate DB + + GET_HANDLER <-- BULK_TRANSFER_DAO: Return bulk transfer status + deactivate BULK_TRANSFER_DAO + + alt Is there a bulk transfer with the given ID recorded in the system? + alt Bulk Transfer state is **"PROCESSING"** + note left of GET_HANDLER #yellow + { + "bulkTransferState": "PROCESSING" + } + end note + NOTIFY_HANDLER <- GET_HANDLER: Publish notification event + deactivate GET_HANDLER + activate NOTIFY_HANDLER + NOTIFY_HANDLER -> DFSP: Send callback - PUT /bulkTransfers/{ID} + deactivate NOTIFY_HANDLER + end + ||| + alt Request is from Payee FSP? + GET_HANDLER <-> GET_HANDLER: Exclude transfers with **transferStateId** not in \n [ **COMMITTED**, **ABORTED_REJECTED**, **EXPIRED_RESERVED** ] + activate GET_HANDLER + end + + note left of GET_HANDLER #yellow + { + "bulkTransferState": "", + "individualTransferResults": [ + { + "transferId": "", + "fulfilment": "WLctttbu2HvTsa1XWvUoGRcQozHsqeu9Ahl2JW9Bsu8", + "errorInformation": , + "extensionList": { + "extension": + [ + { + "key": "Description", + "value": "This is a more detailed description" + } + ] + } + } + ], + "completedTimestamp": "2018-09-24T08:38:08.699-04:00", + "extensionList": + { + "extension": + [ + { + "key": "Description", + "value": "This is a more detailed description" + } + ] + } + } + end note + note left of GET_HANDLER #lightGray + NOTE: If transfer is REJECTED, error information may be provided. + Either fulfilment or errorInformation should be set, not both. + end note + NOTIFY_HANDLER <- GET_HANDLER: Publish notification event + deactivate GET_HANDLER + activate NOTIFY_HANDLER + DFSP <- NOTIFY_HANDLER: callback PUT on /bulkTransfers/{ID} + deactivate NOTIFY_HANDLER + note right of NOTIFY_HANDLER #lightgray + Log ERROR event + end note + else A bulk transfer with the given ID is not present in the System or this is an invalid request + note left of NOTIFY_HANDLER #yellow + { + "errorInformation": { + "errorCode": 3210, + "errorDescription": "Bulk transfer ID not found" + } + } + end note + GET_HANDLER -> NOTIFY_HANDLER: Publish notification event (404) + activate NOTIFY_HANDLER + DFSP <- NOTIFY_HANDLER: callback PUT on /bulkTransfers/{ID}/error + deactivate NOTIFY_HANDLER + end + + deactivate GET_HANDLER + deactivate NOTIFY_HANDLER +deactivate DFSP +end +@enduml diff --git a/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-5.1.0-get-overview.svg b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-5.1.0-get-overview.svg new file mode 100644 index 000000000..0c0bb5959 --- /dev/null +++ b/docs/technical/central-bulk-transfers/assets/diagrams/sequence/seq-bulk-5.1.0-get-overview.svg @@ -0,0 +1,552 @@ + + + + + + + + + + + 5.1.0. Request Bulk Transfer Status + + + + Financial Service Provider + + + + Bulk API Adapter Service + + + + Central Ledger + + + + + + + + + DFSP(n) + + + Participant + + + + + DFSP(n) + + + Participant + + + + + Bulk API Adapter + + + + + Bulk API Adapter + + + + + Bulk API Notification Event Handler + + + + + Bulk API Notification Event Handler + + + + + + + Topic-Transfer-Get + + + + + Topic-Transfer-Get + + + GET Event Handler + + + + + GET Event Handler + + + + + Bulk Transfer DAO + + + + + Bulk Transfer DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Request Bulk transfer status + + + + + 1 + + + Request bulk transfer status - GET - /bulkTransfers/{ID} + + + + + 2 + + + Publish event information + + + + + 3 + + + Respond HTTP - 200 (OK) + + + + + 4 + + + Consume message + + + + + ref + + + GET Handler Consume + + + + + 5 + + + Request bulk transfer participants + + + + + 6 + + + Fetch bulk transfer participants + + + + bulkTransfer + + + participant + + + + + 7 + + + Return query result + + + + + 8 + + + Return bulk transfer participants + + + + + alt + + + [Is request not from bulk transfer Payer or Payee FSP?] + + + + + { + + + "errorInformation": { + + + "errorCode": 3210, + + + "errorDescription": "Bulk transfer ID not found" + + + } + + + } + + + + + 9 + + + Publish notification event (404) + + + + + 10 + + + callback PUT on /bulkTransfers/{ID}/error + + + + + 11 + + + Request bulk transfer status + + + + + 12 + + + Fetch bulk transfer status + + + + bulkTransferStateChange + + + bulkTransferState + + + bulkTransferError + + + bulkTransferExtension + + + transferStateChange + + + transferState + + + transferFulfilment + + + transferError + + + transferExtension + + + ilpPacket + + + + + 13 + + + Return query result + + + + + 14 + + + Return bulk transfer status + + + + + alt + + + [Is there a bulk transfer with the given ID recorded in the system?] + + + + + alt + + + [Bulk Transfer state is + + + "PROCESSING" + + + ] + + + + + { + + + "bulkTransferState": "PROCESSING" + + + } + + + + + 15 + + + Publish notification event + + + + + 16 + + + Send callback - PUT /bulkTransfers/{ID} + + + + + alt + + + [Request is from Payee FSP?] + + + + + 17 + + + Exclude transfers with + + + transferStateId + + + not in + + + [ + + + COMMITTED + + + , + + + ABORTED_REJECTED + + + , + + + EXPIRED_RESERVED + + + ] + + + + + { + + + "bulkTransferState": "<BulkTransferState>", + + + "individualTransferResults": [ + + + { + + + "transferId": "<TransferId>", + + + "fulfilment": "WLctttbu2HvTsa1XWvUoGRcQozHsqeu9Ahl2JW9Bsu8", + + + "errorInformation": <ErrorInformationObject>, + + + "extensionList": { + + + "extension": + + + [ + + + { + + + "key": "Description", + + + "value": "This is a more detailed description" + + + } + + + ] + + + } + + + } + + + ], + + + "completedTimestamp": "2018-09-24T08:38:08.699-04:00", + + + "extensionList": + + + { + + + "extension": + + + [ + + + { + + + "key": "Description", + + + "value": "This is a more detailed description" + + + } + + + ] + + + } + + + } + + + + + NOTE: If transfer is REJECTED, error information may be provided. + + + Either fulfilment or errorInformation should be set, not both. + + + + + 18 + + + Publish notification event + + + + + 19 + + + callback PUT on /bulkTransfers/{ID} + + + + + Log ERROR event + + + + [A bulk transfer with the given ID is not present in the System or this is an invalid request] + + + + + { + + + "errorInformation": { + + + "errorCode": 3210, + + + "errorDescription": "Bulk transfer ID not found" + + + } + + + } + + + + + 20 + + + Publish notification event (404) + + + + + 21 + + + callback PUT on /bulkTransfers/{ID}/error + + diff --git a/docs/technical/central-bulk-transfers/transfers/1.1.0-bulk-prepare-transfer-request-overview.md b/docs/technical/central-bulk-transfers/transfers/1.1.0-bulk-prepare-transfer-request-overview.md new file mode 100644 index 000000000..8ad8c6ce7 --- /dev/null +++ b/docs/technical/central-bulk-transfers/transfers/1.1.0-bulk-prepare-transfer-request-overview.md @@ -0,0 +1,15 @@ +# Bulk Prepare Transfer Request [Overview] [includes individual transfers in a bulk] + +Sequence design diagram for Prepare Transfer Request process. + +## References within Sequence Diagram + +* [Bulk Prepare Handler Consume (1.1.1)](1.1.1-bulk-prepare-handler-consume.md) +* [Prepare Handler Consume (1.2.1)](1.2.1-prepare-handler-consume-for-bulk.md) +* [Position Handler Consume (1.3.0)](1.3.0-position-handler-consume-overview.md) +* [Bulk Processing Handler Consume (1.4.1)](1.4.1-bulk-processing-handler.md) +* [Send notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant.md) + +## Sequence Diagram + +![seq-bulk-1.1.0-bulk-prepare-overview.svg](../assets/diagrams/sequence/seq-bulk-1.1.0-bulk-prepare-overview.svg) diff --git a/docs/technical/central-bulk-transfers/transfers/1.1.1-bulk-prepare-handler-consume.md b/docs/technical/central-bulk-transfers/transfers/1.1.1-bulk-prepare-handler-consume.md new file mode 100644 index 000000000..495a0fdaf --- /dev/null +++ b/docs/technical/central-bulk-transfers/transfers/1.1.1-bulk-prepare-handler-consume.md @@ -0,0 +1,11 @@ +# Bulk Prepare handler consume + +Sequence design diagram for Bulk Prepare Handler Consume process + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) + +## Sequence Diagram + +![seq-bulk-1.1.1-bulk-prepare-handler.svg](../assets/diagrams/sequence/seq-bulk-1.1.1-bulk-prepare-handler.svg) diff --git a/docs/technical/central-bulk-transfers/transfers/1.2.1-prepare-handler-consume-for-bulk.md b/docs/technical/central-bulk-transfers/transfers/1.2.1-prepare-handler-consume-for-bulk.md new file mode 100644 index 000000000..aabde9fb1 --- /dev/null +++ b/docs/technical/central-bulk-transfers/transfers/1.2.1-prepare-handler-consume-for-bulk.md @@ -0,0 +1,11 @@ +# Prepare handler consume [that includes individual transfers in a bulk] + +Sequence design diagram for Prepare Handler Consume process + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) + +## Sequence Diagram + +![seq-bulk-1.2.1-prepare-handler.svg](../assets/diagrams/sequence/seq-bulk-1.2.1-prepare-handler.svg) diff --git a/docs/technical/central-bulk-transfers/transfers/1.3.0-position-handler-consume-overview.md b/docs/technical/central-bulk-transfers/transfers/1.3.0-position-handler-consume-overview.md new file mode 100644 index 000000000..aae066006 --- /dev/null +++ b/docs/technical/central-bulk-transfers/transfers/1.3.0-position-handler-consume-overview.md @@ -0,0 +1,14 @@ +# Position Handler Consume [that includes individual transfers in a bulk] + +Sequence design diagram for Position Handler Consume process + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) +* [Prepare Position Handler Consume (1.3.1)](1.3.1-prepare-position-handler-consume.md) +* [Fufil Position Handler Consume (2.2.1)](2.2.1-fulfil-commit-for-bulk.md) +* [Abort Position Handler Consume (2.2.2)](2.2.2-fulfil-abort-for-bulk.md) + +## Sequence Diagram + +![seq-bulk-1.3.0-position-overview.svg](../assets/diagrams/sequence/seq-bulk-1.3.0-position-overview.svg) diff --git a/docs/technical/central-bulk-transfers/transfers/1.3.1-prepare-position-handler-consume.md b/docs/technical/central-bulk-transfers/transfers/1.3.1-prepare-position-handler-consume.md new file mode 100644 index 000000000..460ab7350 --- /dev/null +++ b/docs/technical/central-bulk-transfers/transfers/1.3.1-prepare-position-handler-consume.md @@ -0,0 +1,7 @@ +# Prepare Position Handler Consume [that includes individual transfers in a bulk] + +Sequence design diagram for Prepare Position Handler Consume process + +## Sequence Diagram + +![seq-bulk-1.3.1-position-prepare.svg](../assets/diagrams/sequence/seq-bulk-1.3.1-position-prepare.svg) diff --git a/docs/technical/central-bulk-transfers/transfers/1.4.1-bulk-processing-handler.md b/docs/technical/central-bulk-transfers/transfers/1.4.1-bulk-processing-handler.md new file mode 100644 index 000000000..53fe3c2b8 --- /dev/null +++ b/docs/technical/central-bulk-transfers/transfers/1.4.1-bulk-processing-handler.md @@ -0,0 +1,7 @@ +# Bulk Processing Handler Consume + +Sequence design diagram for Bulk Processing Handler Consume process + +## Sequence Diagram + +![seq-bulk-1.4.1-bulk-processing-handler.svg](../assets/diagrams/sequence/seq-bulk-1.4.1-bulk-processing-handler.svg) diff --git a/docs/technical/central-bulk-transfers/transfers/2.1.0-bulk-fulfil-transfer-request-overview.md b/docs/technical/central-bulk-transfers/transfers/2.1.0-bulk-fulfil-transfer-request-overview.md new file mode 100644 index 000000000..f08b37d9e --- /dev/null +++ b/docs/technical/central-bulk-transfers/transfers/2.1.0-bulk-fulfil-transfer-request-overview.md @@ -0,0 +1,15 @@ +# Bulk Fulfil Transfer Request Overview + +Sequence design diagram for the Bulk Fulfil Transfer request + +## References within Sequence Diagram + +* [Bulk Fulfil Handler Consume (Success) (2.1.1)](2.1.1-bulk-fulfil-handler-consume.md) +* [Fulfil Handler Consume (Success) (2.2.1)](2.2.1-fulfil-commit-for-bulk.md) +* [Position Handler Consume (Success) (2.3.1)](2.3.1-fulfil-position-handler-consume.md) +* [Bulk Processing Handler Consume (1.4.1)](1.4.1-bulk-processing-handler.md) +* [Send Notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant.md) + +## Sequence Diagram + +![seq-bulk-2.1.0-bulk-fulfil-overview.svg](../assets/diagrams/sequence/seq-bulk-2.1.0-bulk-fulfil-overview.svg) diff --git a/docs/technical/central-bulk-transfers/transfers/2.1.1-bulk-fulfil-handler-consume.md b/docs/technical/central-bulk-transfers/transfers/2.1.1-bulk-fulfil-handler-consume.md new file mode 100644 index 000000000..ea730d0b8 --- /dev/null +++ b/docs/technical/central-bulk-transfers/transfers/2.1.1-bulk-fulfil-handler-consume.md @@ -0,0 +1,13 @@ +# Bulk Fulfil Handler Consume + +Sequence design diagram for the Bulk Fulfil Handler Consume process + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) +* [seq-signature-validation](../../central-event-processor/signature-validation.md) +* [Send Notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant.md) + +## Sequence Diagram + +![seq-bulk-2.1.1-bulk-fulfil-handler.svg](../assets/diagrams/sequence/seq-bulk-2.1.1-bulk-fulfil-handler.svg) diff --git a/docs/technical/central-bulk-transfers/transfers/2.2.1-fulfil-commit-for-bulk.md b/docs/technical/central-bulk-transfers/transfers/2.2.1-fulfil-commit-for-bulk.md new file mode 100644 index 000000000..7a2102201 --- /dev/null +++ b/docs/technical/central-bulk-transfers/transfers/2.2.1-fulfil-commit-for-bulk.md @@ -0,0 +1,11 @@ +# Payee sends a Bulk Fulfil Transfer request - Bulk is broken down into individual transfers + +Sequence design diagram for the Bulk Fulfil Transfer for the Commit option + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) + +## Sequence Diagram + +![seq-bulk-2.2.1-fulfil-handler-commit.svg](../assets/diagrams/sequence/seq-bulk-2.2.1-fulfil-handler-commit.svg) diff --git a/docs/technical/central-bulk-transfers/transfers/2.2.2-fulfil-abort-for-bulk.md b/docs/technical/central-bulk-transfers/transfers/2.2.2-fulfil-abort-for-bulk.md new file mode 100644 index 000000000..6b32a71bc --- /dev/null +++ b/docs/technical/central-bulk-transfers/transfers/2.2.2-fulfil-abort-for-bulk.md @@ -0,0 +1,13 @@ +# Payee sends a Bulk Fulfil Transfer request - Bulk is broken down into individual transfers + +Sequence design diagram for the Fulfil Handler Consume Reject/Abort process + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) +* [seq-signature-validation](../../central-event-processor/signature-validation.md) +* [Send Notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant.md) + +## Sequence Diagram + +![seq-bulk-2.2.2-fulfil-handler-abort.svg](../assets/diagrams/sequence/seq-bulk-2.2.2-fulfil-handler-abort.svg) diff --git a/docs/technical/central-bulk-transfers/transfers/2.3.1-fulfil-position-handler-consume.md b/docs/technical/central-bulk-transfers/transfers/2.3.1-fulfil-position-handler-consume.md new file mode 100644 index 000000000..3b4d2877a --- /dev/null +++ b/docs/technical/central-bulk-transfers/transfers/2.3.1-fulfil-position-handler-consume.md @@ -0,0 +1,11 @@ +# Fulfil Position Handler Consume [that includes individual transfers in a bulk] + +Sequence design diagram for the Fulfil Position Handler Consume process + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) + +## Sequence Diagram + +![seq-bulk-2.3.1-position-fulfil.svg](../assets/diagrams/sequence/seq-bulk-2.3.1-position-fulfil.svg) diff --git a/docs/technical/central-bulk-transfers/transfers/2.3.2-position-consume-abort.md b/docs/technical/central-bulk-transfers/transfers/2.3.2-position-consume-abort.md new file mode 100644 index 000000000..ed4d3f9f8 --- /dev/null +++ b/docs/technical/central-bulk-transfers/transfers/2.3.2-position-consume-abort.md @@ -0,0 +1,7 @@ +# Position Handler Consume for Fulfil aborts at individual transfer level + +Sequence design diagram for Fulfil Position Handler Consume process + +## Sequence Diagram + +![seq-bulk-2.3.2-position-abort.svg](../assets/diagrams/sequence/seq-bulk-2.3.2-position-abort.svg) diff --git a/docs/technical/central-bulk-transfers/transfers/3.1.0-transfer-timeout-overview-for-bulk.md b/docs/technical/central-bulk-transfers/transfers/3.1.0-transfer-timeout-overview-for-bulk.md new file mode 100644 index 000000000..030f29281 --- /dev/null +++ b/docs/technical/central-bulk-transfers/transfers/3.1.0-transfer-timeout-overview-for-bulk.md @@ -0,0 +1,7 @@ +# Transfer Timeout [includes individual transfers in a Bulk] + +Sequence design diagram for the Transfer Timeout process. + +## Sequence Diagram + +![seq-bulk-3.1.0-timeout-overview.svg](../assets/diagrams/sequence/seq-bulk-3.1.0-timeout-overview.svg) diff --git a/docs/technical/central-bulk-transfers/transfers/3.1.1-transfer-timeout-handler-consume.md b/docs/technical/central-bulk-transfers/transfers/3.1.1-transfer-timeout-handler-consume.md new file mode 100644 index 000000000..d8fcefc23 --- /dev/null +++ b/docs/technical/central-bulk-transfers/transfers/3.1.1-transfer-timeout-handler-consume.md @@ -0,0 +1,7 @@ +# TimeOut Handler + +Sequence design diagram for Timeout Handler process + +## Sequence Diagram + +![seq-bulk-3.1.1-timeout-handler.svg](../assets/diagrams/sequence/seq-bulk-3.1.1-timeout-handler.svg) diff --git a/docs/technical/central-bulk-transfers/transfers/4.1.0-transfer-abort-overview-for-bulk.md b/docs/technical/central-bulk-transfers/transfers/4.1.0-transfer-abort-overview-for-bulk.md new file mode 100644 index 000000000..25c4873e4 --- /dev/null +++ b/docs/technical/central-bulk-transfers/transfers/4.1.0-transfer-abort-overview-for-bulk.md @@ -0,0 +1,7 @@ +# Bulk Transfer Abort Overview [includes individual transfers in a Bulk] + +Sequence design diagram for the Bulk Transfer Abort process. + +## Sequence Diagram + +![seq-bulk-4.1.0-abort-overview.svg](../assets/diagrams/sequence/seq-bulk-4.1.0-abort-overview.svg) diff --git a/docs/technical/central-bulk-transfers/transfers/5.1.0-transfer-get-overview-for-bulk.md b/docs/technical/central-bulk-transfers/transfers/5.1.0-transfer-get-overview-for-bulk.md new file mode 100644 index 000000000..d4d05674a --- /dev/null +++ b/docs/technical/central-bulk-transfers/transfers/5.1.0-transfer-get-overview-for-bulk.md @@ -0,0 +1,7 @@ +# Get Bulk Transfer Overview + +Sequence design diagram for the Get Bulk Transfer process. + +## Sequence Diagram + +![seq-bulk-5.1.0-get-overview.svg](../assets/diagrams/sequence/seq-bulk-5.1.0-get-overview.svg) diff --git a/docs/technical/central-bulk-transfers/transfers/README.md b/docs/technical/central-bulk-transfers/transfers/README.md new file mode 100644 index 000000000..36adeecc5 --- /dev/null +++ b/docs/technical/central-bulk-transfers/transfers/README.md @@ -0,0 +1,11 @@ +# Mojaloop Bulk Transfer operations + +Operational processes that is the core of the transfer operational process; + +- Bulk Prepare Process at Bulk Transfer level +- Prepare process at a single transfer level +- Bulk Fulfil process at Bulk Transfer level +- Fulfil process at a single transfer level +- Notifications process at Bulk Transfer level +- Reject/Abort process +- Bulk Processing at a single transfer level to aggregate Bulks diff --git a/docs/technical/central-ledger/.gitkeep b/docs/technical/central-ledger/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/docs/technical/central-ledger/README.md b/docs/technical/central-ledger/README.md new file mode 100644 index 000000000..69df63f59 --- /dev/null +++ b/docs/technical/central-ledger/README.md @@ -0,0 +1,52 @@ +# Central-Ledger Services + +The central ledger is a series of services that facilitate clearing and settlement of transfers between DFSPs, including the following functions: + +* Brokering real-time messaging for funds clearing +* Maintaining net positions for a deferred net settlement +* Propagating scheme-level and off-transfer fees + +## 1. Central Ledger Process Design + +### 1.1 Architecture overview + +![Central-Ledger Architecture](./assets/diagrams/architecture/Arch-mojaloop-central-ledger.svg) + +## 2. Transfers End-to-End Architecture + + +### 2.1 Transfers End-to-End Architecture for v1.1 +![Transfers Architecture for Mojaloop FSP Interoperability API v1.1](./assets/diagrams/architecture/Transfers-Arch-End-to-End-v1.1.svg) + +### 2.2 Transfers End-to-End Architecture for v1.0 +![Transfers Architecture for Mojaloop FSP Interoperability API v1.0](./assets/diagrams/architecture/Transfers-Arch-End-to-End-v1.0.svg) + +## 3. Database Design + +### Note + +The tables *Grey* colored tables are specific to the transfer process. The *Blue* and *Green* color tables are used for reference purposes during the Transfer process. + +Summary of the tables specific to the transfer process; + +- `transfer` - stores data related to the transfer; +- `transferDuplicateCheck` - used to identify duplication during the transfer requests process; +- `transferError` - stores information on transfer errors encountered during the transfer process; +- `transferErrorDuplicateCheck` - used to identify duplication error transfer processes; +- `transferExtensions` - stores information on the transfer extension data; +- `transferFulfilment` - stores data for transfers that have completed the prepare transfer process; +- `transferFulfilmentDuplicateCheck` - used the identify duplicate transfer fulfil requests; +- `transferParticipant` - participant information related to the transfer process; +- `transferStateChange` - use to track state changes of each individual transfer, creating and audit trail for a specific transfer request; +- `transferTimeout` - stores information of transfers that encountered a timeout exception during the process; +- `ilpPacket` - stores the ilp package for the transfer; + +The remaining tables in the below ERD are either lookup (blue) or settlement-specific (red) and are included as direct or indirect dependencies to depict the relation between the transfer specific entities and the transfer tables. + +The **Central Ledger** database schema definition [Central-Ledger Database Schema Definition](./assets/database/central-ledger-ddl-MySQLWorkbench.sql). + +![Central-Ledger Database Diagram](./assets/database/central-ledger-schema.png) + +## 4. API Specification + +Refer to **Central Ledger API** in the [API Specifications](../../api/README.md#central-ledger-api) section. diff --git a/docs/technical/central-ledger/admin-operations/1.0.0-get-health-check.md b/docs/technical/central-ledger/admin-operations/1.0.0-get-health-check.md new file mode 100644 index 000000000..021204219 --- /dev/null +++ b/docs/technical/central-ledger/admin-operations/1.0.0-get-health-check.md @@ -0,0 +1,265 @@ +# GET Health Check + +Design discussion for new Health Check implementation. + + +## Objectives + +The goal for this design is to implement a new Health check for mojaloop switch services that allows for a greater level of detail. + +It Features: +- Clear HTTP Statuses (no need to inspect the response to know there are no issues) +- ~Backwards compatibility with existing health checks~ - No longer a requirement. See [this discussion](https://github.com/mojaloop/project/issues/796#issuecomment-498350828). +- Information about the version of the API, and how long it has been running for +- Information about sub-service (kafka, logging sidecar and mysql) connections + +## Request Format +`/health` + +Uses the newly implemented health check. As discussed [here](https://github.com/mojaloop/project/issues/796#issuecomment-498350828) since there will be no added connection overhead (e.g. pinging a database) as part of implementing the health check, there is no need to complicate things with a simple and detailed version. + +Responses Codes: +- `200` - Success. The API is up and running, and is sucessfully connected to necessary services. +- `502` - Bad Gateway. The API is up and running, but the API cannot connect to necessary service (eg. `kafka`). +- `503` - Service Unavailable. This response is not implemented in this design, but will be the default if the api is not and running + +## Response Format + +| Name | Type | Description | Example | +| --- | --- | --- | --- | +| `status` | `statusEnum` | The status of the service. Options are `OK` and `DOWN`. _See `statusEnum` below_. | `"OK"` | +| `uptime` | `number` | How long (in seconds) the service has been alive for. | `123456` | +| `started` | `string` (ISO formatted date-time) | When the service was started (UTC) | `"2019-05-31T05:09:25.409Z"` | +| `versionNumber` | `string` (semver) | The current version of the service. | `"5.2.5"` | +| `services` | `Array` | A list of services this service depends on, and their connection status | _see below_ | + +### serviceHealth + +| Name | Type | Description | Example | +| --- | --- | --- | --- | +| `name` | `subServiceEnum` | The sub-service name. _See `subServiceEnum` below_. | `"broker"` | +| `status` | `enum` | The status of the service. Options are `OK` and `DOWN` | `"OK"` | + +### subServiceEnum + +The subServiceEnum enum describes a name of the subservice: + +Options: +- `datastore` -> The database for this service (typically a MySQL Database). +- `broker` -> The message broker for this service (typically Kafka). +- `sidecar` -> The logging sidecar sub-service this service attaches to. +- `cache` -> The caching sub-service this services attaches to. + + +### statusEnum + +The status enum represents status of the system or sub-service. + +It has two options: +- `OK` -> The service or sub-service is healthy. +- `DOWN` -> The service or sub-service is unhealthy. + +When a service is `OK`: the API is considered healthy, and all sub-services are also considered healthy. + +If __any__ sub-service is `DOWN`, then the entire health check will fail, and the API will be considered `DOWN`. + +## Defining Sub-Service health + +It is not enough to simply ping a sub-service to know if it is healthy, we want to go one step further. These criteria will change with each sub-service. + +### `datastore` + +For `datastore`, a status of `OK` means: +- An existing connection to the database +- The database is not empty (contains more than 1 table) + + +### `broker` + +For `broker`, a status of `OK` means: +- An existing connection to the kafka broker +- The necessary topics exist. This will change depending on which service the health check is running for. + +For example, for the `central-ledger` service to be considered healthy, the following topics need to be found: +``` +topic-admin-transfer +topic-transfer-prepare +topic-transfer-position +topic-transfer-fulfil +``` + +### `sidecar` + +For `sidecar`, a status of `OK` means: +- An existing connection to the sidecar + + +### `cache` + +For `cache`, a status of `OK` means: +- An existing connection to the cache + + +## Swagger Definition + +>_Note: These will be added to the existing swagger definitions for the following services:_ +> - `ml-api-adapter` +> - `central-ledger` +> - `central-settlement` +> - `central-event-processor` +> - `email-notifier` + +```json +{ + /// . . . + "/health": { + "get": { + "operationId": "getHealth", + "tags": [ + "health" + ], + "responses": { + "default": { + "schema": { + "$ref": "#/definitions/health" + }, + "description": "Successful" + } + } + } + }, + // . . . + "definitions": { + "health": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "OK", + "DOWN" + ] + }, + "uptime": { + "description": "How long (in seconds) the service has been alive for.", + "type": "number", + }, + "started": { + "description": "When the service was started (UTC)", + "type": "string", + "format": "date-time" + }, + "versionNumber": { + "description": "The current version of the service.", + "type": "string", + "example": "5.2.3", + }, + "services": { + "description": "A list of services this service depends on, and their connection status", + "type": "array", + "items": { + "$ref": "#/definitions/serviceHealth" + } + }, + }, + }, + "serviceHealth": { + "type": "object", + "properties": { + "name": { + "description": "The sub-service name.", + "type": "string", + "enum": [ + "datastore", + "broker", + "sidecar", + "cache" + ] + }, + "status": { + "description": "The connection status with the service.", + "type": "string", + "enum": [ + "OK", + "DOWN" + ] + } + } + } + } +} +``` + + +### Example Requests and Responses: + +__Successful Legacy Health Check:__ + +```bash +GET /health HTTP/1.1 +Content-Type: application/json + +200 SUCCESS +{ + "status": "OK" +} +``` + + +__Successful New Health Check:__ + +``` +GET /health?detailed=true HTTP/1.1 +Content-Type: application/json + +200 SUCCESS +{ + "status": "OK", + "uptime": 0, + "started": "2019-05-31T05:09:25.409Z", + "versionNumber": "5.2.3", + "services": [ + { + "name": "broker", + "status": "OK", + } + ] +} +``` + +__Failed Health Check, but API is up:__ + +``` +GET /health?detailed=true HTTP/1.1 +Content-Type: application/json + +502 BAD GATEWAY +{ + "status": "DOWN", + "uptime": 0, + "started": "2019-05-31T05:09:25.409Z", + "versionNumber": "5.2.3", + "services": [ + { + "name": "broker", + "status": "DOWN", + } + ] +} +``` + +__Failed Health Check:__ + +``` +GET /health?detailed=true HTTP/1.1 +Content-Type: application/json + +503 SERVICE UNAVAILABLE +``` + + +## Sequence Diagram + +Sequence design diagram for the GET Health + +![seq-get-health-1.0.0.svg](../assets/diagrams/sequence/seq-get-health-1.0.0.svg) diff --git a/docs/technical/central-ledger/admin-operations/1.0.0-get-limits-for-all-participants.md b/docs/technical/central-ledger/admin-operations/1.0.0-get-limits-for-all-participants.md new file mode 100644 index 000000000..7a1c5e933 --- /dev/null +++ b/docs/technical/central-ledger/admin-operations/1.0.0-get-limits-for-all-participants.md @@ -0,0 +1,7 @@ +# GET Participant Limit Details For All Participants + +Sequence design diagram for the GET Participant Limit Details For All Participants process. + +## Sequence Diagram + +![seq-get-all-participant-limit-1.0.0.svg](../assets/diagrams/sequence/seq-get-all-participant-limit-1.0.0.svg) diff --git a/docs/technical/central-ledger/admin-operations/1.0.0-post-participant-position-limit.md b/docs/technical/central-ledger/admin-operations/1.0.0-post-participant-position-limit.md new file mode 100644 index 000000000..6fda674e3 --- /dev/null +++ b/docs/technical/central-ledger/admin-operations/1.0.0-post-participant-position-limit.md @@ -0,0 +1,7 @@ +# Create initial position and limits for Participant + +Sequence design diagram for the POST (create) Participant Initial Position and Limit process. + +## Sequence Diagram + +![seq-participant-position-limits-1.0.0.svg](../assets/diagrams/sequence/seq-participant-position-limits-1.0.0.svg) diff --git a/docs/technical/central-ledger/admin-operations/1.1.0-get-participant-limit-details.md b/docs/technical/central-ledger/admin-operations/1.1.0-get-participant-limit-details.md new file mode 100644 index 000000000..2419df6fe --- /dev/null +++ b/docs/technical/central-ledger/admin-operations/1.1.0-get-participant-limit-details.md @@ -0,0 +1,7 @@ +# Request Participant Position and Limit Details + +Sequence design diagram for the Request Participant Position and Limit Details process. + +## Sequence Diagram + +![seq-get-participant-position-limit-1.1.0.svg](../assets/diagrams/sequence/seq-get-participant-position-limit-1.1.0.svg) diff --git a/docs/technical/central-ledger/admin-operations/1.1.0-post-participant-limits.md b/docs/technical/central-ledger/admin-operations/1.1.0-post-participant-limits.md new file mode 100644 index 000000000..99fb44d05 --- /dev/null +++ b/docs/technical/central-ledger/admin-operations/1.1.0-post-participant-limits.md @@ -0,0 +1,7 @@ +# Adjust Participant Limit for a certain Currency + +Sequence design diagram for the POST (manage) Participant Limit Details process. + +## Sequence Diagram + +![seq-manage-participant-limit-1.1.0.svg](../assets/diagrams/sequence/seq-manage-participant-limit-1.1.0.svg) diff --git a/docs/technical/central-ledger/admin-operations/1.1.5-get-transfer-status.md b/docs/technical/central-ledger/admin-operations/1.1.5-get-transfer-status.md new file mode 100644 index 000000000..b5c1f6734 --- /dev/null +++ b/docs/technical/central-ledger/admin-operations/1.1.5-get-transfer-status.md @@ -0,0 +1,7 @@ +# Request transfer status + +Sequence design diagram for the GET Transfer Status process. + +## Sequence Diagram + +![seq-get-transfer-1.1.5-phase2.svg](../assets/diagrams/sequence/seq-get-transfer-1.1.5-phase2.svg) diff --git a/docs/technical/central-ledger/admin-operations/3.1.0-get-participant-callback-details.md b/docs/technical/central-ledger/admin-operations/3.1.0-get-participant-callback-details.md new file mode 100644 index 000000000..72020a489 --- /dev/null +++ b/docs/technical/central-ledger/admin-operations/3.1.0-get-participant-callback-details.md @@ -0,0 +1,7 @@ +# 3.1.0 Get Participant Callback Details + +Sequence design diagram for the GET Participant Callback Details process. + +## Sequence Diagram + +![seq-callback-3.1.0.svg](../assets/diagrams/sequence/seq-callback-3.1.0.svg) diff --git a/docs/technical/central-ledger/admin-operations/3.1.0-post-participant-callback-details.md b/docs/technical/central-ledger/admin-operations/3.1.0-post-participant-callback-details.md new file mode 100644 index 000000000..2b9afae31 --- /dev/null +++ b/docs/technical/central-ledger/admin-operations/3.1.0-post-participant-callback-details.md @@ -0,0 +1,7 @@ +# 3.1.0 Add Participant Callback Details + +Sequence design diagram for the POST (Add) Participant Callback Details process. + +## Sequence Diagram + +![seq-callback-add-3.1.0.svg](../assets/diagrams/sequence/seq-callback-add-3.1.0.svg) diff --git a/docs/technical/central-ledger/admin-operations/4.1.0-get-participant-position-details.md b/docs/technical/central-ledger/admin-operations/4.1.0-get-participant-position-details.md new file mode 100644 index 000000000..1153ef409 --- /dev/null +++ b/docs/technical/central-ledger/admin-operations/4.1.0-get-participant-position-details.md @@ -0,0 +1,7 @@ +# Get Participant Position Details + +Sequence design diagram for the GET Participant Position Details process. + +## Sequence Diagram + +![seq-participants-positions-query-4.1.0.svg](../assets/diagrams/sequence/seq-participants-positions-query-4.1.0.svg) diff --git a/docs/technical/central-ledger/admin-operations/4.2.0-get-positions-of-all-participants.md b/docs/technical/central-ledger/admin-operations/4.2.0-get-positions-of-all-participants.md new file mode 100644 index 000000000..176494d61 --- /dev/null +++ b/docs/technical/central-ledger/admin-operations/4.2.0-get-positions-of-all-participants.md @@ -0,0 +1,7 @@ +# Get Position Details for all Participants + +Sequence design diagram for the Get Positions of all Participants process. + +## Sequence Diagram + +![seq-participants-positions-query-all-4.2.0.svg](../assets/diagrams/sequence/seq-participants-positions-query-all-4.2.0.svg) diff --git a/docs/technical/central-ledger/admin-operations/README.md b/docs/technical/central-ledger/admin-operations/README.md new file mode 100644 index 000000000..ebdb6ac1d --- /dev/null +++ b/docs/technical/central-ledger/admin-operations/README.md @@ -0,0 +1,3 @@ +# Mojaloop HUB/Switch operations + +Operational processes normally initiated by a HUB/Switch operator. diff --git a/docs/technical/central-ledger/assets/database/README.md b/docs/technical/central-ledger/assets/database/README.md new file mode 100644 index 000000000..77d71d79d --- /dev/null +++ b/docs/technical/central-ledger/assets/database/README.md @@ -0,0 +1,17 @@ +# How to EDIT the central-ledger-schema-DBeaver.erd file + +This is a basic guide on how to successfully view/update the central-ledger-schema-DBeaver.erd file. + +## Prerequisites +* Download and install the DBeaver Community DB Manager +* The Mojaloop Central-Ledger MySQL Database needs to be up and running, and connectable by the DBeaver +* You'll also need a text editor +## Steps to follow +* Create a new db connection in DBeaver under Database Navigator tab for the MySQL instance running. +* Under the Projects tab right click and create a New ER Diagram. +* Give the diagram a name and select central-ledger db in the wizard. + +* Copy the `central-ledger-schema-DBeaver.erd` file from the documentation module to `DBeaverData/workspace/General/Diagrams` in your DBeaver storage location +* Navigate to the newly created erd file using a text editor, search for `data-source id` and copy its value which looks like `mysql5-171ea991174-1218b6e1bf273693`. +* Navigate with a text editor to the `central-ledger-schema-DBeaver.erd` file in the ER Diagrams directory and replace its `data-source id` value with the one copied from the newly created erd file. +* The `central-ledger-schema-DBeaver.erd` should now show the tables as per the `central-ledger-schema.png` \ No newline at end of file diff --git a/docs/technical/central-ledger/assets/database/central-ledger-ddl-MySQLWorkbench.sql b/docs/technical/central-ledger/assets/database/central-ledger-ddl-MySQLWorkbench.sql new file mode 100644 index 000000000..280962173 --- /dev/null +++ b/docs/technical/central-ledger/assets/database/central-ledger-ddl-MySQLWorkbench.sql @@ -0,0 +1,1820 @@ +-- MySQL dump 10.13 Distrib 8.0.18, for macos10.14 (x86_64) +-- +-- Host: localhost Database: central_ledger +-- ------------------------------------------------------ +-- Server version 8.0.13 + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!50503 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Table structure for table `amountType` +-- + +DROP TABLE IF EXISTS `amountType`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `amountType` ( + `amountTypeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(256) NOT NULL, + `description` varchar(1024) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`amountTypeId`), + UNIQUE KEY `amounttype_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `balanceOfPayments` +-- + +DROP TABLE IF EXISTS `balanceOfPayments`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `balanceOfPayments` ( + `balanceOfPaymentsId` int(10) unsigned NOT NULL, + `name` varchar(256) NOT NULL, + `description` varchar(1024) DEFAULT NULL COMMENT 'Possible values and meaning are defined in https://www.imf.org/external/np/sta/bopcode/', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`balanceOfPaymentsId`), + UNIQUE KEY `balanceofpayments_name_unique` (`name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='See https://www.imf.org/external/np/sta/bopcode/guide.htm'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `bulkProcessingState` +-- + +DROP TABLE IF EXISTS `bulkProcessingState`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `bulkProcessingState` ( + `bulkProcessingStateId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`bulkProcessingStateId`), + UNIQUE KEY `bulkprocessingstate_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `bulkTransfer` +-- + +DROP TABLE IF EXISTS `bulkTransfer`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `bulkTransfer` ( + `bulkTransferId` varchar(36) NOT NULL, + `bulkQuoteId` varchar(36) DEFAULT NULL, + `payerParticipantId` int(10) unsigned DEFAULT NULL, + `payeeParticipantId` int(10) unsigned DEFAULT NULL, + `expirationDate` datetime NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`bulkTransferId`), + KEY `bulktransfer_payerparticipantid_index` (`payerParticipantId`), + KEY `bulktransfer_payeeparticipantid_index` (`payeeParticipantId`), + CONSTRAINT `bulktransfer_bulktransferid_foreign` FOREIGN KEY (`bulkTransferId`) REFERENCES `bulkTransferDuplicateCheck` (`bulktransferid`), + CONSTRAINT `bulktransfer_payeeparticipantid_foreign` FOREIGN KEY (`payeeParticipantId`) REFERENCES `participant` (`participantid`), + CONSTRAINT `bulktransfer_payerparticipantid_foreign` FOREIGN KEY (`payerParticipantId`) REFERENCES `participant` (`participantid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `bulkTransferAssociation` +-- + +DROP TABLE IF EXISTS `bulkTransferAssociation`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `bulkTransferAssociation` ( + `bulkTransferAssociationId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `transferId` varchar(36) NOT NULL, + `bulkTransferId` varchar(36) NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `bulkProcessingStateId` int(10) unsigned NOT NULL, + `lastProcessedDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `errorCode` int(10) unsigned DEFAULT NULL, + `errorDescription` varchar(128) DEFAULT NULL, + PRIMARY KEY (`bulkTransferAssociationId`), + UNIQUE KEY `bulktransferassociation_transferid_bulktransferid_unique` (`transferId`,`bulkTransferId`), + KEY `bulktransferassociation_bulktransferid_foreign` (`bulkTransferId`), + KEY `bulktransferassociation_bulkprocessingstateid_foreign` (`bulkProcessingStateId`), + CONSTRAINT `bulktransferassociation_bulkprocessingstateid_foreign` FOREIGN KEY (`bulkProcessingStateId`) REFERENCES `bulkProcessingState` (`bulkprocessingstateid`), + CONSTRAINT `bulktransferassociation_bulktransferid_foreign` FOREIGN KEY (`bulkTransferId`) REFERENCES `bulkTransfer` (`bulktransferid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `bulkTransferDuplicateCheck` +-- + +DROP TABLE IF EXISTS `bulkTransferDuplicateCheck`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `bulkTransferDuplicateCheck` ( + `bulkTransferId` varchar(36) NOT NULL, + `hash` varchar(256) NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`bulkTransferId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `bulkTransferError` +-- + +DROP TABLE IF EXISTS `bulkTransferError`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `bulkTransferError` ( + `bulkTransferErrorId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `bulkTransferStateChangeId` bigint(20) unsigned NOT NULL, + `errorCode` int(10) unsigned NOT NULL, + `errorDescription` varchar(128) NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`bulkTransferErrorId`), + KEY `bulktransfererror_bulktransferstatechangeid_index` (`bulkTransferStateChangeId`), + CONSTRAINT `bulktransfererror_bulktransferstatechangeid_foreign` FOREIGN KEY (`bulkTransferStateChangeId`) REFERENCES `bulkTransferStateChange` (`bulktransferstatechangeid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `bulkTransferExtension` +-- + +DROP TABLE IF EXISTS `bulkTransferExtension`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `bulkTransferExtension` ( + `bulkTransferExtensionId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `bulkTransferId` varchar(36) NOT NULL, + `isFulfilment` tinyint(1) NOT NULL DEFAULT '0', + `key` varchar(128) NOT NULL, + `value` text NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`bulkTransferExtensionId`), + KEY `bulktransferextension_bulktransferid_index` (`bulkTransferId`), + CONSTRAINT `bulktransferextension_bulktransferid_foreign` FOREIGN KEY (`bulkTransferId`) REFERENCES `bulkTransfer` (`bulktransferid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `bulkTransferFulfilment` +-- + +DROP TABLE IF EXISTS `bulkTransferFulfilment`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `bulkTransferFulfilment` ( + `bulkTransferId` varchar(36) NOT NULL, + `completedDate` datetime NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`bulkTransferId`), + CONSTRAINT `bulktransferfulfilment_bulktransferid_foreign` FOREIGN KEY (`bulkTransferId`) REFERENCES `bulkTransferFulfilmentDuplicateCheck` (`bulktransferid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `bulkTransferFulfilmentDuplicateCheck` +-- + +DROP TABLE IF EXISTS `bulkTransferFulfilmentDuplicateCheck`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `bulkTransferFulfilmentDuplicateCheck` ( + `bulkTransferId` varchar(36) NOT NULL, + `hash` varchar(256) NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`bulkTransferId`), + CONSTRAINT `bulktransferfulfilmentduplicatecheck_bulktransferid_foreign` FOREIGN KEY (`bulkTransferId`) REFERENCES `bulkTransfer` (`bulktransferid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `bulkTransferState` +-- + +DROP TABLE IF EXISTS `bulkTransferState`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `bulkTransferState` ( + `bulkTransferStateId` varchar(50) NOT NULL, + `enumeration` varchar(50) NOT NULL COMMENT 'bulkTransferState associated to the Mojaloop API', + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`bulkTransferStateId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `bulkTransferStateChange` +-- + +DROP TABLE IF EXISTS `bulkTransferStateChange`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `bulkTransferStateChange` ( + `bulkTransferStateChangeId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `bulkTransferId` varchar(36) NOT NULL, + `bulkTransferStateId` varchar(50) NOT NULL, + `reason` varchar(512) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`bulkTransferStateChangeId`), + KEY `bulktransferstatechange_bulktransferid_index` (`bulkTransferId`), + KEY `bulktransferstatechange_bulktransferstateid_index` (`bulkTransferStateId`), + CONSTRAINT `bulktransferstatechange_bulktransferid_foreign` FOREIGN KEY (`bulkTransferId`) REFERENCES `bulkTransfer` (`bulktransferid`), + CONSTRAINT `bulktransferstatechange_bulktransferstateid_foreign` FOREIGN KEY (`bulkTransferStateId`) REFERENCES `bulkTransferState` (`bulktransferstateid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `contactType` +-- + +DROP TABLE IF EXISTS `contactType`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `contactType` ( + `contactTypeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`contactTypeId`), + UNIQUE KEY `contacttype_name_unique` (`name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `currency` +-- + +DROP TABLE IF EXISTS `currency`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `currency` ( + `currencyId` varchar(3) NOT NULL, + `name` varchar(128) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `scale` int(10) unsigned NOT NULL DEFAULT '4', + PRIMARY KEY (`currencyId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `endpointType` +-- + +DROP TABLE IF EXISTS `endpointType`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `endpointType` ( + `endpointTypeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`endpointTypeId`), + UNIQUE KEY `endpointtype_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=29 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `event` +-- + +DROP TABLE IF EXISTS `event`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `event` ( + `eventId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(128) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`eventId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `expiringTransfer` +-- + +DROP TABLE IF EXISTS `expiringTransfer`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `expiringTransfer` ( + `expiringTransferId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `transferId` varchar(36) NOT NULL, + `expirationDate` datetime NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`expiringTransferId`), + UNIQUE KEY `expiringtransfer_transferid_unique` (`transferId`), + KEY `expiringtransfer_expirationdate_index` (`expirationDate`), + CONSTRAINT `expiringtransfer_transferid_foreign` FOREIGN KEY (`transferId`) REFERENCES `transfer` (`transferid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `geoCode` +-- + +DROP TABLE IF EXISTS `geoCode`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `geoCode` ( + `geoCodeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `quotePartyId` bigint(20) unsigned NOT NULL COMMENT 'Optionally the GeoCode for the Payer/Payee may have been provided. If the Quote Response has the GeoCode for the Payee, an additional row is added', + `latitude` varchar(50) NOT NULL COMMENT 'Latitude of the initiating Party', + `longitude` varchar(50) NOT NULL COMMENT 'Longitude of the initiating Party', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`geoCodeId`), + KEY `geocode_quotepartyid_foreign` (`quotePartyId`), + CONSTRAINT `geocode_quotepartyid_foreign` FOREIGN KEY (`quotePartyId`) REFERENCES `quoteParty` (`quotepartyid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ilpPacket` +-- + +DROP TABLE IF EXISTS `ilpPacket`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `ilpPacket` ( + `transferId` varchar(36) NOT NULL, + `value` text NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferId`), + CONSTRAINT `ilppacket_transferid_foreign` FOREIGN KEY (`transferId`) REFERENCES `transfer` (`transferid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ledgerAccountType` +-- + +DROP TABLE IF EXISTS `ledgerAccountType`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `ledgerAccountType` ( + `ledgerAccountTypeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `isSettleable` tinyint(1) NOT NULL DEFAULT '0', + PRIMARY KEY (`ledgerAccountTypeId`), + UNIQUE KEY `ledgeraccounttype_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `ledgerEntryType` +-- + +DROP TABLE IF EXISTS `ledgerEntryType`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `ledgerEntryType` ( + `ledgerEntryTypeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `ledgerAccountTypeId` int(10) unsigned DEFAULT NULL, + PRIMARY KEY (`ledgerEntryTypeId`), + UNIQUE KEY `ledgerentrytype_name_unique` (`name`), + KEY `ledgerentrytype_ledgeraccounttypeid_foreign` (`ledgerAccountTypeId`), + CONSTRAINT `ledgerentrytype_ledgeraccounttypeid_foreign` FOREIGN KEY (`ledgerAccountTypeId`) REFERENCES `ledgerAccountType` (`ledgeraccounttypeid`) +) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `migration` +-- + +DROP TABLE IF EXISTS `migration`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `migration` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(255) DEFAULT NULL, + `batch` int(11) DEFAULT NULL, + `migration_time` timestamp NULL DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=157 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `migration_lock` +-- + +DROP TABLE IF EXISTS `migration_lock`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `migration_lock` ( + `index` int(10) unsigned NOT NULL AUTO_INCREMENT, + `is_locked` int(11) DEFAULT NULL, + PRIMARY KEY (`index`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `participant` +-- + +DROP TABLE IF EXISTS `participant`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `participant` ( + `participantId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(256) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `createdBy` varchar(128) NOT NULL, + PRIMARY KEY (`participantId`), + UNIQUE KEY `participant_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `participantContact` +-- + +DROP TABLE IF EXISTS `participantContact`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `participantContact` ( + `participantContactId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `participantId` int(10) unsigned NOT NULL, + `contactTypeId` int(10) unsigned NOT NULL, + `value` varchar(256) NOT NULL, + `priorityPreference` int(11) NOT NULL DEFAULT '9', + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `createdBy` varchar(128) NOT NULL, + PRIMARY KEY (`participantContactId`), + KEY `participantcontact_participantid_index` (`participantId`), + KEY `participantcontact_contacttypeid_index` (`contactTypeId`), + CONSTRAINT `participantcontact_contacttypeid_foreign` FOREIGN KEY (`contactTypeId`) REFERENCES `contactType` (`contacttypeid`), + CONSTRAINT `participantcontact_participantid_foreign` FOREIGN KEY (`participantId`) REFERENCES `participant` (`participantid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `participantCurrency` +-- + +DROP TABLE IF EXISTS `participantCurrency`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `participantCurrency` ( + `participantCurrencyId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `participantId` int(10) unsigned NOT NULL, + `currencyId` varchar(3) NOT NULL, + `ledgerAccountTypeId` int(10) unsigned NOT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `createdBy` varchar(128) NOT NULL, + PRIMARY KEY (`participantCurrencyId`), + UNIQUE KEY `participantcurrency_pcl_unique` (`participantId`,`currencyId`,`ledgerAccountTypeId`), + KEY `participantcurrency_ledgeraccounttypeid_foreign` (`ledgerAccountTypeId`), + KEY `participantcurrency_participantid_index` (`participantId`), + KEY `participantcurrency_currencyid_index` (`currencyId`), + CONSTRAINT `participantcurrency_currencyid_foreign` FOREIGN KEY (`currencyId`) REFERENCES `currency` (`currencyid`), + CONSTRAINT `participantcurrency_ledgeraccounttypeid_foreign` FOREIGN KEY (`ledgerAccountTypeId`) REFERENCES `ledgerAccountType` (`ledgeraccounttypeid`), + CONSTRAINT `participantcurrency_participantid_foreign` FOREIGN KEY (`participantId`) REFERENCES `participant` (`participantid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `participantEndpoint` +-- + +DROP TABLE IF EXISTS `participantEndpoint`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `participantEndpoint` ( + `participantEndpointId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `participantId` int(10) unsigned NOT NULL, + `endpointTypeId` int(10) unsigned NOT NULL, + `value` varchar(512) NOT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `createdBy` varchar(128) NOT NULL, + PRIMARY KEY (`participantEndpointId`), + KEY `participantendpoint_participantid_index` (`participantId`), + KEY `participantendpoint_endpointtypeid_index` (`endpointTypeId`), + CONSTRAINT `participantendpoint_endpointtypeid_foreign` FOREIGN KEY (`endpointTypeId`) REFERENCES `endpointType` (`endpointtypeid`), + CONSTRAINT `participantendpoint_participantid_foreign` FOREIGN KEY (`participantId`) REFERENCES `participant` (`participantid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `participantLimit` +-- + +DROP TABLE IF EXISTS `participantLimit`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `participantLimit` ( + `participantLimitId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `participantCurrencyId` int(10) unsigned NOT NULL, + `participantLimitTypeId` int(10) unsigned NOT NULL, + `value` decimal(18,4) NOT NULL DEFAULT '0.0000', + `thresholdAlarmPercentage` decimal(5,2) NOT NULL DEFAULT '10.00', + `startAfterParticipantPositionChangeId` bigint(20) unsigned DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `createdBy` varchar(128) NOT NULL, + PRIMARY KEY (`participantLimitId`), + KEY `participantlimit_participantcurrencyid_index` (`participantCurrencyId`), + KEY `participantlimit_participantlimittypeid_index` (`participantLimitTypeId`), + KEY `participantlimit_startafterparticipantpositionchangeid_index` (`startAfterParticipantPositionChangeId`), + CONSTRAINT `participantlimit_participantcurrencyid_foreign` FOREIGN KEY (`participantCurrencyId`) REFERENCES `participantCurrency` (`participantcurrencyid`), + CONSTRAINT `participantlimit_participantlimittypeid_foreign` FOREIGN KEY (`participantLimitTypeId`) REFERENCES `participantLimitType` (`participantlimittypeid`), + CONSTRAINT `participantlimit_startafterparticipantpositionchangeid_foreign` FOREIGN KEY (`startAfterParticipantPositionChangeId`) REFERENCES `participantPositionChange` (`participantpositionchangeid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `participantLimitType` +-- + +DROP TABLE IF EXISTS `participantLimitType`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `participantLimitType` ( + `participantLimitTypeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`participantLimitTypeId`), + UNIQUE KEY `participantlimittype_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `participantParty` +-- + +DROP TABLE IF EXISTS `participantParty`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `participantParty` ( + `participantPartyId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `participantId` int(10) unsigned NOT NULL, + `partyId` bigint(20) unsigned NOT NULL, + PRIMARY KEY (`participantPartyId`), + UNIQUE KEY `participantparty_participantid_partyid_unique` (`participantId`,`partyId`), + KEY `participantparty_participantid_index` (`participantId`), + CONSTRAINT `participantparty_participantid_foreign` FOREIGN KEY (`participantId`) REFERENCES `participant` (`participantid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `participantPosition` +-- + +DROP TABLE IF EXISTS `participantPosition`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `participantPosition` ( + `participantPositionId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `participantCurrencyId` int(10) unsigned NOT NULL, + `value` decimal(18,4) NOT NULL, + `reservedValue` decimal(18,4) NOT NULL, + `changedDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`participantPositionId`), + KEY `participantposition_participantcurrencyid_index` (`participantCurrencyId`), + CONSTRAINT `participantposition_participantcurrencyid_foreign` FOREIGN KEY (`participantCurrencyId`) REFERENCES `participantCurrency` (`participantcurrencyid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `participantPositionChange` +-- + +DROP TABLE IF EXISTS `participantPositionChange`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `participantPositionChange` ( + `participantPositionChangeId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `participantPositionId` bigint(20) unsigned NOT NULL, + `transferStateChangeId` bigint(20) unsigned NOT NULL, + `value` decimal(18,4) NOT NULL, + `reservedValue` decimal(18,4) NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`participantPositionChangeId`), + KEY `participantpositionchange_participantpositionid_index` (`participantPositionId`), + KEY `participantpositionchange_transferstatechangeid_index` (`transferStateChangeId`), + CONSTRAINT `participantpositionchange_participantpositionid_foreign` FOREIGN KEY (`participantPositionId`) REFERENCES `participantPosition` (`participantpositionid`), + CONSTRAINT `participantpositionchange_transferstatechangeid_foreign` FOREIGN KEY (`transferStateChangeId`) REFERENCES `transferStateChange` (`transferstatechangeid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `party` +-- + +DROP TABLE IF EXISTS `party`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `party` ( + `partyId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `quotePartyId` bigint(20) unsigned NOT NULL, + `firstName` varchar(128) DEFAULT NULL, + `middleName` varchar(128) DEFAULT NULL, + `lastName` varchar(128) DEFAULT NULL, + `dateOfBirth` datetime DEFAULT NULL, + PRIMARY KEY (`partyId`), + KEY `party_quotepartyid_foreign` (`quotePartyId`), + CONSTRAINT `party_quotepartyid_foreign` FOREIGN KEY (`quotePartyId`) REFERENCES `quoteParty` (`quotepartyid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Optional pers. data provided during Quote Request & Response'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `partyIdentifierType` +-- + +DROP TABLE IF EXISTS `partyIdentifierType`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `partyIdentifierType` ( + `partyIdentifierTypeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + `description` varchar(512) NOT NULL, + PRIMARY KEY (`partyIdentifierTypeId`), + UNIQUE KEY `partyidentifiertype_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `partyType` +-- + +DROP TABLE IF EXISTS `partyType`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `partyType` ( + `partyTypeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(128) NOT NULL, + `description` varchar(256) NOT NULL, + PRIMARY KEY (`partyTypeId`), + UNIQUE KEY `partytype_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `quote` +-- + +DROP TABLE IF EXISTS `quote`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `quote` ( + `quoteId` varchar(36) NOT NULL, + `transactionReferenceId` varchar(36) NOT NULL COMMENT 'Common ID (decided by the Payer FSP) between the FSPs for the future transaction object', + `transactionRequestId` varchar(36) DEFAULT NULL COMMENT 'Optional previously-sent transaction request', + `note` text COMMENT 'A memo that will be attached to the transaction', + `expirationDate` datetime DEFAULT NULL COMMENT 'Optional expiration for the requested transaction', + `transactionInitiatorId` int(10) unsigned NOT NULL COMMENT 'This is part of the transaction initiator', + `transactionInitiatorTypeId` int(10) unsigned NOT NULL COMMENT 'This is part of the transaction initiator type', + `transactionScenarioId` int(10) unsigned NOT NULL COMMENT 'This is part of the transaction scenario', + `balanceOfPaymentsId` int(10) unsigned DEFAULT NULL COMMENT 'This is part of the transaction type that contains the elements- balance of payment', + `transactionSubScenarioId` int(10) unsigned DEFAULT NULL COMMENT 'This is part of the transaction type sub scenario as defined by the local scheme', + `amountTypeId` int(10) unsigned NOT NULL COMMENT 'This is part of the transaction type that contains valid elements for - Amount Type', + `amount` decimal(18,4) NOT NULL DEFAULT '0.0000' COMMENT 'The amount that the quote is being requested for. Need to be interpert in accordance with the amount type', + `currencyId` varchar(255) DEFAULT NULL COMMENT 'Trading currency pertaining to the Amount', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`quoteId`), + KEY `quote_transactionreferenceid_foreign` (`transactionReferenceId`), + KEY `quote_transactionrequestid_foreign` (`transactionRequestId`), + KEY `quote_transactioninitiatorid_foreign` (`transactionInitiatorId`), + KEY `quote_transactioninitiatortypeid_foreign` (`transactionInitiatorTypeId`), + KEY `quote_transactionscenarioid_foreign` (`transactionScenarioId`), + KEY `quote_balanceofpaymentsid_foreign` (`balanceOfPaymentsId`), + KEY `quote_transactionsubscenarioid_foreign` (`transactionSubScenarioId`), + KEY `quote_amounttypeid_foreign` (`amountTypeId`), + KEY `quote_currencyid_foreign` (`currencyId`), + CONSTRAINT `quote_amounttypeid_foreign` FOREIGN KEY (`amountTypeId`) REFERENCES `amountType` (`amounttypeid`), + CONSTRAINT `quote_balanceofpaymentsid_foreign` FOREIGN KEY (`balanceOfPaymentsId`) REFERENCES `balanceOfPayments` (`balanceofpaymentsid`), + CONSTRAINT `quote_currencyid_foreign` FOREIGN KEY (`currencyId`) REFERENCES `currency` (`currencyid`), + CONSTRAINT `quote_transactioninitiatorid_foreign` FOREIGN KEY (`transactionInitiatorId`) REFERENCES `transactionInitiator` (`transactioninitiatorid`), + CONSTRAINT `quote_transactioninitiatortypeid_foreign` FOREIGN KEY (`transactionInitiatorTypeId`) REFERENCES `transactionInitiatorType` (`transactioninitiatortypeid`), + CONSTRAINT `quote_transactionreferenceid_foreign` FOREIGN KEY (`transactionReferenceId`) REFERENCES `transactionReference` (`transactionreferenceid`), + CONSTRAINT `quote_transactionrequestid_foreign` FOREIGN KEY (`transactionRequestId`) REFERENCES `transactionReference` (`transactionreferenceid`), + CONSTRAINT `quote_transactionscenarioid_foreign` FOREIGN KEY (`transactionScenarioId`) REFERENCES `transactionScenario` (`transactionscenarioid`), + CONSTRAINT `quote_transactionsubscenarioid_foreign` FOREIGN KEY (`transactionSubScenarioId`) REFERENCES `transactionSubScenario` (`transactionsubscenarioid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `quoteDuplicateCheck` +-- + +DROP TABLE IF EXISTS `quoteDuplicateCheck`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `quoteDuplicateCheck` ( + `quoteId` varchar(36) NOT NULL COMMENT 'Common ID between the FSPs for the quote object, decided by the Payer FSP', + `hash` varchar(1024) DEFAULT NULL COMMENT 'hash value received for the quote request', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`quoteId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `quoteError` +-- + +DROP TABLE IF EXISTS `quoteError`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `quoteError` ( + `quoteErrorId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `quoteId` varchar(36) NOT NULL COMMENT 'Common ID between the FSPs for the quote object, decided by the Payer FSP', + `quoteResponseId` bigint(20) unsigned DEFAULT NULL COMMENT 'The response to the intial quote', + `errorCode` int(10) unsigned NOT NULL, + `errorDescription` varchar(128) NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`quoteErrorId`), + KEY `quoteerror_quoteid_foreign` (`quoteId`), + KEY `quoteerror_quoteresponseid_foreign` (`quoteResponseId`), + CONSTRAINT `quoteerror_quoteid_foreign` FOREIGN KEY (`quoteId`) REFERENCES `quote` (`quoteid`), + CONSTRAINT `quoteerror_quoteresponseid_foreign` FOREIGN KEY (`quoteResponseId`) REFERENCES `quoteResponse` (`quoteresponseid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `quoteExtension` +-- + +DROP TABLE IF EXISTS `quoteExtension`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `quoteExtension` ( + `quoteExtensionId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `quoteId` varchar(36) NOT NULL COMMENT 'Common ID between the FSPs for the quote object, decided by the Payer FSP', + `quoteResponseId` bigint(20) unsigned NOT NULL COMMENT 'The response to the intial quote', + `transactionId` varchar(36) NOT NULL COMMENT 'The transaction reference that is part of the initial quote', + `key` varchar(128) NOT NULL, + `value` text NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`quoteExtensionId`), + KEY `quoteextension_quoteid_foreign` (`quoteId`), + KEY `quoteextension_quoteresponseid_foreign` (`quoteResponseId`), + KEY `quoteextension_transactionid_foreign` (`transactionId`), + CONSTRAINT `quoteextension_quoteid_foreign` FOREIGN KEY (`quoteId`) REFERENCES `quote` (`quoteid`), + CONSTRAINT `quoteextension_quoteresponseid_foreign` FOREIGN KEY (`quoteResponseId`) REFERENCES `quoteResponse` (`quoteresponseid`), + CONSTRAINT `quoteextension_transactionid_foreign` FOREIGN KEY (`transactionId`) REFERENCES `transactionReference` (`transactionreferenceid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `quoteParty` +-- + +DROP TABLE IF EXISTS `quoteParty`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `quoteParty` ( + `quotePartyId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `quoteId` varchar(36) NOT NULL COMMENT 'Common ID between the FSPs for the quote object, decided by the Payer FSP', + `partyTypeId` int(10) unsigned NOT NULL COMMENT 'Specifies the type of party this row relates to; typically PAYER or PAYEE', + `partyIdentifierTypeId` int(10) unsigned NOT NULL COMMENT 'Specifies the type of identifier used to identify this party e.g. MSISDN, IBAN etc...', + `partyIdentifierValue` varchar(128) NOT NULL COMMENT 'The value of the identifier used to identify this party', + `partySubIdOrTypeId` int(10) unsigned DEFAULT NULL COMMENT 'A sub-identifier or sub-type for the Party', + `fspId` varchar(255) DEFAULT NULL COMMENT 'This is the FSP ID as provided in the quote. For the switch between multi-parties it is required', + `participantId` int(10) unsigned DEFAULT NULL COMMENT 'Reference to the resolved FSP ID (if supplied/known). If not an error will be reported', + `merchantClassificationCode` varchar(4) DEFAULT NULL COMMENT 'Used in the context of Payee Information, where the Payee happens to be a merchant accepting merchant payments', + `partyName` varchar(128) DEFAULT NULL COMMENT 'Display name of the Party, could be a real name or a nick name', + `transferParticipantRoleTypeId` int(10) unsigned NOT NULL COMMENT 'The role this Party is playing in the transaction', + `ledgerEntryTypeId` int(10) unsigned NOT NULL COMMENT 'The type of financial entry this Party is presenting', + `amount` decimal(18,4) NOT NULL, + `currencyId` varchar(3) NOT NULL COMMENT 'Trading currency pertaining to the party amount', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`quotePartyId`), + KEY `quoteparty_quoteid_foreign` (`quoteId`), + KEY `quoteparty_partytypeid_foreign` (`partyTypeId`), + KEY `quoteparty_partyidentifiertypeid_foreign` (`partyIdentifierTypeId`), + KEY `quoteparty_partysubidortypeid_foreign` (`partySubIdOrTypeId`), + KEY `quoteparty_participantid_foreign` (`participantId`), + KEY `quoteparty_transferparticipantroletypeid_foreign` (`transferParticipantRoleTypeId`), + KEY `quoteparty_ledgerentrytypeid_foreign` (`ledgerEntryTypeId`), + KEY `quoteparty_currencyid_foreign` (`currencyId`), + CONSTRAINT `quoteparty_currencyid_foreign` FOREIGN KEY (`currencyId`) REFERENCES `currency` (`currencyid`), + CONSTRAINT `quoteparty_ledgerentrytypeid_foreign` FOREIGN KEY (`ledgerEntryTypeId`) REFERENCES `ledgerEntryType` (`ledgerentrytypeid`), + CONSTRAINT `quoteparty_participantid_foreign` FOREIGN KEY (`participantId`) REFERENCES `participant` (`participantid`), + CONSTRAINT `quoteparty_partyidentifiertypeid_foreign` FOREIGN KEY (`partyIdentifierTypeId`) REFERENCES `partyIdentifierType` (`partyidentifiertypeid`), + CONSTRAINT `quoteparty_partysubidortypeid_foreign` FOREIGN KEY (`partySubIdOrTypeId`) REFERENCES `partyIdentifierType` (`partyidentifiertypeid`), + CONSTRAINT `quoteparty_partytypeid_foreign` FOREIGN KEY (`partyTypeId`) REFERENCES `partyType` (`partytypeid`), + CONSTRAINT `quoteparty_quoteid_foreign` FOREIGN KEY (`quoteId`) REFERENCES `quote` (`quoteid`), + CONSTRAINT `quoteparty_transferparticipantroletypeid_foreign` FOREIGN KEY (`transferParticipantRoleTypeId`) REFERENCES `transferParticipantRoleType` (`transferparticipantroletypeid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Temporary view structure for view `quotePartyView` +-- + +DROP TABLE IF EXISTS `quotePartyView`; +/*!50001 DROP VIEW IF EXISTS `quotePartyView`*/; +SET @saved_cs_client = @@character_set_client; +/*!50503 SET character_set_client = utf8mb4 */; +/*!50001 CREATE VIEW `quotePartyView` AS SELECT + 1 AS `quoteId`, + 1 AS `quotePartyId`, + 1 AS `partyType`, + 1 AS `identifierType`, + 1 AS `partyIdentifierValue`, + 1 AS `partySubIdOrType`, + 1 AS `fspId`, + 1 AS `merchantClassificationCode`, + 1 AS `partyName`, + 1 AS `firstName`, + 1 AS `lastName`, + 1 AS `middleName`, + 1 AS `dateOfBirth`, + 1 AS `longitude`, + 1 AS `latitude`*/; +SET character_set_client = @saved_cs_client; + +-- +-- Table structure for table `quoteResponse` +-- + +DROP TABLE IF EXISTS `quoteResponse`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `quoteResponse` ( + `quoteResponseId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `quoteId` varchar(36) NOT NULL COMMENT 'Common ID between the FSPs for the quote object, decided by the Payer FSP', + `transferAmountCurrencyId` varchar(3) NOT NULL COMMENT 'CurrencyId of the transfer amount', + `transferAmount` decimal(18,4) NOT NULL COMMENT 'The amount of money that the Payer FSP should transfer to the Payee FSP', + `payeeReceiveAmountCurrencyId` varchar(3) DEFAULT NULL COMMENT 'CurrencyId of the payee receive amount', + `payeeReceiveAmount` decimal(18,4) DEFAULT NULL COMMENT 'The amount of Money that the Payee should receive in the end-to-end transaction. Optional as the Payee FSP might not want to disclose any optional Payee fees', + `payeeFspFeeCurrencyId` varchar(3) DEFAULT NULL COMMENT 'CurrencyId of the payee fsp fee amount', + `payeeFspFeeAmount` decimal(18,4) DEFAULT NULL COMMENT 'Payee FSP’s part of the transaction fee', + `payeeFspCommissionCurrencyId` varchar(3) DEFAULT NULL COMMENT 'CurrencyId of the payee fsp commission amount', + `payeeFspCommissionAmount` decimal(18,4) DEFAULT NULL COMMENT 'Transaction commission from the Payee FSP', + `ilpCondition` varchar(256) NOT NULL, + `responseExpirationDate` datetime DEFAULT NULL COMMENT 'Optional expiration for the requested transaction', + `isValid` tinyint(1) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`quoteResponseId`), + KEY `quoteresponse_quoteid_foreign` (`quoteId`), + KEY `quoteresponse_transferamountcurrencyid_foreign` (`transferAmountCurrencyId`), + KEY `quoteresponse_payeereceiveamountcurrencyid_foreign` (`payeeReceiveAmountCurrencyId`), + KEY `quoteresponse_payeefspcommissioncurrencyid_foreign` (`payeeFspCommissionCurrencyId`), + CONSTRAINT `quoteresponse_payeefspcommissioncurrencyid_foreign` FOREIGN KEY (`payeeFspCommissionCurrencyId`) REFERENCES `currency` (`currencyid`), + CONSTRAINT `quoteresponse_payeereceiveamountcurrencyid_foreign` FOREIGN KEY (`payeeReceiveAmountCurrencyId`) REFERENCES `currency` (`currencyid`), + CONSTRAINT `quoteresponse_quoteid_foreign` FOREIGN KEY (`quoteId`) REFERENCES `quote` (`quoteid`), + CONSTRAINT `quoteresponse_transferamountcurrencyid_foreign` FOREIGN KEY (`transferAmountCurrencyId`) REFERENCES `currency` (`currencyid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='This table is the primary store for quote responses'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `quoteResponseDuplicateCheck` +-- + +DROP TABLE IF EXISTS `quoteResponseDuplicateCheck`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `quoteResponseDuplicateCheck` ( + `quoteResponseId` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'The response to the intial quote', + `quoteId` varchar(36) NOT NULL COMMENT 'Common ID between the FSPs for the quote object, decided by the Payer FSP', + `hash` varchar(255) DEFAULT NULL COMMENT 'hash value received for the quote response', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`quoteResponseId`), + KEY `quoteresponseduplicatecheck_quoteid_foreign` (`quoteId`), + CONSTRAINT `quoteresponseduplicatecheck_quoteid_foreign` FOREIGN KEY (`quoteId`) REFERENCES `quote` (`quoteid`), + CONSTRAINT `quoteresponseduplicatecheck_quoteresponseid_foreign` FOREIGN KEY (`quoteResponseId`) REFERENCES `quoteResponse` (`quoteresponseid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `quoteResponseIlpPacket` +-- + +DROP TABLE IF EXISTS `quoteResponseIlpPacket`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `quoteResponseIlpPacket` ( + `quoteResponseId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `value` text NOT NULL COMMENT 'ilpPacket returned from Payee in response to a quote request', + PRIMARY KEY (`quoteResponseId`), + CONSTRAINT `quoteresponseilppacket_quoteresponseid_foreign` FOREIGN KEY (`quoteResponseId`) REFERENCES `quoteResponse` (`quoteresponseid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Temporary view structure for view `quoteResponseView` +-- + +DROP TABLE IF EXISTS `quoteResponseView`; +/*!50001 DROP VIEW IF EXISTS `quoteResponseView`*/; +SET @saved_cs_client = @@character_set_client; +/*!50503 SET character_set_client = utf8mb4 */; +/*!50001 CREATE VIEW `quoteResponseView` AS SELECT + 1 AS `quoteResponseId`, + 1 AS `quoteId`, + 1 AS `transferAmountCurrencyId`, + 1 AS `transferAmount`, + 1 AS `payeeReceiveAmountCurrencyId`, + 1 AS `payeeReceiveAmount`, + 1 AS `payeeFspFeeCurrencyId`, + 1 AS `payeeFspFeeAmount`, + 1 AS `payeeFspCommissionCurrencyId`, + 1 AS `payeeFspCommissionAmount`, + 1 AS `ilpCondition`, + 1 AS `responseExpirationDate`, + 1 AS `isValid`, + 1 AS `createdDate`, + 1 AS `ilpPacket`, + 1 AS `longitude`, + 1 AS `latitude`*/; +SET character_set_client = @saved_cs_client; + +-- +-- Temporary view structure for view `quoteView` +-- + +DROP TABLE IF EXISTS `quoteView`; +/*!50001 DROP VIEW IF EXISTS `quoteView`*/; +SET @saved_cs_client = @@character_set_client; +/*!50503 SET character_set_client = utf8mb4 */; +/*!50001 CREATE VIEW `quoteView` AS SELECT + 1 AS `quoteId`, + 1 AS `transactionReferenceId`, + 1 AS `transactionRequestId`, + 1 AS `note`, + 1 AS `expirationDate`, + 1 AS `transactionInitiator`, + 1 AS `transactionInitiatorType`, + 1 AS `transactionScenario`, + 1 AS `balanceOfPaymentsId`, + 1 AS `transactionSubScenario`, + 1 AS `amountType`, + 1 AS `amount`, + 1 AS `currency`*/; +SET character_set_client = @saved_cs_client; + +-- +-- Table structure for table `segment` +-- + +DROP TABLE IF EXISTS `segment`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `segment` ( + `segmentId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `segmentType` varchar(50) NOT NULL, + `enumeration` int(11) NOT NULL DEFAULT '0', + `tableName` varchar(50) NOT NULL, + `value` bigint(20) NOT NULL, + `changedDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`segmentId`), + KEY `segment_keys_index` (`segmentType`,`enumeration`,`tableName`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlement` +-- + +DROP TABLE IF EXISTS `settlement`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `settlement` ( + `settlementId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `reason` varchar(512) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `currentStateChangeId` bigint(20) unsigned DEFAULT NULL, + `settlementModelId` int(10) unsigned DEFAULT NULL, + PRIMARY KEY (`settlementId`), + KEY `settlement_currentstatechangeid_foreign` (`currentStateChangeId`), + KEY `settlement_settlementmodelid_foreign` (`settlementModelId`), + CONSTRAINT `settlement_currentstatechangeid_foreign` FOREIGN KEY (`currentStateChangeId`) REFERENCES `settlementStateChange` (`settlementstatechangeid`), + CONSTRAINT `settlement_settlementmodelid_foreign` FOREIGN KEY (`settlementModelId`) REFERENCES `settlementModel` (`settlementmodelid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementContentAggregation` +-- + +DROP TABLE IF EXISTS `settlementContentAggregation`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `settlementContentAggregation` ( + `settlementContentAggregationId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `settlementWindowContentId` bigint(20) unsigned NOT NULL, + `participantCurrencyId` int(10) unsigned NOT NULL, + `transferParticipantRoleTypeId` int(10) unsigned NOT NULL, + `ledgerEntryTypeId` int(10) unsigned NOT NULL, + `amount` decimal(18,2) NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `currentStateId` varchar(50) NOT NULL, + `settlementId` bigint(20) unsigned DEFAULT NULL, + PRIMARY KEY (`settlementContentAggregationId`), + KEY `settlementcontentaggregation_settlementwindowcontentid_index` (`settlementWindowContentId`), + KEY `settlementcontentaggregation_participantcurrencyid_index` (`participantCurrencyId`), + KEY `settlementcontentaggregation_transferparticipantroletypeid_index` (`transferParticipantRoleTypeId`), + KEY `settlementcontentaggregation_ledgerentrytypeid_index` (`ledgerEntryTypeId`), + KEY `settlementcontentaggregation_currentstateid_index` (`currentStateId`), + KEY `settlementcontentaggregation_settlementid_index` (`settlementId`), + CONSTRAINT `sca_transferparticipantroletypeid_foreign` FOREIGN KEY (`transferParticipantRoleTypeId`) REFERENCES `transferParticipantRoleType` (`transferparticipantroletypeid`), + CONSTRAINT `settlementcontentaggregation_currentstateid_foreign` FOREIGN KEY (`currentStateId`) REFERENCES `settlementWindowState` (`settlementwindowstateid`), + CONSTRAINT `settlementcontentaggregation_ledgerentrytypeid_foreign` FOREIGN KEY (`ledgerEntryTypeId`) REFERENCES `ledgerEntryType` (`ledgerentrytypeid`), + CONSTRAINT `settlementcontentaggregation_participantcurrencyid_foreign` FOREIGN KEY (`participantCurrencyId`) REFERENCES `participantCurrency` (`participantcurrencyid`), + CONSTRAINT `settlementcontentaggregation_settlementid_foreign` FOREIGN KEY (`settlementId`) REFERENCES `settlement` (`settlementid`), + CONSTRAINT `settlementcontentaggregation_settlementwindowcontentid_foreign` FOREIGN KEY (`settlementWindowContentId`) REFERENCES `settlementWindowContent` (`settlementwindowcontentid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementDelay` +-- + +DROP TABLE IF EXISTS `settlementDelay`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `settlementDelay` ( + `settlementDelayId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`settlementDelayId`), + UNIQUE KEY `settlementdelay_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementGranularity` +-- + +DROP TABLE IF EXISTS `settlementGranularity`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `settlementGranularity` ( + `settlementGranularityId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`settlementGranularityId`), + UNIQUE KEY `settlementgranularity_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementInterchange` +-- + +DROP TABLE IF EXISTS `settlementInterchange`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `settlementInterchange` ( + `settlementInterchangeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`settlementInterchangeId`), + UNIQUE KEY `settlementinterchange_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementModel` +-- + +DROP TABLE IF EXISTS `settlementModel`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `settlementModel` ( + `settlementModelId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `settlementGranularityId` int(10) unsigned NOT NULL, + `settlementInterchangeId` int(10) unsigned NOT NULL, + `settlementDelayId` int(10) unsigned NOT NULL, + `currencyId` varchar(3) DEFAULT NULL, + `requireLiquidityCheck` tinyint(1) NOT NULL DEFAULT '1', + `ledgerAccountTypeId` int(10) unsigned NOT NULL, + `autoPositionReset` tinyint(1) NOT NULL DEFAULT '0', + PRIMARY KEY (`settlementModelId`), + UNIQUE KEY `settlementmodel_name_unique` (`name`), + KEY `settlementmodel_settlementgranularityid_index` (`settlementGranularityId`), + KEY `settlementmodel_settlementinterchangeid_index` (`settlementInterchangeId`), + KEY `settlementmodel_settlementdelayid_index` (`settlementDelayId`), + KEY `settlementmodel_currencyid_index` (`currencyId`), + KEY `settlementmodel_ledgeraccounttypeid_index` (`ledgerAccountTypeId`), + CONSTRAINT `settlementmodel_currencyid_foreign` FOREIGN KEY (`currencyId`) REFERENCES `currency` (`currencyid`), + CONSTRAINT `settlementmodel_ledgeraccounttypeid_foreign` FOREIGN KEY (`ledgerAccountTypeId`) REFERENCES `ledgerAccountType` (`ledgeraccounttypeid`), + CONSTRAINT `settlementmodel_settlementdelayid_foreign` FOREIGN KEY (`settlementDelayId`) REFERENCES `settlementDelay` (`settlementdelayid`), + CONSTRAINT `settlementmodel_settlementgranularityid_foreign` FOREIGN KEY (`settlementGranularityId`) REFERENCES `settlementGranularity` (`settlementgranularityid`), + CONSTRAINT `settlementmodel_settlementinterchangeid_foreign` FOREIGN KEY (`settlementInterchangeId`) REFERENCES `settlementInterchange` (`settlementinterchangeid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementParticipantCurrency` +-- + +DROP TABLE IF EXISTS `settlementParticipantCurrency`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `settlementParticipantCurrency` ( + `settlementParticipantCurrencyId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `settlementId` bigint(20) unsigned NOT NULL, + `participantCurrencyId` int(10) unsigned NOT NULL, + `netAmount` decimal(18,4) NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `currentStateChangeId` bigint(20) unsigned DEFAULT NULL, + `settlementTransferId` varchar(36) DEFAULT NULL, + PRIMARY KEY (`settlementParticipantCurrencyId`), + KEY `settlementparticipantcurrency_settlementid_index` (`settlementId`), + KEY `settlementparticipantcurrency_participantcurrencyid_index` (`participantCurrencyId`), + KEY `settlementparticipantcurrency_settlementtransferid_index` (`settlementTransferId`), + KEY `spc_currentstatechangeid_foreign` (`currentStateChangeId`), + CONSTRAINT `settlementparticipantcurrency_participantcurrencyid_foreign` FOREIGN KEY (`participantCurrencyId`) REFERENCES `participantCurrency` (`participantcurrencyid`), + CONSTRAINT `settlementparticipantcurrency_settlementid_foreign` FOREIGN KEY (`settlementId`) REFERENCES `settlement` (`settlementid`), + CONSTRAINT `spc_currentstatechangeid_foreign` FOREIGN KEY (`currentStateChangeId`) REFERENCES `settlementParticipantCurrencyStateChange` (`settlementparticipantcurrencystatechangeid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementParticipantCurrencyStateChange` +-- + +DROP TABLE IF EXISTS `settlementParticipantCurrencyStateChange`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `settlementParticipantCurrencyStateChange` ( + `settlementParticipantCurrencyStateChangeId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `settlementParticipantCurrencyId` bigint(20) unsigned NOT NULL, + `settlementStateId` varchar(50) NOT NULL, + `reason` varchar(512) DEFAULT NULL, + `externalReference` varchar(50) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`settlementParticipantCurrencyStateChangeId`), + KEY `spcsc_settlementparticipantcurrencyid_index` (`settlementParticipantCurrencyId`), + KEY `spcsc_settlementstateid_index` (`settlementStateId`), + CONSTRAINT `spcsc_settlementparticipantcurrencyid_foreign` FOREIGN KEY (`settlementParticipantCurrencyId`) REFERENCES `settlementParticipantCurrency` (`settlementparticipantcurrencyid`), + CONSTRAINT `spcsc_settlementstateid_foreign` FOREIGN KEY (`settlementStateId`) REFERENCES `settlementState` (`settlementstateid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementSettlementWindow` +-- + +DROP TABLE IF EXISTS `settlementSettlementWindow`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `settlementSettlementWindow` ( + `settlementSettlementWindowId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `settlementId` bigint(20) unsigned NOT NULL, + `settlementWindowId` bigint(20) unsigned NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`settlementSettlementWindowId`), + UNIQUE KEY `settlementsettlementwindow_unique` (`settlementId`,`settlementWindowId`), + KEY `settlementsettlementwindow_settlementid_index` (`settlementId`), + KEY `settlementsettlementwindow_settlementwindowid_index` (`settlementWindowId`), + CONSTRAINT `settlementsettlementwindow_settlementid_foreign` FOREIGN KEY (`settlementId`) REFERENCES `settlement` (`settlementid`), + CONSTRAINT `settlementsettlementwindow_settlementwindowid_foreign` FOREIGN KEY (`settlementWindowId`) REFERENCES `settlementWindow` (`settlementwindowid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementState` +-- + +DROP TABLE IF EXISTS `settlementState`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `settlementState` ( + `settlementStateId` varchar(50) NOT NULL, + `enumeration` varchar(50) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`settlementStateId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementStateChange` +-- + +DROP TABLE IF EXISTS `settlementStateChange`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `settlementStateChange` ( + `settlementStateChangeId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `settlementId` bigint(20) unsigned NOT NULL, + `settlementStateId` varchar(50) NOT NULL, + `reason` varchar(512) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`settlementStateChangeId`), + KEY `settlementstatechange_settlementid_index` (`settlementId`), + KEY `settlementstatechange_settlementstateid_index` (`settlementStateId`), + CONSTRAINT `settlementstatechange_settlementid_foreign` FOREIGN KEY (`settlementId`) REFERENCES `settlement` (`settlementid`), + CONSTRAINT `settlementstatechange_settlementstateid_foreign` FOREIGN KEY (`settlementStateId`) REFERENCES `settlementState` (`settlementstateid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementTransferParticipant` +-- + +DROP TABLE IF EXISTS `settlementTransferParticipant`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `settlementTransferParticipant` ( + `settlementTransferParticipantId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `settlementId` bigint(20) unsigned NOT NULL, + `settlementWindowId` bigint(20) unsigned NOT NULL, + `participantCurrencyId` int(10) unsigned NOT NULL, + `transferParticipantRoleTypeId` int(10) unsigned NOT NULL, + `ledgerEntryTypeId` int(10) unsigned NOT NULL, + `amount` decimal(18,4) NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`settlementTransferParticipantId`), + KEY `settlementtransferparticipant_settlementid_index` (`settlementId`), + KEY `settlementtransferparticipant_settlementwindowid_index` (`settlementWindowId`), + KEY `settlementtransferparticipant_participantcurrencyid_index` (`participantCurrencyId`), + KEY `stp_transferparticipantroletypeid_index` (`transferParticipantRoleTypeId`), + KEY `settlementtransferparticipant_ledgerentrytypeid_index` (`ledgerEntryTypeId`), + CONSTRAINT `settlementtransferparticipant_ledgerentrytypeid_foreign` FOREIGN KEY (`ledgerEntryTypeId`) REFERENCES `ledgerEntryType` (`ledgerentrytypeid`), + CONSTRAINT `settlementtransferparticipant_participantcurrencyid_foreign` FOREIGN KEY (`participantCurrencyId`) REFERENCES `participantCurrency` (`participantcurrencyid`), + CONSTRAINT `settlementtransferparticipant_settlementid_foreign` FOREIGN KEY (`settlementId`) REFERENCES `settlement` (`settlementid`), + CONSTRAINT `settlementtransferparticipant_settlementwindowid_foreign` FOREIGN KEY (`settlementWindowId`) REFERENCES `settlementWindow` (`settlementwindowid`), + CONSTRAINT `stp_transferparticipantroletypeid_foreign` FOREIGN KEY (`transferParticipantRoleTypeId`) REFERENCES `transferParticipantRoleType` (`transferparticipantroletypeid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementWindow` +-- + +DROP TABLE IF EXISTS `settlementWindow`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `settlementWindow` ( + `settlementWindowId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `reason` varchar(512) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `currentStateChangeId` bigint(20) unsigned DEFAULT NULL, + PRIMARY KEY (`settlementWindowId`), + KEY `settlementwindow_currentstatechangeid_foreign` (`currentStateChangeId`), + CONSTRAINT `settlementwindow_currentstatechangeid_foreign` FOREIGN KEY (`currentStateChangeId`) REFERENCES `settlementWindowStateChange` (`settlementwindowstatechangeid`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementWindowContent` +-- + +DROP TABLE IF EXISTS `settlementWindowContent`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `settlementWindowContent` ( + `settlementWindowContentId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `settlementWindowId` bigint(20) unsigned NOT NULL, + `ledgerAccountTypeId` int(10) unsigned NOT NULL, + `currencyId` varchar(3) NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `currentStateChangeId` bigint(20) unsigned DEFAULT NULL, + `settlementId` bigint(20) unsigned DEFAULT NULL, + PRIMARY KEY (`settlementWindowContentId`), + KEY `settlementwindowcontent_settlementwindowid_index` (`settlementWindowId`), + KEY `settlementwindowcontent_ledgeraccounttypeid_index` (`ledgerAccountTypeId`), + KEY `settlementwindowcontent_currencyid_index` (`currencyId`), + KEY `settlementwindowcontent_currentstatechangeid_index` (`currentStateChangeId`), + KEY `settlementwindowcontent_settlementid_index` (`settlementId`), + CONSTRAINT `settlementwindowcontent_currencyid_foreign` FOREIGN KEY (`currencyId`) REFERENCES `currency` (`currencyid`), + CONSTRAINT `settlementwindowcontent_currentstatechangeid_foreign` FOREIGN KEY (`currentStateChangeId`) REFERENCES `settlementWindowContentStateChange` (`settlementwindowcontentstatechangeid`), + CONSTRAINT `settlementwindowcontent_ledgeraccounttypeid_foreign` FOREIGN KEY (`ledgerAccountTypeId`) REFERENCES `ledgerAccountType` (`ledgeraccounttypeid`), + CONSTRAINT `settlementwindowcontent_settlementid_foreign` FOREIGN KEY (`settlementId`) REFERENCES `settlement` (`settlementid`), + CONSTRAINT `settlementwindowcontent_settlementwindowid_foreign` FOREIGN KEY (`settlementWindowId`) REFERENCES `settlementWindow` (`settlementwindowid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementWindowContentStateChange` +-- + +DROP TABLE IF EXISTS `settlementWindowContentStateChange`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `settlementWindowContentStateChange` ( + `settlementWindowContentStateChangeId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `settlementWindowContentId` bigint(20) unsigned NOT NULL, + `settlementWindowStateId` varchar(50) NOT NULL, + `reason` varchar(512) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`settlementWindowContentStateChangeId`), + KEY `swcsc_settlementwindowcontentid_index` (`settlementWindowContentId`), + KEY `swcsc_settlementwindowstateid_index` (`settlementWindowStateId`), + CONSTRAINT `swc_settlementwindowcontentid_foreign` FOREIGN KEY (`settlementWindowContentId`) REFERENCES `settlementWindowContent` (`settlementwindowcontentid`), + CONSTRAINT `sws1_settlementwindowstateid_foreign` FOREIGN KEY (`settlementWindowStateId`) REFERENCES `settlementWindowState` (`settlementwindowstateid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementWindowState` +-- + +DROP TABLE IF EXISTS `settlementWindowState`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `settlementWindowState` ( + `settlementWindowStateId` varchar(50) NOT NULL, + `enumeration` varchar(50) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`settlementWindowStateId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `settlementWindowStateChange` +-- + +DROP TABLE IF EXISTS `settlementWindowStateChange`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `settlementWindowStateChange` ( + `settlementWindowStateChangeId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `settlementWindowId` bigint(20) unsigned NOT NULL, + `settlementWindowStateId` varchar(50) NOT NULL, + `reason` varchar(512) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`settlementWindowStateChangeId`), + KEY `settlementwindowstatechange_settlementwindowid_index` (`settlementWindowId`), + KEY `settlementwindowstatechange_settlementwindowstateid_index` (`settlementWindowStateId`), + CONSTRAINT `settlementwindowstatechange_settlementwindowid_foreign` FOREIGN KEY (`settlementWindowId`) REFERENCES `settlementWindow` (`settlementwindowid`), + CONSTRAINT `settlementwindowstatechange_settlementwindowstateid_foreign` FOREIGN KEY (`settlementWindowStateId`) REFERENCES `settlementWindowState` (`settlementwindowstateid`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `token` +-- + +DROP TABLE IF EXISTS `token`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `token` ( + `tokenId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `participantId` int(10) unsigned NOT NULL, + `value` varchar(256) NOT NULL, + `expiration` bigint(20) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`tokenId`), + UNIQUE KEY `token_value_unique` (`value`), + KEY `token_participantid_index` (`participantId`), + CONSTRAINT `token_participantid_foreign` FOREIGN KEY (`participantId`) REFERENCES `participant` (`participantid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transactionInitiator` +-- + +DROP TABLE IF EXISTS `transactionInitiator`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `transactionInitiator` ( + `transactionInitiatorId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(256) NOT NULL, + `description` varchar(1024) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`transactionInitiatorId`), + UNIQUE KEY `transactioninitiator_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transactionInitiatorType` +-- + +DROP TABLE IF EXISTS `transactionInitiatorType`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `transactionInitiatorType` ( + `transactionInitiatorTypeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(256) NOT NULL, + `description` varchar(1024) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`transactionInitiatorTypeId`), + UNIQUE KEY `transactioninitiatortype_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transactionReference` +-- + +DROP TABLE IF EXISTS `transactionReference`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `transactionReference` ( + `transactionReferenceId` varchar(36) NOT NULL COMMENT 'Common ID (decided by the Payer FSP) between the FSPs for the future transaction object', + `quoteId` varchar(36) DEFAULT NULL COMMENT 'Common ID between the FSPs for the quote object, decided by the Payer FSP', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System row creation timestamp', + PRIMARY KEY (`transactionReferenceId`), + KEY `transactionreference_quoteid_index` (`quoteId`), + CONSTRAINT `transactionreference_quoteid_foreign` FOREIGN KEY (`quoteId`) REFERENCES `quoteDuplicateCheck` (`quoteid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transactionScenario` +-- + +DROP TABLE IF EXISTS `transactionScenario`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `transactionScenario` ( + `transactionScenarioId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(256) NOT NULL, + `description` varchar(1024) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`transactionScenarioId`), + UNIQUE KEY `transactionscenario_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transactionSubScenario` +-- + +DROP TABLE IF EXISTS `transactionSubScenario`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `transactionSubScenario` ( + `transactionSubScenarioId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(256) NOT NULL, + `description` varchar(1024) DEFAULT NULL COMMENT 'Possible sub-scenario, defined locally within the scheme', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'System dateTime stamp pertaining to the inserted record', + PRIMARY KEY (`transactionSubScenarioId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transfer` +-- + +DROP TABLE IF EXISTS `transfer`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `transfer` ( + `transferId` varchar(36) NOT NULL, + `amount` decimal(18,4) NOT NULL, + `currencyId` varchar(3) NOT NULL, + `ilpCondition` varchar(256) NOT NULL, + `expirationDate` datetime NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferId`), + KEY `transfer_currencyid_index` (`currencyId`), + CONSTRAINT `transfer_currencyid_foreign` FOREIGN KEY (`currencyId`) REFERENCES `currency` (`currencyid`), + CONSTRAINT `transfer_transferid_foreign` FOREIGN KEY (`transferId`) REFERENCES `transferDuplicateCheck` (`transferid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferDuplicateCheck` +-- + +DROP TABLE IF EXISTS `transferDuplicateCheck`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `transferDuplicateCheck` ( + `transferId` varchar(36) NOT NULL, + `hash` varchar(256) NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferError` +-- + +DROP TABLE IF EXISTS `transferError`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `transferError` ( + `transferId` varchar(36) NOT NULL, + `transferStateChangeId` bigint(20) unsigned NOT NULL, + `errorCode` int(10) unsigned NOT NULL, + `errorDescription` varchar(128) NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferId`), + KEY `transfererror_transferstatechangeid_foreign` (`transferStateChangeId`), + CONSTRAINT `transfererror_transferstatechangeid_foreign` FOREIGN KEY (`transferStateChangeId`) REFERENCES `transferStateChange` (`transferstatechangeid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferErrorDuplicateCheck` +-- + +DROP TABLE IF EXISTS `transferErrorDuplicateCheck`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `transferErrorDuplicateCheck` ( + `transferId` varchar(36) NOT NULL, + `hash` varchar(256) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferId`), + CONSTRAINT `transfererrorduplicatecheck_transferid_foreign` FOREIGN KEY (`transferId`) REFERENCES `transfer` (`transferid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferExtension` +-- + +DROP TABLE IF EXISTS `transferExtension`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `transferExtension` ( + `transferExtensionId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `transferId` varchar(36) NOT NULL, + `key` varchar(128) NOT NULL, + `value` text NOT NULL, + `isFulfilment` tinyint(1) NOT NULL DEFAULT '0', + `isError` tinyint(1) NOT NULL DEFAULT '0', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferExtensionId`), + KEY `transferextension_transferid_foreign` (`transferId`), + CONSTRAINT `transferextension_transferid_foreign` FOREIGN KEY (`transferId`) REFERENCES `transfer` (`transferid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferFulfilment` +-- + +DROP TABLE IF EXISTS `transferFulfilment`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `transferFulfilment` ( + `transferId` varchar(36) NOT NULL, + `ilpFulfilment` varchar(256) DEFAULT NULL, + `completedDate` datetime NOT NULL, + `isValid` tinyint(1) DEFAULT NULL, + `settlementWindowId` bigint(20) unsigned DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferId`), + KEY `transferfulfilment_settlementwindowid_foreign` (`settlementWindowId`), + CONSTRAINT `transferfulfilment_settlementwindowid_foreign` FOREIGN KEY (`settlementWindowId`) REFERENCES `settlementWindow` (`settlementwindowid`), + CONSTRAINT `transferfulfilment_transferid_foreign` FOREIGN KEY (`transferId`) REFERENCES `transferFulfilmentDuplicateCheck` (`transferid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferFulfilmentDuplicateCheck` +-- + +DROP TABLE IF EXISTS `transferFulfilmentDuplicateCheck`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `transferFulfilmentDuplicateCheck` ( + `transferId` varchar(36) NOT NULL, + `hash` varchar(256) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferId`), + CONSTRAINT `transferfulfilmentduplicatecheck_transferid_foreign` FOREIGN KEY (`transferId`) REFERENCES `transfer` (`transferid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferParticipant` +-- + +DROP TABLE IF EXISTS `transferParticipant`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `transferParticipant` ( + `transferParticipantId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `transferId` varchar(36) NOT NULL, + `participantCurrencyId` int(10) unsigned NOT NULL, + `transferParticipantRoleTypeId` int(10) unsigned NOT NULL, + `ledgerEntryTypeId` int(10) unsigned NOT NULL, + `amount` decimal(18,4) NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `currentStateChangeId` bigint(20) unsigned DEFAULT NULL, + PRIMARY KEY (`transferParticipantId`), + KEY `transferparticipant_transferid_index` (`transferId`), + KEY `transferparticipant_participantcurrencyid_index` (`participantCurrencyId`), + KEY `transferparticipant_transferparticipantroletypeid_index` (`transferParticipantRoleTypeId`), + KEY `transferparticipant_ledgerentrytypeid_index` (`ledgerEntryTypeId`), + KEY `transferparticipant_currentstatechangeid_foreign` (`currentStateChangeId`), + CONSTRAINT `transferparticipant_currentstatechangeid_foreign` FOREIGN KEY (`currentStateChangeId`) REFERENCES `transferParticipantStateChange` (`transferparticipantstatechangeid`), + CONSTRAINT `transferparticipant_ledgerentrytypeid_foreign` FOREIGN KEY (`ledgerEntryTypeId`) REFERENCES `ledgerEntryType` (`ledgerentrytypeid`), + CONSTRAINT `transferparticipant_participantcurrencyid_foreign` FOREIGN KEY (`participantCurrencyId`) REFERENCES `participantCurrency` (`participantcurrencyid`), + CONSTRAINT `transferparticipant_transferid_foreign` FOREIGN KEY (`transferId`) REFERENCES `transfer` (`transferid`), + CONSTRAINT `transferparticipant_transferparticipantroletypeid_foreign` FOREIGN KEY (`transferParticipantRoleTypeId`) REFERENCES `transferParticipantRoleType` (`transferparticipantroletypeid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferParticipantRoleType` +-- + +DROP TABLE IF EXISTS `transferParticipantRoleType`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `transferParticipantRoleType` ( + `transferParticipantRoleTypeId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferParticipantRoleTypeId`), + UNIQUE KEY `transferparticipantroletype_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferParticipantStateChange` +-- + +DROP TABLE IF EXISTS `transferParticipantStateChange`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `transferParticipantStateChange` ( + `transferParticipantStateChangeId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `transferParticipantId` bigint(20) unsigned NOT NULL, + `settlementWindowStateId` varchar(50) NOT NULL, + `reason` varchar(512) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferParticipantStateChangeId`), + KEY `transferparticipantstatechange_transferparticipantid_index` (`transferParticipantId`), + KEY `transferparticipantstatechange_settlementwindowstateid_index` (`settlementWindowStateId`), + CONSTRAINT `transferparticipantstatechange_settlementwindowstateid_foreign` FOREIGN KEY (`settlementWindowStateId`) REFERENCES `settlementWindowState` (`settlementwindowstateid`), + CONSTRAINT `transferparticipantstatechange_transferparticipantid_foreign` FOREIGN KEY (`transferParticipantId`) REFERENCES `transferParticipant` (`transferparticipantid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferRules` +-- + +DROP TABLE IF EXISTS `transferRules`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `transferRules` ( + `transferRulesId` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(128) NOT NULL, + `description` varchar(512) DEFAULT NULL, + `rule` text NOT NULL, + `enabled` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferRulesId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferState` +-- + +DROP TABLE IF EXISTS `transferState`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `transferState` ( + `transferStateId` varchar(50) NOT NULL, + `enumeration` varchar(50) NOT NULL COMMENT 'transferState associated to the Mojaloop API', + `description` varchar(512) DEFAULT NULL, + `isActive` tinyint(1) NOT NULL DEFAULT '1', + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferStateId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferStateChange` +-- + +DROP TABLE IF EXISTS `transferStateChange`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `transferStateChange` ( + `transferStateChangeId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `transferId` varchar(36) NOT NULL, + `transferStateId` varchar(50) NOT NULL, + `reason` varchar(512) DEFAULT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferStateChangeId`), + KEY `transferstatechange_transferid_index` (`transferId`), + KEY `transferstatechange_transferstateid_index` (`transferStateId`), + CONSTRAINT `transferstatechange_transferid_foreign` FOREIGN KEY (`transferId`) REFERENCES `transfer` (`transferid`), + CONSTRAINT `transferstatechange_transferstateid_foreign` FOREIGN KEY (`transferStateId`) REFERENCES `transferState` (`transferstateid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Table structure for table `transferTimeout` +-- + +DROP TABLE IF EXISTS `transferTimeout`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!50503 SET character_set_client = utf8mb4 */; +CREATE TABLE `transferTimeout` ( + `transferTimeoutId` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `transferId` varchar(36) NOT NULL, + `expirationDate` datetime NOT NULL, + `createdDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`transferTimeoutId`), + UNIQUE KEY `transfertimeout_transferid_unique` (`transferId`), + CONSTRAINT `transfertimeout_transferid_foreign` FOREIGN KEY (`transferId`) REFERENCES `transfer` (`transferid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Final view structure for view `quotePartyView` +-- + +/*!50001 DROP VIEW IF EXISTS `quotePartyView`*/; +/*!50001 SET @saved_cs_client = @@character_set_client */; +/*!50001 SET @saved_cs_results = @@character_set_results */; +/*!50001 SET @saved_col_connection = @@collation_connection */; +/*!50001 SET character_set_client = utf8 */; +/*!50001 SET character_set_results = utf8 */; +/*!50001 SET collation_connection = utf8_general_ci */; +/*!50001 CREATE ALGORITHM=UNDEFINED */ +/*!50013 DEFINER=`central_ledger`@`%` SQL SECURITY DEFINER */ +/*!50001 VIEW `quotePartyView` AS select `qp`.`quoteId` AS `quoteId`,`qp`.`quotePartyId` AS `quotePartyId`,`pt`.`name` AS `partyType`,`pit`.`name` AS `identifierType`,`qp`.`partyIdentifierValue` AS `partyIdentifierValue`,`spit`.`name` AS `partySubIdOrType`,`qp`.`fspId` AS `fspId`,`qp`.`merchantClassificationCode` AS `merchantClassificationCode`,`qp`.`partyName` AS `partyName`,`p`.`firstName` AS `firstName`,`p`.`lastName` AS `lastName`,`p`.`middleName` AS `middleName`,`p`.`dateOfBirth` AS `dateOfBirth`,`gc`.`longitude` AS `longitude`,`gc`.`latitude` AS `latitude` from (((((`quoteParty` `qp` join `partyType` `pt` on((`pt`.`partyTypeId` = `qp`.`partyTypeId`))) join `partyIdentifierType` `pit` on((`pit`.`partyIdentifierTypeId` = `qp`.`partyIdentifierTypeId`))) left join `party` `p` on((`p`.`quotePartyId` = `qp`.`quotePartyId`))) left join `partyIdentifierType` `spit` on((`spit`.`partyIdentifierTypeId` = `qp`.`partySubIdOrTypeId`))) left join `geoCode` `gc` on((`gc`.`quotePartyId` = `qp`.`quotePartyId`))) */; +/*!50001 SET character_set_client = @saved_cs_client */; +/*!50001 SET character_set_results = @saved_cs_results */; +/*!50001 SET collation_connection = @saved_col_connection */; + +-- +-- Final view structure for view `quoteResponseView` +-- + +/*!50001 DROP VIEW IF EXISTS `quoteResponseView`*/; +/*!50001 SET @saved_cs_client = @@character_set_client */; +/*!50001 SET @saved_cs_results = @@character_set_results */; +/*!50001 SET @saved_col_connection = @@collation_connection */; +/*!50001 SET character_set_client = utf8 */; +/*!50001 SET character_set_results = utf8 */; +/*!50001 SET collation_connection = utf8_general_ci */; +/*!50001 CREATE ALGORITHM=UNDEFINED */ +/*!50013 DEFINER=`central_ledger`@`%` SQL SECURITY DEFINER */ +/*!50001 VIEW `quoteResponseView` AS select `qr`.`quoteResponseId` AS `quoteResponseId`,`qr`.`quoteId` AS `quoteId`,`qr`.`transferAmountCurrencyId` AS `transferAmountCurrencyId`,`qr`.`transferAmount` AS `transferAmount`,`qr`.`payeeReceiveAmountCurrencyId` AS `payeeReceiveAmountCurrencyId`,`qr`.`payeeReceiveAmount` AS `payeeReceiveAmount`,`qr`.`payeeFspFeeCurrencyId` AS `payeeFspFeeCurrencyId`,`qr`.`payeeFspFeeAmount` AS `payeeFspFeeAmount`,`qr`.`payeeFspCommissionCurrencyId` AS `payeeFspCommissionCurrencyId`,`qr`.`payeeFspCommissionAmount` AS `payeeFspCommissionAmount`,`qr`.`ilpCondition` AS `ilpCondition`,`qr`.`responseExpirationDate` AS `responseExpirationDate`,`qr`.`isValid` AS `isValid`,`qr`.`createdDate` AS `createdDate`,`qrilp`.`value` AS `ilpPacket`,`gc`.`longitude` AS `longitude`,`gc`.`latitude` AS `latitude` from ((((`quoteResponse` `qr` join `quoteResponseIlpPacket` `qrilp` on((`qrilp`.`quoteResponseId` = `qr`.`quoteResponseId`))) join `quoteParty` `qp` on((`qp`.`quoteId` = `qr`.`quoteId`))) join `partyType` `pt` on((`pt`.`partyTypeId` = `qp`.`partyTypeId`))) left join `geoCode` `gc` on((`gc`.`quotePartyId` = `qp`.`quotePartyId`))) where (`pt`.`name` = 'PAYEE') */; +/*!50001 SET character_set_client = @saved_cs_client */; +/*!50001 SET character_set_results = @saved_cs_results */; +/*!50001 SET collation_connection = @saved_col_connection */; + +-- +-- Final view structure for view `quoteView` +-- + +/*!50001 DROP VIEW IF EXISTS `quoteView`*/; +/*!50001 SET @saved_cs_client = @@character_set_client */; +/*!50001 SET @saved_cs_results = @@character_set_results */; +/*!50001 SET @saved_col_connection = @@collation_connection */; +/*!50001 SET character_set_client = utf8 */; +/*!50001 SET character_set_results = utf8 */; +/*!50001 SET collation_connection = utf8_general_ci */; +/*!50001 CREATE ALGORITHM=UNDEFINED */ +/*!50013 DEFINER=`central_ledger`@`%` SQL SECURITY DEFINER */ +/*!50001 VIEW `quoteView` AS select `q`.`quoteId` AS `quoteId`,`q`.`transactionReferenceId` AS `transactionReferenceId`,`q`.`transactionRequestId` AS `transactionRequestId`,`q`.`note` AS `note`,`q`.`expirationDate` AS `expirationDate`,`ti`.`name` AS `transactionInitiator`,`tit`.`name` AS `transactionInitiatorType`,`ts`.`name` AS `transactionScenario`,`q`.`balanceOfPaymentsId` AS `balanceOfPaymentsId`,`tss`.`name` AS `transactionSubScenario`,`amt`.`name` AS `amountType`,`q`.`amount` AS `amount`,`q`.`currencyId` AS `currency` from (((((`quote` `q` join `transactionInitiator` `ti` on((`ti`.`transactionInitiatorId` = `q`.`transactionInitiatorId`))) join `transactionInitiatorType` `tit` on((`tit`.`transactionInitiatorTypeId` = `q`.`transactionInitiatorTypeId`))) join `transactionScenario` `ts` on((`ts`.`transactionScenarioId` = `q`.`transactionScenarioId`))) join `amountType` `amt` on((`amt`.`amountTypeId` = `q`.`amountTypeId`))) left join `transactionSubScenario` `tss` on((`tss`.`transactionSubScenarioId` = `q`.`transactionSubScenarioId`))) */; +/*!50001 SET character_set_client = @saved_cs_client */; +/*!50001 SET character_set_results = @saved_cs_results */; +/*!50001 SET collation_connection = @saved_col_connection */; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2020-02-20 22:51:43 diff --git a/docs/technical/central-ledger/assets/database/central-ledger-schema-DBeaver.erd b/docs/technical/central-ledger/assets/database/central-ledger-schema-DBeaver.erd new file mode 100644 index 000000000..303fa1534 --- /dev/null +++ b/docs/technical/central-ledger/assets/database/central-ledger-schema-DBeaver.erd @@ -0,0 +1,612 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/technical/central-ledger/assets/database/central-ledger-schema.png b/docs/technical/central-ledger/assets/database/central-ledger-schema.png new file mode 100644 index 000000000..62b4a1a1e Binary files /dev/null and b/docs/technical/central-ledger/assets/database/central-ledger-schema.png differ diff --git a/docs/technical/central-ledger/assets/diagrams/architecture/Arch-mojaloop-central-ledger.svg b/docs/technical/central-ledger/assets/diagrams/architecture/Arch-mojaloop-central-ledger.svg new file mode 100644 index 000000000..d91178975 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/architecture/Arch-mojaloop-central-ledger.svg @@ -0,0 +1,3 @@ + + +
Mojaloop Adapter
Mojaloop Adapter
Ledger
Ledger
Mojaloop
Adapter
[Not supported by viewer]
C 1. Transfer
C 1. Transfer
request_to_prepare
request_to_prepare
C 1.2
[Not supported by viewer]
C 1.3
[Not supported by viewer]
prepared.notification
prepared.notification
C 1.4
C 1.4
fulfiled.notification
fulfiled.notification
request_to_fulfil
request_to_fulfil
Fulfil Transfer
Fulfil Transfer
C 1.8
C 1.8
C 1.9
[Not supported by viewer]
C 1.10
[Not supported by viewer]
C 1.11
C 1.11
C 1.12 Fulfil Notify
C 1.12 Fulfil Notify
C 1.1
C 1.1
C 1.5
C 1.5
DB
DB
Central Services
[Not supported by viewer]
positions
positions
Account-Lookup-Service
[Not supported by viewer]
Pathfinder
Pathfinder
FSP
Backend

(Does not natively speak Mojaloop API)



[Not supported by viewer]
Scheme-Adapter

(Converts from Mojaloop API to backend FSP API)
[Not supported by viewer]
A 2. MSISDN
based lookup
A 2. MSISDN <br>based lookup
DB
DB
 Database
 Database
FSP
Backend
  

(Natively speaks Mojaloop API)



[Not supported by viewer]
A
A
A 1. User Lookup
A 1. User Lookup
A 3. Receiver Details
A 3. Receiver Details
B
B
B 1. Quote
B 1. Quote
Mojaloop Hub
[Not supported by viewer]
Payer FSP
[Not supported by viewer]
Payee FSP
[Not supported by viewer]
Ledger
Ledger<br>
Ledger
Ledger<br>
C
C
kafka
kafka
kafka
kafka
kafka
kafka
kafka
kafka
kafka
kafka
C 1.6
Prepare
Transfer
[Not supported by viewer]
C 1.7
C 1.7
C 1.11
C 1.11
C 1.12
C 1.12
Fulfil Notify
Fulfil Notify
C 1.13
Fulfil Notify
[Not supported by viewer]
B 2. Fee /
Commission
[Not supported by viewer]
A 4. Get 
receiver 
details
[Not supported by viewer]
B 1. Quote
B 1. Quote
D 6.
D 6.
Settlements
Settlements
D 5. Update Positions
[Not supported by viewer]
settlement.notifications
settlement.notifications
Scheme Settlement Processor
<span>Scheme Settlement Processor</span><br>
Hub Operator
Hub Operator
D 1. Create
Settlement
[Not supported by viewer]
D
D
D 2. Query
Settlement
Report
(Pull)
[Not supported by viewer]
D 4. Send
Acks
(Push)
[Not supported by viewer]
Settlement
Bank
Settlement<br>Bank<br>
D 3. Process Settlements
[Not supported by viewer]
Bank
[Not supported by viewer]
D 7. Position Notifications Change result
D 7. Position Notifications Change result
D 7. Settlement Notification
D 7. Settlement Notification
\ No newline at end of file diff --git a/docs/technical/central-ledger/assets/diagrams/architecture/Transfers-Arch-End-to-End-v1.0-old.svg b/docs/technical/central-ledger/assets/diagrams/architecture/Transfers-Arch-End-to-End-v1.0-old.svg new file mode 100644 index 000000000..73c49765f --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/architecture/Transfers-Arch-End-to-End-v1.0-old.svg @@ -0,0 +1,3 @@ + + +
1.5 Increment Position (fsp1)
[Not supported by viewer]
1.4 Increment
Position (fsp1)

[Not supported by viewer]
PrepareHandler
PrepareHandler
PositionHandler
PositionHandler
Fulfil
Sucess
[Not supported by viewer]
2.4 Fulfil
Success
[Not supported by viewer]
<alt> 2.4 
Fulfil Reject

[Not supported by viewer]
Fulfil
Reject
[Not supported by viewer]
<alt> 2.5 Decrement
Position (fsp1)

[Not supported by viewer]
<alt>1.6 Reject Notification
(Not enough position)

[Not supported by viewer]
Central - Services
<font style="font-size: 18px">Central - Services</font>
3.0 Reject
[Not supported by viewer]
2.6 Fulfil Notification /
 <alt> 2.6 Reject Notification (Fulfil) /
3.2 Reject Notification (Timeout)

[Not supported by viewer]
1.0 Transfer 
Request

[Not supported by viewer]
3.1 Decrement
Position (fsp1)

[Not supported by viewer]
1.6 Prepare Notification
[Not supported by viewer]
ML-Adapter
[Not supported by viewer]
Transfer
API
[Not supported by viewer]
Notification
Event Handler
[Not supported by viewer]
fsp prepare
fsp prepare
1.3 Prepare Consume
[Not supported by viewer]
notifications
notifications
FSP1
(Payer)

[Not supported by viewer]
FSP2
(Payee)
[Not supported by viewer]
1.1
Prepare Request
[Not supported by viewer]
1.2 Accpeted
(202)
[Not supported by viewer]
Transfer
API
[Not supported by viewer]
2.0 Fulfil 
Success / 
Reject

[Not supported by viewer]
fulfils
fulfils
FulfilHandler
FulfilHandler
Success/
Reject
[Not supported by viewer]
2.5 Decrement
Position (fsp2)

[Not supported by viewer]
2.1 Fulfil 
Success / Reject

[Not supported by viewer]
2.2 OK
(200)
[Not supported by viewer]
2.3 Fulfil
Success /
Reject
Consume
[Not supported by viewer]
OK (200)
[Not supported by viewer]
OK (200)
[Not supported by viewer]
Transfer Timeout
Handler
[Not supported by viewer]
<alt> 1.4 Prepare Failure
[Not supported by viewer]
<alt> 2.4 Fulfil Failure
[Not supported by viewer]
2.7 Fulfil Notify Callback /
<alt> 2.7 Reject Response (Fulfil reject) /
3.1, 3.3 Reject Response (Timeout) /
<alt> 1.7 Reject Response (Not enough position)
<alt> 1.5 Prepare Failure 

[Not supported by viewer]
1.7 Prepare Notify /
2.8 Fulfil Notify /
<alt> 2.7 Reject Response (Fulfil reject)
3.3 Reject Response (Timeout)
<alt> 2.5 Fulfil Failure

[Not supported by viewer]
position
position<br>
\ No newline at end of file diff --git a/docs/technical/central-ledger/assets/diagrams/architecture/Transfers-Arch-End-to-End-v1.0.svg b/docs/technical/central-ledger/assets/diagrams/architecture/Transfers-Arch-End-to-End-v1.0.svg new file mode 100644 index 000000000..02658b83d --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/architecture/Transfers-Arch-End-to-End-v1.0.svg @@ -0,0 +1,3 @@ + + +
1.5 Increment Position (fsp1)
1.5 Increment Position (fsp1)
1.4 Increment
Position (fsp1)

1.4 Increment...
PrepareHandler
PrepareHandler
PositionHandler
PositionHandler
Fulfil
Sucess
Fulfil...
2.4 Fulfil
Success
2.4 Fulfil...
<alt> 2.4 
Fulfil Reject

<alt> 2.4...
Fulfil
Reject
Fulfil...
<alt> 2.5 Decrement
Position (fsp1)

<alt> 2.5 Decrement...
<alt>1.6 Reject Notification
(Not enough position)

<alt>1.6...
Central - Services
Central - Services
3.0 Reject
3.0 Reject
2.6 Fulfil Notification /
 <alt> 2.6 Reject Notification (Fulfil) /
3.2 Reject Notification (Timeout)

2.6 Fulfil Notification /...
1.0 Transfer 
Request

1.0 Transfer...
3.1 Decrement
Position (fsp1)

3.1 Decrement...
1.6 Prepare Notification
1.6 Prepare Notification
ML-Adapter
ML-Adapter
Transfer
API
Transfer...
Notification
Event Handler
Notification...
fsp prepare
fsp prep...
1.3 Prepare Consume
1.3 Prepare Consume
notifications
notificati...
FSP1
(Payer)

FSP1...
FSP2
(Payee)
FSP2...
1.1
Prepare Request
1.1...
1.2 Accpeted
(202)
1.2 Accpeted...
Transfer
API
Transfer...
2.0 Fulfil 
Success / 
Reject

2...
fulfils
fulfils
FulfilHandler
FulfilHandler
Success/
Reject
Success/...
2.5 Decrement
Position (fsp2)

2.5 Decrement...
2.1 Fulfil 
Success / Reject

2.1 Fulfil...
2.2 OK
(200)
2.2 OK...
2.3 Fulfil
Success /
Reject
Consume
2.3 Fulfil...
OK (200)
OK (200)
OK (200)
OK (200)
Transfer Timeout
Handler
Transfer Timeout...
<alt> 1.4 Prepare Failure
<alt> 1.4 Prepare Failure
<alt> 2.4 Fulfil Failure
<alt>...
2.7 Fulfil Notify Callback /
<alt> 2.7 Reject Response (Fulfil reject) /
3.1, 3.3 Reject Response (Timeout) /
<alt> 1.7 Reject Response (Not enough position)
<alt> 1.5 Prepare Failure 

2.7 Fulfil Notify Callback /...
1.7 Prepare Notify /
2.8 Commit Notify (optional) /
<alt> 2.7 Reject Response (Fulfil reject)
3.3 Reject Response (Timeout)
<alt> 2.5 Fulfil Failure

1.7 Prepare Notify /...
position
position
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/docs/technical/central-ledger/assets/diagrams/architecture/Transfers-Arch-End-to-End-v1.1.svg b/docs/technical/central-ledger/assets/diagrams/architecture/Transfers-Arch-End-to-End-v1.1.svg new file mode 100644 index 000000000..e9a1460c8 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/architecture/Transfers-Arch-End-to-End-v1.1.svg @@ -0,0 +1,3 @@ + + +
1.5 Increment Position (fsp1)
1.5 Increment Position (fsp1)
1.4 Increment
Position (fsp1)

1.4 Increment...
PrepareHandler
PrepareHandler
PositionHandler
PositionHandler
Fulfil
Sucess
Fulfil...
2.4 Fulfil
Success
2.4 Fulfil...
<alt> 2.4 
Fulfil Reject

<alt> 2.4...
Fulfil
Reject
Fulfil...
<alt> 2.5 Decrement
Position (fsp1)

<alt> 2.5 Decrement...
<alt>1.6 Reject Notification
(Not enough position)

<alt>1.6...
Central - Services
Central - Services
3.0 Reject
3.0 Reject
2.6 Fulfil Notification /
 <alt> 2.6 Reject Notification (Fulfil) /
3.2 Reject Notification (Timeout)

2.6 Fulfil Notification /...
1.0 Transfer 
Request

1.0 Transfer...
3.1 Decrement
Position (fsp1)

3.1 Decrement...
1.6 Prepare Notification
1.6 Prepare Notification
ML-Adapter
ML-Adapter
Transfer
API
Transfer...
Notification
Event Handler
Notification...
fsp prepare
fsp prep...
1.3 Prepare Consume
1.3 Prepare Consume
notifications
notificati...
FSP1
(Payer)

FSP1...
FSP2
(Payee)
FSP2...
1.1
Prepare Request
1.1...
1.2 Accpeted
(202)
1.2 Accpeted...
Transfer
API
Transfer...
2.0 Fulfil 
Success / 
Reject

2...
fulfils
fulfils
FulfilHandler
FulfilHandler
Success/
Reject
Success/...
2.5 Decrement
Position (fsp2)

2.5 Decrement...
2.1 Fulfil 
Success / Reject

2.1 Fulfil...
2.2 OK
(200)
2.2 OK...
2.3 Fulfil
Success /
Reject
Consume
2.3 Fulfil...
OK (200)
OK (200)
OK (200)
OK (200)
Transfer Timeout
Handler
Transfer Timeout...
<alt> 1.4 Prepare Failure
<alt> 1.4 Prepare Failure
<alt> 2.4 Fulfil Failure
<alt>...
2.7 Fulfil Notify Callback /
<alt> 2.7 Reject Response (Fulfil reject) /
3.1, 3.3 Reject Response (Timeout) /
<alt> 1.7 Reject Response (Not enough position)
<alt> 1.5 Prepare Failure 

2.7 Fulfil Notify Callback /...
1.7 Prepare Notify /
2.8 Commit Notify (if transfer reserved) /
<alt> 2.7 Reject Response (Fulfil reject)
3.3 Reject Response (Timeout)
<alt> 2.5 Fulfil Failure

1.7 Prepare Notify /...
position
position
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-callback-3.1.0.plantuml b/docs/technical/central-ledger/assets/diagrams/sequence/seq-callback-3.1.0.plantuml new file mode 100644 index 000000000..461a64c23 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-callback-3.1.0.plantuml @@ -0,0 +1,160 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Shashikant Hirugade + -------------- + ******'/ + +@startuml +' declate title +title 3.1.0 Get Participant Callback Details + +autonumber +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +entity "ML-API-ADAPTER" as MLAPI +boundary "Central Service API" as CSAPI +control "Participant Handler" as PARTICIPANT_HANDLER +entity "Central Service API" as CSAPI +entity "Participant DAO" as PARTICIPANT_DAO +database "Central Store" as DB +box "ML API Adapter Service" #LightBlue +participant MLAPI +end box + +box "Central Services" #LightYellow +participant CSAPI +participant PARTICIPANT_HANDLER +participant PARTICIPANT_DAO +participant DB +end box + +' start flow + +activate MLAPI +group Get Callback Details + MLAPI -> CSAPI: Request to get callback details - GET - /participants/{name}/endpoints?type={typeValue} + activate CSAPI + CSAPI -> PARTICIPANT_HANDLER: Fetch Callback details for Participant + activate PARTICIPANT_HANDLER + PARTICIPANT_HANDLER ->PARTICIPANT_DAO: Fetch Participant \nError code: 3200 + + activate PARTICIPANT_DAO + PARTICIPANT_DAO ->DB: Fetch Participant + activate DB + hnote over DB #lightyellow + participant + end note + DB --> PARTICIPANT_DAO: Retrieved Participant + deactivate DB + PARTICIPANT_DAO -->PARTICIPANT_HANDLER: Return Participant + deactivate PARTICIPANT_DAO + PARTICIPANT_HANDLER ->PARTICIPANT_HANDLER: Validate DFSP + alt Validate participant (success) + PARTICIPANT_HANDLER -> PARTICIPANT_HANDLER: check if "type" parameter is sent + alt Check if "type" parameter is sent (Sent) + PARTICIPANT_HANDLER ->PARTICIPANT_DAO: Fetch Callback details for Participant and type \nError code: 3000 + activate PARTICIPANT_DAO + PARTICIPANT_DAO ->DB: Fetch Callback details for Participant and type + note right of PARTICIPANT_DAO #lightgrey + Condition: + isActive = 1 + [endpointTypeId = ] + end note + + activate DB + hnote over DB #lightyellow + participantEndpoint + end note + DB --> PARTICIPANT_DAO: Retrieved Callback details for Participant and type + deactivate DB + PARTICIPANT_DAO -->PARTICIPANT_HANDLER: Return Callback details for Participant and type + deactivate PARTICIPANT_DAO + note right of PARTICIPANT_HANDLER #yellow + Message: + { + endpoints: {type: , value: } + } + end note + PARTICIPANT_HANDLER -->CSAPI: Return Callback details for Participant + deactivate PARTICIPANT_HANDLER + CSAPI -->MLAPI: Return Callback details for Participant + else Check if "type" parameter is sent (Not Sent) + activate PARTICIPANT_HANDLER + PARTICIPANT_HANDLER ->PARTICIPANT_DAO: Fetch Callback details for Participant \nError code: 3000 + activate PARTICIPANT_DAO + PARTICIPANT_DAO ->DB: Fetch Callback details for Participant + note right of PARTICIPANT_DAO #lightgrey + Condition: + isActive = 1 + end note + + activate DB + hnote over DB #lightyellow + participantEndpoint + end note + DB --> PARTICIPANT_DAO: Retrieved Callback details for Participant + deactivate DB + PARTICIPANT_DAO -->PARTICIPANT_HANDLER: Return Callback details for Participant + deactivate PARTICIPANT_DAO + note right of PARTICIPANT_HANDLER #yellow + Message: + { + endpoints: [ + {type: , value: }, + {type: , value: } + ] + } + end note + PARTICIPANT_HANDLER -->CSAPI: Return Callback details for Participant + ' deactivate PARTICIPANT_HANDLER + CSAPI -->MLAPI: Return Callback details for Participant + end + + + else Validate participant (failure)/ Error + activate PARTICIPANT_HANDLER + note right of PARTICIPANT_HANDLER #red: Validation failure/ Error! + activate PARTICIPANT_HANDLER + note right of PARTICIPANT_HANDLER #yellow + Message: + { + "errorInformation": { + "errorCode": , + "errorDescription": , + } + } + end note + PARTICIPANT_HANDLER -->CSAPI: Return Error code: 3000, 3200 + deactivate PARTICIPANT_HANDLER + CSAPI -->MLAPI: Return Error code: 3000, 3200 + + end + deactivate CSAPI + deactivate MLAPI +end + +@enduml diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-callback-3.1.0.svg b/docs/technical/central-ledger/assets/diagrams/sequence/seq-callback-3.1.0.svg new file mode 100644 index 000000000..c7acd7bd0 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-callback-3.1.0.svg @@ -0,0 +1,409 @@ + + + + + + + + + + + 3.1.0 Get Participant Callback Details + + + + ML API Adapter Service + + + + Central Services + + + + + + + + + ML-API-ADAPTER + + + + + ML-API-ADAPTER + + + + + Central Service API + + + + + Central Service API + + + + + Participant Handler + + + + + Participant Handler + + + + + Participant DAO + + + + + Participant DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Get Callback Details + + + + + 1 + + + Request to get callback details - GET - /participants/{name}/endpoints?type={typeValue} + + + + + 2 + + + Fetch Callback details for Participant + + + + + 3 + + + Fetch Participant + + + Error code: + + + 3200 + + + + + 4 + + + Fetch Participant + + + + participant + + + + + 5 + + + Retrieved Participant + + + + + 6 + + + Return Participant + + + + + 7 + + + Validate DFSP + + + + + alt + + + [Validate participant (success)] + + + + + 8 + + + check if "type" parameter is sent + + + + + alt + + + [Check if "type" parameter is sent (Sent)] + + + + + 9 + + + Fetch Callback details for Participant and type + + + Error code: + + + 3000 + + + + + 10 + + + Fetch Callback details for Participant and type + + + + + Condition: + + + isActive = 1 + + + [endpointTypeId = <type>] + + + + participantEndpoint + + + + + 11 + + + Retrieved Callback details for Participant and type + + + + + 12 + + + Return Callback details for Participant and type + + + + + Message: + + + { + + + endpoints: {type: <type>, value: <value>} + + + } + + + + + 13 + + + Return Callback details for Participant + + + + + 14 + + + Return Callback details for Participant + + + + [Check if "type" parameter is sent (Not Sent)] + + + + + 15 + + + Fetch Callback details for Participant + + + Error code: + + + 3000 + + + + + 16 + + + Fetch Callback details for Participant + + + + + Condition: + + + isActive = 1 + + + + participantEndpoint + + + + + 17 + + + Retrieved Callback details for Participant + + + + + 18 + + + Return Callback details for Participant + + + + + Message: + + + { + + + endpoints: [ + + + {type: <type>, value: <value>}, + + + {type: <type>, value: <value>} + + + ] + + + } + + + + + 19 + + + Return Callback details for Participant + + + + + 20 + + + Return Callback details for Participant + + + + [Validate participant (failure)/ Error] + + + + + Validation failure/ Error! + + + + + Message: + + + { + + + "errorInformation": { + + + "errorCode": <errorCode>, + + + "errorDescription": <ErrorMessage>, + + + } + + + } + + + + + 21 + + + Return + + + Error code: + + + 3000, 3200 + + + + + 22 + + + Return + + + Error code: + + + 3000, 3200 + + diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-callback-add-3.1.0.plantuml b/docs/technical/central-ledger/assets/diagrams/sequence/seq-callback-add-3.1.0.plantuml new file mode 100644 index 000000000..dd4849343 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-callback-add-3.1.0.plantuml @@ -0,0 +1,149 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Shashikant Hirugade + -------------- + ******'/ + + +@startuml +' declate title +title 3.1.0 Add Participant Callback Details + +autonumber +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +actor "HUB OPERATOR" as OPERATOR +boundary "Central Service API" as CSAPI +control "Participant Handler" as PARTICIPANT_HANDLER +entity "Central Service API" as CSAPI +entity "Participant DAO" as PARTICIPANT_DAO +database "Central Store" as DB + +box "Central Services" #LightYellow +participant CSAPI +participant PARTICIPANT_HANDLER +participant PARTICIPANT_DAO +participant DB +end box + +' start flow + +activate OPERATOR +group Add Callback Details + OPERATOR -> CSAPI: Request to add callback details - POST - /paticipants/{name}/endpoints + note right of OPERATOR #yellow + Message: + { + payload: { + endpoint: { + type: , + value: + } + } + } + end note + + activate CSAPI + CSAPI -> PARTICIPANT_HANDLER: Add Callback details for Participant + activate PARTICIPANT_HANDLER + PARTICIPANT_HANDLER ->PARTICIPANT_DAO: Fetch Participant \nError code: 3200 + + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Fetch Participant + activate DB + hnote over DB #lightyellow + participant + end note + DB --> PARTICIPANT_DAO: Retrieved Participant + deactivate DB + PARTICIPANT_DAO --> PARTICIPANT_HANDLER: Return Participant + deactivate PARTICIPANT_DAO + PARTICIPANT_HANDLER ->PARTICIPANT_HANDLER: Validate DFSP + alt Validate participant (success) + PARTICIPANT_HANDLER ->PARTICIPANT_DAO: Add Callback details for Participant \nError code: 2003/Msg: Service unavailable \nError code: 2001/Msg: Internal Server Error + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Persist Participant Endpoint + activate DB + hnote over DB #lightyellow + participantEndpoint + end note + deactivate DB + note right of PARTICIPANT_DAO #lightgrey + If (endpoint exists && isActive = 1) + oldEndpoint.isActive = 0 + insert endpoint + Else + insert endpoint + End + + end note + PARTICIPANT_DAO --> PARTICIPANT_HANDLER: Return status + deactivate PARTICIPANT_DAO + PARTICIPANT_HANDLER -> PARTICIPANT_HANDLER: Validate status + alt Validate status (success) + PARTICIPANT_HANDLER -->CSAPI: Return Status Code 201 + deactivate PARTICIPANT_HANDLER + CSAPI -->OPERATOR: Return Status Code 201 + else Validate status (failure) / Error + note right of PARTICIPANT_HANDLER #red: Error! + activate PARTICIPANT_HANDLER + note right of PARTICIPANT_HANDLER #yellow + Message: + { + "errorInformation": { + "errorCode": , + "errorDescription": , + } + } + end note + PARTICIPANT_HANDLER -->CSAPI: Return Error code + ' deactivate PARTICIPANT_HANDLER + CSAPI -->OPERATOR: Return Error code + + end + + else Validate participant (failure) + note right of PARTICIPANT_HANDLER #red: Validation failure! + activate PARTICIPANT_HANDLER + note right of PARTICIPANT_HANDLER #yellow + Message: + { + "errorInformation": { + "errorCode": 3200, + "errorDescription": "FSP id Not Found", + } + } + end note + PARTICIPANT_HANDLER -->CSAPI: Return Error code: 3200 + deactivate PARTICIPANT_HANDLER + CSAPI -->OPERATOR: Return Error code: 3200 + + end + deactivate CSAPI + deactivate OPERATOR +end +@enduml diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-callback-add-3.1.0.svg b/docs/technical/central-ledger/assets/diagrams/sequence/seq-callback-add-3.1.0.svg new file mode 100644 index 000000000..975978ddb --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-callback-add-3.1.0.svg @@ -0,0 +1,400 @@ + + + + + + + + + + + 3.1.0 Add Participant Callback Details + + + + Central Services + + + + + + + + + HUB OPERATOR + + + + + HUB OPERATOR + + + + + Central Service API + + + + + Central Service API + + + + + Participant Handler + + + + + Participant Handler + + + + + Participant DAO + + + + + Participant DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Add Callback Details + + + + + 1 + + + Request to add callback details - POST - /paticipants/{name}/endpoints + + + + + Message: + + + { + + + payload: { + + + endpoint: { + + + type: <typeValue>, + + + value: <endpointValue> + + + } + + + } + + + } + + + + + 2 + + + Add Callback details for Participant + + + + + 3 + + + Fetch Participant + + + Error code: + + + 3200 + + + + + 4 + + + Fetch Participant + + + + participant + + + + + 5 + + + Retrieved Participant + + + + + 6 + + + Return Participant + + + + + 7 + + + Validate DFSP + + + + + alt + + + [Validate participant (success)] + + + + + 8 + + + Add Callback details for Participant + + + Error code: + + + 2003/ + + + Msg: + + + Service unavailable + + + Error code: + + + 2001/ + + + Msg: + + + Internal Server Error + + + + + 9 + + + Persist Participant Endpoint + + + + participantEndpoint + + + + + If (endpoint exists && isActive = 1) + + + oldEndpoint.isActive = 0 + + + insert endpoint + + + Else + + + insert endpoint + + + End + + + + + 10 + + + Return status + + + + + 11 + + + Validate status + + + + + alt + + + [Validate status (success)] + + + + + 12 + + + Return Status Code 201 + + + + + 13 + + + Return Status Code 201 + + + + [Validate status (failure) / Error] + + + + + Error! + + + + + Message: + + + { + + + "errorInformation": { + + + "errorCode": <Error Code>, + + + "errorDescription": <Msg>, + + + } + + + } + + + + + 14 + + + Return + + + Error code + + + + + 15 + + + Return + + + Error code + + + + [Validate participant (failure)] + + + + + Validation failure! + + + + + Message: + + + { + + + "errorInformation": { + + + "errorCode": 3200, + + + "errorDescription": "FSP id Not Found", + + + } + + + } + + + + + 16 + + + Return + + + Error code: + + + 3200 + + + + + 17 + + + Return + + + Error code: + + + 3200 + + diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.0-v1.1.plantuml b/docs/technical/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.0-v1.1.plantuml new file mode 100644 index 000000000..c24ae484b --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.0-v1.1.plantuml @@ -0,0 +1,207 @@ +/' + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Valentin Genev + -------------- + '/ + + +@startuml +' declate title +title 2.1.0. DFSP2 sends a Fulfil Success Transfer request v1.1 + +autonumber +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +actor "DFSP1\nPayer" as DFSP1 +actor "DFSP2\nPayee" as DFSP2 +boundary "ML API Adapter" as MLAPI +control "ML API Notification Event Handler" as NOTIFY_HANDLER +boundary "Central Service API" as CSAPI +collections "topic-fulfil" as TOPIC_FULFIL +control "Fulfil Event Handler" as FULF_HANDLER +collections "topic-\nsettlement-model" as TOPIC_SETMODEL +control "Settlement Model\nHandler" as SETMODEL_HANDLER +collections "topic-\ntransfer-position" as TOPIC_TRANSFER_POSITION +control "Position Handler" as POS_HANDLER +collections "topic-\nnotification" as TOPIC_NOTIFICATIONS + +box "Financial Service Providers" #lightGray + participant DFSP1 + participant DFSP2 +end box + +box "ML API Adapter Service" #LightBlue + participant MLAPI + participant NOTIFY_HANDLER +end box + +box "Central Service" #LightYellow + participant CSAPI + participant TOPIC_FULFIL + participant FULF_HANDLER + participant TOPIC_SETMODEL + participant SETMODEL_HANDLER + participant TOPIC_TRANSFER_POSITION + participant POS_HANDLER + participant TOPIC_NOTIFICATIONS +end box + +' start flow +activate NOTIFY_HANDLER +activate FULF_HANDLER +activate SETMODEL_HANDLER +activate POS_HANDLER +group DFSP2 sends a request for notification after tranfer is being committed in the Switch + DFSP2 <-> DFSP2: Retrieve fulfilment string generated during\nthe quoting process or regenerate it using\n**Local secret** and **ILP Packet** as inputs + alt Send back notification reserve request + note right of DFSP2 #yellow + Headers - transferHeaders: { + Content-Length: , + Content-Type: , + Date: , + X-Forwarded-For: , + FSPIOP-Source: , + FSPIOP-Destination: , + FSPIOP-Encryption: , + FSPIOP-Signature: , + FSPIOP-URI: , + FSPIOP-HTTP-Method: + } + + Payload - transferMessage: + { + "fulfilment": , + "transferState": "RESERVED" + "extensionList": { + "extension": [ + { + "key": , + "value": + } + ] + } + } + end note + else Send back commit request + + note right of DFSP2 #yellow + Headers - transferHeaders: { + Content-Length: , + Content-Type: , + Date: , + X-Forwarded-For: , + FSPIOP-Source: , + FSPIOP-Destination: , + FSPIOP-Encryption: , + FSPIOP-Signature: , + FSPIOP-URI: , + FSPIOP-HTTP-Method: + } + + Payload - transferMessage: + { + "fulfilment": , + "completedTimestamp": , + "transferState": "COMMITTED" + "extensionList": { + "extension": [ + { + "key": , + "value": + } + ] + } + } + end note + end + DFSP2 ->> MLAPI: PUT - /transfers/ + activate MLAPI + MLAPI -> MLAPI: Validate incoming token and originator matching Payee\nError codes: 3000-3002, 3100-3107 + note right of MLAPI #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + type: fulfil, + action: reserve || commit, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + MLAPI -> TOPIC_FULFIL: Route & Publish Fulfil event for Payee\nError code: 2003 + activate TOPIC_FULFIL + TOPIC_FULFIL <-> TOPIC_FULFIL: Ensure event is replicated as configured (ACKS=all)\nError code: 2003 + TOPIC_FULFIL --> MLAPI: Respond replication acknowledgements have been received + deactivate TOPIC_FULFIL + MLAPI -->> DFSP2: Respond HTTP - 200 (OK) + deactivate MLAPI + TOPIC_FULFIL <- FULF_HANDLER: Consume message + ref over TOPIC_FULFIL, TOPIC_TRANSFER_POSITION: Fulfil Handler Consume (Success) {[[https://github.com/mojaloop/documentation/tree/master/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.1-v1.1.svg 2.1.1-v1.1]]} \n + FULF_HANDLER -> TOPIC_SETMODEL: Produce message + FULF_HANDLER -> TOPIC_TRANSFER_POSITION: Produce message + ||| + TOPIC_SETMODEL <- SETMODEL_HANDLER: Consume message + ref over TOPIC_SETMODEL, SETMODEL_HANDLER: Settlement Model Handler Consume (Success)\n + ||| + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume message + ref over TOPIC_TRANSFER_POSITION, TOPIC_NOTIFICATIONS: Position Handler Consume (Success)\n + POS_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + ||| + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message + opt action == 'commit' + ||| + ref over DFSP1, TOPIC_NOTIFICATIONS: Send notification to Participant (Payer)\n + NOTIFY_HANDLER -> DFSP1: Send callback notification + end + ||| + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message + opt action == 'reserve' + ||| + ref over DFSP2, TOPIC_NOTIFICATIONS: Send notification to Participant (Payee)\n + NOTIFY_HANDLER -> DFSP2: Send callback notification + end + ||| +end +deactivate POS_HANDLER +deactivate FULF_HANDLER +deactivate NOTIFY_HANDLER +@enduml diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.0-v1.1.svg b/docs/technical/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.0-v1.1.svg new file mode 100644 index 000000000..1a04bdb4a --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.0-v1.1.svg @@ -0,0 +1,665 @@ + + + + + + + + + + + 2.1.0. DFSP2 sends a Fulfil Success Transfer request v1.1 + + + + Financial Service Providers + + + + ML API Adapter Service + + + + Central Service + + + + + + + + + DFSP1 + + + Payer + + + + + DFSP1 + + + Payer + + + + + DFSP2 + + + Payee + + + + + DFSP2 + + + Payee + + + + + ML API Adapter + + + + + ML API Adapter + + + + + ML API Notification Event Handler + + + + + ML API Notification Event Handler + + + + + Central Service API + + + + + Central Service API + + + + + + + topic-fulfil + + + + + topic-fulfil + + + Fulfil Event Handler + + + + + Fulfil Event Handler + + + + + + + topic- + + + settlement-model + + + + + topic- + + + settlement-model + + + Settlement Model + + + Handler + + + + + Settlement Model + + + Handler + + + + + + + topic- + + + transfer-position + + + + + topic- + + + transfer-position + + + Position Handler + + + + + Position Handler + + + + + + + topic- + + + notification + + + + + topic- + + + notification + + + + + + DFSP2 sends a request for notification after tranfer is being committed in the Switch + + + + + 1 + + + Retrieve fulfilment string generated during + + + the quoting process or regenerate it using + + + Local secret + + + and + + + ILP Packet + + + as inputs + + + + + alt + + + [Send back notification reserve request] + + + + + Headers - transferHeaders: { + + + Content-Length: <Content-Length>, + + + Content-Type: <Content-Type>, + + + Date: <Date>, + + + X-Forwarded-For: <X-Forwarded-For>, + + + FSPIOP-Source: <FSPIOP-Source>, + + + FSPIOP-Destination: <FSPIOP-Destination>, + + + FSPIOP-Encryption: <FSPIOP-Encryption>, + + + FSPIOP-Signature: <FSPIOP-Signature>, + + + FSPIOP-URI: <FSPIOP-URI>, + + + FSPIOP-HTTP-Method: <FSPIOP-HTTP-Method> + + + } + + + Payload - transferMessage: + + + { + + + "fulfilment": <IlpFulfilment>, + + + "transferState": "RESERVED" + + + "extensionList": { + + + "extension": [ + + + { + + + "key": <string>, + + + "value": <string> + + + } + + + ] + + + } + + + } + + + + [Send back commit request] + + + + + Headers - transferHeaders: { + + + Content-Length: <Content-Length>, + + + Content-Type: <Content-Type>, + + + Date: <Date>, + + + X-Forwarded-For: <X-Forwarded-For>, + + + FSPIOP-Source: <FSPIOP-Source>, + + + FSPIOP-Destination: <FSPIOP-Destination>, + + + FSPIOP-Encryption: <FSPIOP-Encryption>, + + + FSPIOP-Signature: <FSPIOP-Signature>, + + + FSPIOP-URI: <FSPIOP-URI>, + + + FSPIOP-HTTP-Method: <FSPIOP-HTTP-Method> + + + } + + + Payload - transferMessage: + + + { + + + "fulfilment": <IlpFulfilment>, + + + "completedTimestamp": <DateTime>, + + + "transferState": "COMMITTED" + + + "extensionList": { + + + "extension": [ + + + { + + + "key": <string>, + + + "value": <string> + + + } + + + ] + + + } + + + } + + + + 2 + + + PUT - /transfers/<ID> + + + + + 3 + + + Validate incoming token and originator matching Payee + + + Error codes: + + + 3000-3002, 3100-3107 + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + type: fulfil, + + + action: reserve || commit, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 4 + + + Route & Publish Fulfil event for Payee + + + Error code: + + + 2003 + + + + + 5 + + + Ensure event is replicated as configured (ACKS=all) + + + Error code: + + + 2003 + + + + + 6 + + + Respond replication acknowledgements have been received + + + + + 7 + + + Respond HTTP - 200 (OK) + + + + + 8 + + + Consume message + + + + + ref + + + Fulfil Handler Consume (Success) { + + + + 2.1.1-v1.1 + + + + } + + + + + 9 + + + Produce message + + + + + 10 + + + Produce message + + + + + 11 + + + Consume message + + + + + ref + + + Settlement Model Handler Consume (Success) + + + + + 12 + + + Consume message + + + + + ref + + + Position Handler Consume (Success) + + + + + 13 + + + Produce message + + + + + 14 + + + Consume message + + + + + opt + + + [action == 'commit'] + + + + + ref + + + Send notification to Participant (Payer) + + + + + 15 + + + Send callback notification + + + + + 16 + + + Consume message + + + + + opt + + + [action == 'reserve'] + + + + + ref + + + Send notification to Participant (Payee) + + + + + 17 + + + Send callback notification + + diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.0.plantuml b/docs/technical/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.0.plantuml new file mode 100644 index 000000000..08c71eb9f --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.0.plantuml @@ -0,0 +1,174 @@ +/' + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + -------------- + '/ + + +@startuml +' declate title +title 2.1.0. DFSP2 sends a Fulfil Success Transfer request + +autonumber +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +actor "DFSP1\nPayer" as DFSP1 +actor "DFSP2\nPayee" as DFSP2 +boundary "ML API Adapter" as MLAPI +control "ML API Notification Event Handler" as NOTIFY_HANDLER +boundary "Central Service API" as CSAPI +collections "topic-fulfil" as TOPIC_FULFIL +control "Fulfil Event Handler" as FULF_HANDLER +collections "topic-\nsettlement-model" as TOPIC_SETMODEL +control "Settlement Model\nHandler" as SETMODEL_HANDLER +collections "topic-\ntransfer-position" as TOPIC_TRANSFER_POSITION +control "Position Handler" as POS_HANDLER +collections "topic-\nnotification" as TOPIC_NOTIFICATIONS + +box "Financial Service Providers" #lightGray + participant DFSP1 + participant DFSP2 +end box + +box "ML API Adapter Service" #LightBlue + participant MLAPI + participant NOTIFY_HANDLER +end box + +box "Central Service" #LightYellow + participant CSAPI + participant TOPIC_FULFIL + participant FULF_HANDLER + participant TOPIC_SETMODEL + participant SETMODEL_HANDLER + participant TOPIC_TRANSFER_POSITION + participant POS_HANDLER + participant TOPIC_NOTIFICATIONS +end box + +' start flow +activate NOTIFY_HANDLER +activate FULF_HANDLER +activate SETMODEL_HANDLER +activate POS_HANDLER +group DFSP2 sends a Fulfil Success Transfer request + DFSP2 <-> DFSP2: Retrieve fulfilment string generated during\nthe quoting process or regenerate it using\n**Local secret** and **ILP Packet** as inputs + note right of DFSP2 #yellow + Headers - transferHeaders: { + Content-Length: , + Content-Type: , + Date: , + X-Forwarded-For: , + FSPIOP-Source: , + FSPIOP-Destination: , + FSPIOP-Encryption: , + FSPIOP-Signature: , + FSPIOP-URI: , + FSPIOP-HTTP-Method: + } + + Payload - transferMessage: + { + "fulfilment": , + "completedTimestamp": , + "transferState": "COMMITTED", + "extensionList": { + "extension": [ + { + "key": , + "value": + } + ] + } + } + end note + DFSP2 ->> MLAPI: PUT - /transfers/ + activate MLAPI + MLAPI -> MLAPI: Validate incoming token and originator matching Payee\nError codes: 3000-3002, 3100-3107 + note right of MLAPI #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + type: fulfil, + action: commit, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + MLAPI -> TOPIC_FULFIL: Route & Publish Fulfil event for Payee\nError code: 2003 + activate TOPIC_FULFIL + TOPIC_FULFIL <-> TOPIC_FULFIL: Ensure event is replicated as configured (ACKS=all)\nError code: 2003 + TOPIC_FULFIL --> MLAPI: Respond replication acknowledgements have been received + deactivate TOPIC_FULFIL + MLAPI -->> DFSP2: Respond HTTP - 200 (OK) + deactivate MLAPI + TOPIC_FULFIL <- FULF_HANDLER: Consume message + ref over TOPIC_FULFIL, TOPIC_TRANSFER_POSITION: Fulfil Handler Consume (Success) {[[https://github.com/mojaloop/documentation/tree/master/mojaloop-technical-overview/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.1.svg 2.1.1]]} \n + FULF_HANDLER -> TOPIC_SETMODEL: Produce message + FULF_HANDLER -> TOPIC_TRANSFER_POSITION: Produce message + ||| + TOPIC_SETMODEL <- SETMODEL_HANDLER: Consume message + ref over TOPIC_SETMODEL, SETMODEL_HANDLER: Settlement Model Handler Consume (Success)\n + ||| + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume message + ref over TOPIC_TRANSFER_POSITION, TOPIC_NOTIFICATIONS: Position Handler Consume (Success)\n + POS_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + ||| + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message + opt action == 'commit' + ||| + ref over DFSP1, TOPIC_NOTIFICATIONS: Send notification to Participant (Payer)\n + NOTIFY_HANDLER -> DFSP1: Send callback notification + end + ||| + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message + opt action == 'commit' + ||| + ref over DFSP2, TOPIC_NOTIFICATIONS: Send notification to Participant (Payee)\n + NOTIFY_HANDLER -> DFSP2: Send callback notification + end + ||| +end +deactivate POS_HANDLER +deactivate FULF_HANDLER +deactivate NOTIFY_HANDLER +@enduml \ No newline at end of file diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.0.svg b/docs/technical/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.0.svg new file mode 100644 index 000000000..052c40891 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.0.svg @@ -0,0 +1,574 @@ + + + + + + + + + + + 2.1.0. DFSP2 sends a Fulfil Success Transfer request + + + + Financial Service Providers + + + + ML API Adapter Service + + + + Central Service + + + + + + + DFSP1 + + + Payer + + + + + DFSP1 + + + Payer + + + + + DFSP2 + + + Payee + + + + + DFSP2 + + + Payee + + + + + ML API Adapter + + + + + ML API Adapter + + + + + ML API Notification Event Handler + + + + + ML API Notification Event Handler + + + + + Central Service API + + + + + Central Service API + + + + + + + topic-fulfil + + + + + topic-fulfil + + + Fulfil Event Handler + + + + + Fulfil Event Handler + + + + + + + topic- + + + settlement-model + + + + + topic- + + + settlement-model + + + Settlement Model + + + Handler + + + + + Settlement Model + + + Handler + + + + + + + topic- + + + transfer-position + + + + + topic- + + + transfer-position + + + Position Handler + + + + + Position Handler + + + + + + + topic- + + + notification + + + + + topic- + + + notification + + + + + + DFSP2 sends a Fulfil Success Transfer request + + + + + 1 + + + Retrieve fulfilment string generated during + + + the quoting process or regenerate it using + + + Local secret + + + and + + + ILP Packet + + + as inputs + + + + + Headers - transferHeaders: { + + + Content-Length: <Content-Length>, + + + Content-Type: <Content-Type>, + + + Date: <Date>, + + + X-Forwarded-For: <X-Forwarded-For>, + + + FSPIOP-Source: <FSPIOP-Source>, + + + FSPIOP-Destination: <FSPIOP-Destination>, + + + FSPIOP-Encryption: <FSPIOP-Encryption>, + + + FSPIOP-Signature: <FSPIOP-Signature>, + + + FSPIOP-URI: <FSPIOP-URI>, + + + FSPIOP-HTTP-Method: <FSPIOP-HTTP-Method> + + + } + + + Payload - transferMessage: + + + { + + + "fulfilment": <IlpFulfilment>, + + + "completedTimestamp": <DateTime>, + + + "transferState": "COMMITTED", + + + "extensionList": { + + + "extension": [ + + + { + + + "key": <string>, + + + "value": <string> + + + } + + + ] + + + } + + + } + + + + 2 + + + PUT - /transfers/<ID> + + + + + 3 + + + Validate incoming token and originator matching Payee + + + Error codes: + + + 3000-3002, 3100-3107 + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + type: fulfil, + + + action: commit, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 4 + + + Route & Publish Fulfil event for Payee + + + Error code: + + + 2003 + + + + + 5 + + + Ensure event is replicated as configured (ACKS=all) + + + Error code: + + + 2003 + + + + + 6 + + + Respond replication acknowledgements have been received + + + + + 7 + + + Respond HTTP - 200 (OK) + + + + + 8 + + + Consume message + + + + + ref + + + Fulfil Handler Consume (Success) { + + + + 2.1.1 + + + + } + + + + + 9 + + + Produce message + + + + + 10 + + + Produce message + + + + + 11 + + + Consume message + + + + + ref + + + Settlement Model Handler Consume (Success) + + + + + 12 + + + Consume message + + + + + ref + + + Position Handler Consume (Success) + + + + + 13 + + + Produce message + + + + + 14 + + + Consume message + + + + + opt + + + [action == 'commit'] + + + + + ref + + + Send notification to Participant (Payer) + + + + + 15 + + + Send callback notification + + + + + 16 + + + Consume message + + + + + opt + + + [action == 'commit'] + + + + + ref + + + Send notification to Participant (Payee) + + + + + 17 + + + Send callback notification + + diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.1-v1.1.plantuml b/docs/technical/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.1-v1.1.plantuml new file mode 100644 index 000000000..9f2523d6d --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.1-v1.1.plantuml @@ -0,0 +1,273 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Rajiv Mothilal + * Georgi Georgiev + * Valentin Genev + -------------- + ******'/ + +@startuml +' declate title +title 2.1.1. Fulfil Handler Consume (Success) v1.1 +autonumber +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store +' declare actors +collections "topic-fulfil" as TOPIC_FULFIL +control "Fulfil Event\nHandler" as FULF_HANDLER +collections "topic-event" as TOPIC_EVENT +collections "topic-\ntransfer-position" as TOPIC_TRANSFER_POSITION +collections "topic-\nsettlement-model" as TOPIC_SETMODEL +collections "topic-\nnotification" as TOPIC_NOTIFICATIONS + +entity "Position DAO" as POS_DAO +database "Central Store" as DB +box "Central Service" #LightYellow + participant TOPIC_FULFIL + participant FULF_HANDLER + participant TOPIC_TRANSFER_POSITION + participant TOPIC_EVENT + participant TOPIC_SETMODEL + participant TOPIC_NOTIFICATIONS + participant POS_DAO + participant DB +end box +' start flow +activate FULF_HANDLER +group Fulfil Handler Consume (Success) + alt Consume Single Message + TOPIC_FULFIL <- FULF_HANDLER: Consume Fulfil event message for Payer + activate TOPIC_FULFIL + deactivate TOPIC_FULFIL + break + group Validate Event + FULF_HANDLER <-> FULF_HANDLER: Validate event - Rule: type == 'fulfil' && action IN ['commit', 'reserve']\nError codes: 2001 + end + end + group Persist Event Information + ||| + FULF_HANDLER -> TOPIC_EVENT: Publish event information + ref over FULF_HANDLER, TOPIC_EVENT: Event Handler Consume\n + ||| + end + + group Validate Duplicate Check + ||| + FULF_HANDLER -> DB: Request Duplicate Check + ref over FULF_HANDLER, DB: Request Duplicate Check\n + DB --> FULF_HANDLER: Return { hasDuplicateId: Boolean, hasDuplicateHash: Boolean } + end + + alt hasDuplicateId == TRUE && hasDuplicateHash == TRUE + break + FULF_HANDLER -> FULF_HANDLER: stateRecord = await getTransferState(transferId) + alt endStateList.includes(stateRecord.transferStateId) + ||| + ref over FULF_HANDLER, TOPIC_NOTIFICATIONS: getTransfer callback\n + FULF_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + else + note right of FULF_HANDLER #lightgrey + Ignore - resend in progress + end note + end + end + else hasDuplicateId == TRUE && hasDuplicateHash == FALSE + note right of FULF_HANDLER #lightgrey + Validate Prepare Transfer (failure) - Modified Request + end note + else hasDuplicateId == FALSE + group Validate and persist Transfer Fulfilment + FULF_HANDLER -> POS_DAO: Request information for the validate checks\nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Fetch from database + activate DB + hnote over DB #lightyellow + transfer + end note + DB --> POS_DAO + deactivate DB + FULF_HANDLER <-- POS_DAO: Return transfer + deactivate POS_DAO + FULF_HANDLER ->FULF_HANDLER: Validate that Transfer.ilpCondition = SHA-256 (content.payload.fulfilment)\nError code: 2001 + FULF_HANDLER -> FULF_HANDLER: Validate expirationDate\nError code: 3303 + + opt Transfer.ilpCondition validate successful + group Request current Settlement Window + FULF_HANDLER -> POS_DAO: Request to retrieve current/latest transfer settlement window\nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Fetch settlementWindowId + activate DB + hnote over DB #lightyellow + settlementWindow + end note + DB --> POS_DAO + deactivate DB + FULF_HANDLER <-- POS_DAO: Return settlementWindowId to be appended during transferFulfilment insert\n**TODO**: During settlement design make sure transfers in 'RECEIVED-FULFIL'\nstate are updated to the next settlement window + deactivate POS_DAO + end + end + + group Persist fulfilment + FULF_HANDLER -> POS_DAO: Persist fulfilment with the result of the above check (transferFulfilment.isValid)\nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Persist to database + activate DB + deactivate DB + hnote over DB #lightyellow + transferFulfilment + transferExtension + end note + FULF_HANDLER <-- POS_DAO: Return success + deactivate POS_DAO + end + + alt Transfer.ilpCondition validate successful + group Persist Transfer State (with transferState='RECEIVED-FULFIL') + FULF_HANDLER -> POS_DAO: Request to persist transfer state\nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Persist transfer state + activate DB + hnote over DB #lightyellow + transferStateChange + end note + deactivate DB + POS_DAO --> FULF_HANDLER: Return success + deactivate POS_DAO + end + + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: switch, + to: switch, + type: application/json + content: { + payload: { + transferId: {id} + } + }, + metadata: { + event: { + id: , + responseTo: , + type: setmodel, + action: commit, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_SETMODEL: Route & Publish settlement model event + activate TOPIC_SETMODEL + deactivate TOPIC_SETMODEL + + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: position, + action: commit || reserve, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_TRANSFER_POSITION: Route & Publish Position event for Payee + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + else Validate Fulfil Transfer not successful + group Persist Transfer State (with transferState='ABORTED') + FULF_HANDLER -> POS_DAO: Request to persist transfer state\nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Persist transfer state + activate DB + hnote over DB #lightyellow + transferStateChange + end note + deactivate DB + POS_DAO --> FULF_HANDLER: Return success + deactivate POS_DAO + end + + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: position, + action: abort, + createdAt: , + state: { + status: "error", + code: 1 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_TRANSFER_POSITION: Route & Publish Position event for Payer + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + end + end + end + else Consume Batch Messages + note left of FULF_HANDLER #lightblue + To be delivered by future story + end note + end +end +deactivate FULF_HANDLER +@enduml diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.1-v1.1.svg b/docs/technical/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.1-v1.1.svg new file mode 100644 index 000000000..9d931dc0c --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.1-v1.1.svg @@ -0,0 +1,821 @@ + + + + + + + + + + + 2.1.1. Fulfil Handler Consume (Success) v1.1 + + + + Central Service + + + + + + + + + + + + + + + + + + + + + + topic-fulfil + + + + + topic-fulfil + + + Fulfil Event + + + Handler + + + + + Fulfil Event + + + Handler + + + + + + + topic- + + + transfer-position + + + + + topic- + + + transfer-position + + + + + topic-event + + + + + topic-event + + + + + topic- + + + settlement-model + + + + + topic- + + + settlement-model + + + + + topic- + + + notification + + + + + topic- + + + notification + + + Position DAO + + + + + Position DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Fulfil Handler Consume (Success) + + + + + alt + + + [Consume Single Message] + + + + + 1 + + + Consume Fulfil event message for Payer + + + + + break + + + + + Validate Event + + + + + 2 + + + Validate event - Rule: type == 'fulfil' && action IN ['commit', 'reserve'] + + + Error codes: + + + 2001 + + + + + Persist Event Information + + + + + 3 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + Validate Duplicate Check + + + + + 4 + + + Request Duplicate Check + + + + + ref + + + Request Duplicate Check + + + + + 5 + + + Return { hasDuplicateId: Boolean, hasDuplicateHash: Boolean } + + + + + alt + + + [hasDuplicateId == TRUE && hasDuplicateHash == TRUE] + + + + + break + + + + + 6 + + + stateRecord = await getTransferState(transferId) + + + + + alt + + + [endStateList.includes(stateRecord.transferStateId)] + + + + + ref + + + getTransfer callback + + + + + 7 + + + Produce message + + + + + + Ignore - resend in progress + + + + [hasDuplicateId == TRUE && hasDuplicateHash == FALSE] + + + + + Validate Prepare Transfer (failure) - Modified Request + + + + [hasDuplicateId == FALSE] + + + + + Validate and persist Transfer Fulfilment + + + + + 8 + + + Request information for the validate checks + + + Error code: + + + 2003 + + + + + 9 + + + Fetch from database + + + + transfer + + + + + 10 + + + + + 11 + + + Return transfer + + + + + 12 + + + Validate that Transfer.ilpCondition = SHA-256 (content.payload.fulfilment) + + + Error code: + + + 2001 + + + + + 13 + + + Validate expirationDate + + + Error code: + + + 3303 + + + + + opt + + + [Transfer.ilpCondition validate successful] + + + + + Request current Settlement Window + + + + + 14 + + + Request to retrieve current/latest transfer settlement window + + + Error code: + + + 2003 + + + + + 15 + + + Fetch settlementWindowId + + + + settlementWindow + + + + + 16 + + + + + 17 + + + Return settlementWindowId to be appended during transferFulfilment insert + + + TODO + + + : During settlement design make sure transfers in 'RECEIVED-FULFIL' + + + state are updated to the next settlement window + + + + + Persist fulfilment + + + + + 18 + + + Persist fulfilment with the result of the above check (transferFulfilment.isValid) + + + Error code: + + + 2003 + + + + + 19 + + + Persist to database + + + + transferFulfilment + + + transferExtension + + + + + 20 + + + Return success + + + + + alt + + + [Transfer.ilpCondition validate successful] + + + + + Persist Transfer State (with transferState='RECEIVED-FULFIL') + + + + + 21 + + + Request to persist transfer state + + + Error code: + + + 2003 + + + + + 22 + + + Persist transfer state + + + + transferStateChange + + + + + 23 + + + Return success + + + + + Message: + + + { + + + id: <id>, + + + from: switch, + + + to: switch, + + + type: application/json + + + content: { + + + payload: { + + + transferId: {id} + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: setmodel, + + + action: commit, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 24 + + + Route & Publish settlement model event + + + + + Message: + + + { + + + id: <id>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: position, + + + action: commit || reserve, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 25 + + + Route & Publish Position event for Payee + + + + [Validate Fulfil Transfer not successful] + + + + + Persist Transfer State (with transferState='ABORTED') + + + + + 26 + + + Request to persist transfer state + + + Error code: + + + 2003 + + + + + 27 + + + Persist transfer state + + + + transferStateChange + + + + + 28 + + + Return success + + + + + Message: + + + { + + + id: <id>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: position, + + + action: abort, + + + createdAt: <timestamp>, + + + state: { + + + status: "error", + + + code: 1 + + + } + + + } + + + } + + + } + + + + + 29 + + + Route & Publish Position event for Payer + + + + [Consume Batch Messages] + + + + + To be delivered by future story + + diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.1.plantuml b/docs/technical/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.1.plantuml new file mode 100644 index 000000000..42f281ef6 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.1.plantuml @@ -0,0 +1,272 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Rajiv Mothilal + * Georgi Georgiev + -------------- + ******'/ + +@startuml +' declate title +title 2.1.1. Fulfil Handler Consume (Success) +autonumber +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store +' declare actors +collections "topic-fulfil" as TOPIC_FULFIL +control "Fulfil Event\nHandler" as FULF_HANDLER +collections "topic-event" as TOPIC_EVENT +collections "topic-\ntransfer-position" as TOPIC_TRANSFER_POSITION +collections "topic-\nsettlement-model" as TOPIC_SETMODEL +collections "topic-\nnotification" as TOPIC_NOTIFICATIONS + +entity "Position DAO" as POS_DAO +database "Central Store" as DB +box "Central Service" #LightYellow + participant TOPIC_FULFIL + participant FULF_HANDLER + participant TOPIC_TRANSFER_POSITION + participant TOPIC_EVENT + participant TOPIC_SETMODEL + participant TOPIC_NOTIFICATIONS + participant POS_DAO + participant DB +end box +' start flow +activate FULF_HANDLER +group Fulfil Handler Consume (Success) + alt Consume Single Message + TOPIC_FULFIL <- FULF_HANDLER: Consume Fulfil event message for Payer + activate TOPIC_FULFIL + deactivate TOPIC_FULFIL + break + group Validate Event + FULF_HANDLER <-> FULF_HANDLER: Validate event - Rule: type == 'fulfil' && action == 'commit'\nError codes: 2001 + end + end + group Persist Event Information + ||| + FULF_HANDLER -> TOPIC_EVENT: Publish event information + ref over FULF_HANDLER, TOPIC_EVENT: Event Handler Consume\n + ||| + end + + group Validate Duplicate Check + ||| + FULF_HANDLER -> DB: Request Duplicate Check + ref over FULF_HANDLER, DB: Request Duplicate Check\n + DB --> FULF_HANDLER: Return { hasDuplicateId: Boolean, hasDuplicateHash: Boolean } + end + + alt hasDuplicateId == TRUE && hasDuplicateHash == TRUE + break + FULF_HANDLER -> FULF_HANDLER: stateRecord = await getTransferState(transferId) + alt endStateList.includes(stateRecord.transferStateId) + ||| + ref over FULF_HANDLER, TOPIC_NOTIFICATIONS: getTransfer callback\n + FULF_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + else + note right of FULF_HANDLER #lightgrey + Ignore - resend in progress + end note + end + end + else hasDuplicateId == TRUE && hasDuplicateHash == FALSE + note right of FULF_HANDLER #lightgrey + Validate Prepare Transfer (failure) - Modified Request + end note + else hasDuplicateId == FALSE + group Validate and persist Transfer Fulfilment + FULF_HANDLER -> POS_DAO: Request information for the validate checks\nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Fetch from database + activate DB + hnote over DB #lightyellow + transfer + end note + DB --> POS_DAO + deactivate DB + FULF_HANDLER <-- POS_DAO: Return transfer + deactivate POS_DAO + FULF_HANDLER ->FULF_HANDLER: Validate that Transfer.ilpCondition = SHA-256 (content.payload.fulfilment)\nError code: 2001 + FULF_HANDLER -> FULF_HANDLER: Validate expirationDate\nError code: 3303 + + opt Transfer.ilpCondition validate successful + group Request current Settlement Window + FULF_HANDLER -> POS_DAO: Request to retrieve current/latest transfer settlement window\nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Fetch settlementWindowId + activate DB + hnote over DB #lightyellow + settlementWindow + end note + DB --> POS_DAO + deactivate DB + FULF_HANDLER <-- POS_DAO: Return settlementWindowId to be appended during transferFulfilment insert\n**TODO**: During settlement design make sure transfers in 'RECEIVED-FULFIL'\nstate are updated to the next settlement window + deactivate POS_DAO + end + end + + group Persist fulfilment + FULF_HANDLER -> POS_DAO: Persist fulfilment with the result of the above check (transferFulfilment.isValid)\nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Persist to database + activate DB + deactivate DB + hnote over DB #lightyellow + transferFulfilment + transferExtension + end note + FULF_HANDLER <-- POS_DAO: Return success + deactivate POS_DAO + end + + alt Transfer.ilpCondition validate successful + group Persist Transfer State (with transferState='RECEIVED-FULFIL') + FULF_HANDLER -> POS_DAO: Request to persist transfer state\nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Persist transfer state + activate DB + hnote over DB #lightyellow + transferStateChange + end note + deactivate DB + POS_DAO --> FULF_HANDLER: Return success + deactivate POS_DAO + end + + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: switch, + to: switch, + type: application/json + content: { + payload: { + transferId: {id} + } + }, + metadata: { + event: { + id: , + responseTo: , + type: setmodel, + action: commit, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_SETMODEL: Route & Publish settlement model event + activate TOPIC_SETMODEL + deactivate TOPIC_SETMODEL + + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: position, + action: commit, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_TRANSFER_POSITION: Route & Publish Position event for Payee + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + else Validate Fulfil Transfer not successful + group Persist Transfer State (with transferState='ABORTED') + FULF_HANDLER -> POS_DAO: Request to persist transfer state\nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Persist transfer state + activate DB + hnote over DB #lightyellow + transferStateChange + end note + deactivate DB + POS_DAO --> FULF_HANDLER: Return success + deactivate POS_DAO + end + + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: position, + action: abort, + createdAt: , + state: { + status: "error", + code: 1 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_TRANSFER_POSITION: Route & Publish Position event for Payer + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + end + end + end + else Consume Batch Messages + note left of FULF_HANDLER #lightblue + To be delivered by future story + end note + end +end +deactivate FULF_HANDLER +@enduml diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.1.svg b/docs/technical/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.1.svg new file mode 100644 index 000000000..de1888f4f --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-fulfil-2.1.1.svg @@ -0,0 +1,821 @@ + + + + + + + + + + + 2.1.1. Fulfil Handler Consume (Success) + + + + Central Service + + + + + + + + + + + + + + + + + + + + + + topic-fulfil + + + + + topic-fulfil + + + Fulfil Event + + + Handler + + + + + Fulfil Event + + + Handler + + + + + + + topic- + + + transfer-position + + + + + topic- + + + transfer-position + + + + + topic-event + + + + + topic-event + + + + + topic- + + + settlement-model + + + + + topic- + + + settlement-model + + + + + topic- + + + notification + + + + + topic- + + + notification + + + Position DAO + + + + + Position DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Fulfil Handler Consume (Success) + + + + + alt + + + [Consume Single Message] + + + + + 1 + + + Consume Fulfil event message for Payer + + + + + break + + + + + Validate Event + + + + + 2 + + + Validate event - Rule: type == 'fulfil' && action == 'commit' + + + Error codes: + + + 2001 + + + + + Persist Event Information + + + + + 3 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + Validate Duplicate Check + + + + + 4 + + + Request Duplicate Check + + + + + ref + + + Request Duplicate Check + + + + + 5 + + + Return { hasDuplicateId: Boolean, hasDuplicateHash: Boolean } + + + + + alt + + + [hasDuplicateId == TRUE && hasDuplicateHash == TRUE] + + + + + break + + + + + 6 + + + stateRecord = await getTransferState(transferId) + + + + + alt + + + [endStateList.includes(stateRecord.transferStateId)] + + + + + ref + + + getTransfer callback + + + + + 7 + + + Produce message + + + + + + Ignore - resend in progress + + + + [hasDuplicateId == TRUE && hasDuplicateHash == FALSE] + + + + + Validate Prepare Transfer (failure) - Modified Request + + + + [hasDuplicateId == FALSE] + + + + + Validate and persist Transfer Fulfilment + + + + + 8 + + + Request information for the validate checks + + + Error code: + + + 2003 + + + + + 9 + + + Fetch from database + + + + transfer + + + + + 10 + + + + + 11 + + + Return transfer + + + + + 12 + + + Validate that Transfer.ilpCondition = SHA-256 (content.payload.fulfilment) + + + Error code: + + + 2001 + + + + + 13 + + + Validate expirationDate + + + Error code: + + + 3303 + + + + + opt + + + [Transfer.ilpCondition validate successful] + + + + + Request current Settlement Window + + + + + 14 + + + Request to retrieve current/latest transfer settlement window + + + Error code: + + + 2003 + + + + + 15 + + + Fetch settlementWindowId + + + + settlementWindow + + + + + 16 + + + + + 17 + + + Return settlementWindowId to be appended during transferFulfilment insert + + + TODO + + + : During settlement design make sure transfers in 'RECEIVED-FULFIL' + + + state are updated to the next settlement window + + + + + Persist fulfilment + + + + + 18 + + + Persist fulfilment with the result of the above check (transferFulfilment.isValid) + + + Error code: + + + 2003 + + + + + 19 + + + Persist to database + + + + transferFulfilment + + + transferExtension + + + + + 20 + + + Return success + + + + + alt + + + [Transfer.ilpCondition validate successful] + + + + + Persist Transfer State (with transferState='RECEIVED-FULFIL') + + + + + 21 + + + Request to persist transfer state + + + Error code: + + + 2003 + + + + + 22 + + + Persist transfer state + + + + transferStateChange + + + + + 23 + + + Return success + + + + + Message: + + + { + + + id: <id>, + + + from: switch, + + + to: switch, + + + type: application/json + + + content: { + + + payload: { + + + transferId: {id} + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: setmodel, + + + action: commit, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 24 + + + Route & Publish settlement model event + + + + + Message: + + + { + + + id: <id>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: position, + + + action: commit, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 25 + + + Route & Publish Position event for Payee + + + + [Validate Fulfil Transfer not successful] + + + + + Persist Transfer State (with transferState='ABORTED') + + + + + 26 + + + Request to persist transfer state + + + Error code: + + + 2003 + + + + + 27 + + + Persist transfer state + + + + transferStateChange + + + + + 28 + + + Return success + + + + + Message: + + + { + + + id: <id>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: position, + + + action: abort, + + + createdAt: <timestamp>, + + + state: { + + + status: "error", + + + code: 1 + + + } + + + } + + + } + + + } + + + + + 29 + + + Route & Publish Position event for Payer + + + + [Consume Batch Messages] + + + + + To be delivered by future story + + diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-get-all-participant-limit-1.0.0.plantuml b/docs/technical/central-ledger/assets/diagrams/sequence/seq-get-all-participant-limit-1.0.0.plantuml new file mode 100644 index 000000000..d3d86084c --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-get-all-participant-limit-1.0.0.plantuml @@ -0,0 +1,111 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Shashikant Hirugade + -------------- + ******'/ + +@startuml +' declate title +title 1.0.0 Get Participant Limit Details For All Participants + +autonumber + + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +entity "HUB OPERATOR" as OPERATOR +boundary "Central Service API" as CSAPI +control "Participant Handler" as PARTICIPANT_HANDLER +entity "Central Service API" as CSAPI +entity "Participant Facade" as PARTICIPANT_DAO +database "Central Store" as DB + +box "Central Services" #LightYellow +participant CSAPI +participant PARTICIPANT_HANDLER +participant PARTICIPANT_DAO +participant DB +end box + +' start flow + +activate OPERATOR +group Get Limits for all Participants + OPERATOR -> CSAPI: Request to get Limits - GET - /participants/limits?type={typeValue}¤cy={currencyType} + activate CSAPI + CSAPI -> PARTICIPANT_HANDLER: Fetch Limits for all Participants + activate PARTICIPANT_HANDLER + PARTICIPANT_HANDLER ->PARTICIPANT_DAO: Fetch Limits for all participants with currency and type \nError code: 3000 + activate PARTICIPANT_DAO + PARTICIPANT_DAO ->DB: Fetch Limits for currencyId and type(if passed) + note right of PARTICIPANT_DAO #lightgrey + Condition: + participantCurrency.participantCurrencyId = participant.participantCurrencyId + participantLimit.isActive = 1 + participantLimit.participantCurrencyId = participantCurrency.participantCurrencyId + [ + participantLimit.participantLimitTypeId = participantLimitType.participantLimitTypeId + participantLimit.participantCurrencyId = + participantLimitType.name = + ] + end note + + activate DB + hnote over DB #lightyellow + participant + participantCurrency + participantLimit + participantLimitType + end note + DB --> PARTICIPANT_DAO: Retrieved Participant Limits for currencyId and type + deactivate DB + PARTICIPANT_DAO -->PARTICIPANT_HANDLER: Return Limits for all participants + deactivate PARTICIPANT_DAO + note right of PARTICIPANT_HANDLER #yellow + Message: + [ + { + name: + currency: , + limit: {type: , value: } + }, + { + name: + currency: , + limit: {type: , value: } + } + ] + end note + PARTICIPANT_HANDLER -->CSAPI: Return Limits for all participants \nError code: 3000 + deactivate PARTICIPANT_HANDLER + CSAPI -->OPERATOR: Return Limits for all participants \nError code: 3000 + + deactivate CSAPI + deactivate OPERATOR +end + +@enduml diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-get-all-participant-limit-1.0.0.svg b/docs/technical/central-ledger/assets/diagrams/sequence/seq-get-all-participant-limit-1.0.0.svg new file mode 100644 index 000000000..3f24665cc --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-get-all-participant-limit-1.0.0.svg @@ -0,0 +1,241 @@ + + + + + + + + + + + 1.0.0 Get Participant Limit Details For All Participants + + + + Central Services + + + + + + HUB OPERATOR + + + + + HUB OPERATOR + + + + + Central Service API + + + + + Central Service API + + + + + Participant Handler + + + + + Participant Handler + + + + + Participant Facade + + + + + Participant Facade + + + + + Central Store + + + + + Central Store + + + + + + + + Get Limits for all Participants + + + + + 1 + + + Request to get Limits - GET - /participants/limits?type={typeValue}&currency={currencyType} + + + + + 2 + + + Fetch Limits for all Participants + + + + + 3 + + + Fetch Limits for all participants with currency and type + + + Error code: + + + 3000 + + + + + 4 + + + Fetch Limits for currencyId and type(if passed) + + + + + Condition: + + + participantCurrency.participantCurrencyId = participant.participantCurrencyId + + + participantLimit.isActive = 1 + + + participantLimit.participantCurrencyId = participantCurrency.participantCurrencyId + + + [ + + + participantLimit.participantLimitTypeId = participantLimitType.participantLimitTypeId + + + participantLimit.participantCurrencyId = <currencyId> + + + participantLimitType.name = <type> + + + ] + + + + participant + + + participantCurrency + + + participantLimit + + + participantLimitType + + + + + 5 + + + Retrieved Participant Limits for currencyId and type + + + + + 6 + + + Return Limits for all participants + + + + + Message: + + + [ + + + { + + + name: <fsp> + + + currency: <currencyId>, + + + limit: {type: <type>, value: <value>} + + + }, + + + { + + + name: <fsp> + + + currency: <currencyId>, + + + limit: {type: <type>, value: <value>} + + + } + + + ] + + + + + 7 + + + Return Limits for all participants + + + Error code: + + + 3000 + + + + + 8 + + + Return Limits for all participants + + + Error code: + + + 3000 + + diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-get-health-1.0.0.plantuml b/docs/technical/central-ledger/assets/diagrams/sequence/seq-get-health-1.0.0.plantuml new file mode 100644 index 000000000..b8a7ba51b --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-get-health-1.0.0.plantuml @@ -0,0 +1,203 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Lewis Daly + -------------- + ******'/ + + +@startuml +' declare title +title 1.0.0 Get Health Check + +autonumber + + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +entity "HUB OPERATOR" as OPERATOR +boundary "Central Service API" as CSAPI +control "Metadata Handler" as METADATA_HANDLER +entity "Central Service API" as CSAPI +database "Central Store" as DB +collections "Kafka Store" as KAFKA +collections "Logging Sidecar" as SIDECAR + +box "Central Services" #LightYellow +participant CSAPI +participant METADATA_HANDLER +participant DB +participant KAFKA +participant SIDECAR +end box + +' start flow + +activate OPERATOR +group Get Detailed Health Check + OPERATOR -> CSAPI: Request to getHealth - GET /health?detailed=true + activate CSAPI + + CSAPI -> METADATA_HANDLER: Fetch health status for all sub services + activate METADATA_HANDLER + + METADATA_HANDLER -> METADATA_HANDLER: Fetch Service Metadata + note right of METADATA_HANDLER #yellow + - versionNumber + - uptime + - time service started + end note + + + METADATA_HANDLER -> DB: Check connection status + activate DB + DB --> METADATA_HANDLER: Report connection status + deactivate DB + + + METADATA_HANDLER -> KAFKA: Check connection status + activate KAFKA + KAFKA --> METADATA_HANDLER: Report connection status + deactivate KAFKA + + + METADATA_HANDLER -> SIDECAR: Check connection status + activate SIDECAR + SIDECAR --> METADATA_HANDLER: Report connection status + deactivate SIDECAR + + alt Validate Status (success) + METADATA_HANDLER --> CSAPI: Return status response + deactivate METADATA_HANDLER + note right of OPERATOR #yellow + **Example Message:** + ""200 Success"" + { + "status": "UP", + "uptime": 1234, + "started": "2019-05-31T05:09:25.409Z", + "versionNumber": "5.2.3", + "services": [ + { + "name": "kafka", + "status": "UP", + "latency": 10 + } + ] + } + end note + + CSAPI --> OPERATOR: Return HTTP Status: 200 + + deactivate CSAPI + deactivate OPERATOR + end + + alt Validate Status (service failure) + METADATA_HANDLER --> CSAPI: Return status response + deactivate METADATA_HANDLER + note right of OPERATOR #yellow + **Example Message:** + ""502 Bad Gateway"" + { + "status": "DOWN", + "uptime": 1234, + "started": "2019-05-31T05:09:25.409Z", + "versionNumber": "5.2.3", + "services": [ + { + "name": "kafka", + "status": "DOWN", + "latency": 1111111 + } + ] + } + end note + + CSAPI --> OPERATOR: Return HTTP Status: 502 + + deactivate CSAPI + deactivate OPERATOR + + + end + + +' group Get Limits for all Participants +' OPERATOR -> CSAPI: Request to get Limits - GET - /participants/limits?type={typeValue}¤cy={currencyType} +' activate CSAPI +' CSAPI -> PARTICIPANT_HANDLER: Fetch Limits for all Participants +' activate PARTICIPANT_HANDLER +' PARTICIPANT_HANDLER ->PARTICIPANT_DAO: Fetch Limits for all participants with currency and type \nError code: 3000 +' activate PARTICIPANT_DAO +' PARTICIPANT_DAO ->DB: Fetch Limits for currencyId and type(if passed) +' note right of PARTICIPANT_DAO #lightgrey +' Condition: +' participantCurrency.participantCurrencyId = participant.participantCurrencyId +' participantLimit.isActive = 1 +' participantLimit.participantCurrencyId = participantCurrency.participantCurrencyId +' [ +' participantLimit.participantLimitTypeId = participantLimitType.participantLimitTypeId +' participantLimit.participantCurrencyId = +' participantLimitType.name = +' ] +' end note + +' activate DB +' hnote over DB #lightyellow +' participant +' participantCurrency +' participantLimit +' participantLimitType +' end note +' DB --> PARTICIPANT_DAO: Retrieved Participant Limits for currencyId and type +' deactivate DB +' PARTICIPANT_DAO -->PARTICIPANT_HANDLER: Return Limits for all participants +' deactivate PARTICIPANT_DAO +' note right of PARTICIPANT_HANDLER #yellow +' Message: +' [ +' { +' name: +' currency: , +' limit: {type: , value: } +' }, +' { +' name: +' currency: , +' limit: {type: , value: } +' } +' ] +' end note +' PARTICIPANT_HANDLER -->CSAPI: Return Limits for all participants \nError code: 3000 +' deactivate PARTICIPANT_HANDLER +' CSAPI -->OPERATOR: Return Limits for all participants \nError code: 3000 + +' deactivate CSAPI +' deactivate OPERATOR +end + +@enduml diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-get-health-1.0.0.svg b/docs/technical/central-ledger/assets/diagrams/sequence/seq-get-health-1.0.0.svg new file mode 100644 index 000000000..aff440cd5 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-get-health-1.0.0.svg @@ -0,0 +1,324 @@ + + + + + + + + + + + 1.0.0 Get Health Check + + + + Central Services + + + + + + + HUB OPERATOR + + + + + HUB OPERATOR + + + + + Central Service API + + + + + Central Service API + + + + + Metadata Handler + + + + + Metadata Handler + + + + + Central Store + + + + + Central Store + + + + + + + Kafka Store + + + + + Kafka Store + + + + + Logging Sidecar + + + + + Logging Sidecar + + + + + + Get Detailed Health Check + + + + + 1 + + + Request to getHealth - GET /health?detailed=true + + + + + 2 + + + Fetch health status for all sub services + + + + + 3 + + + Fetch Service Metadata + + + + + - versionNumber + + + - uptime + + + - time service started + + + + + 4 + + + Check connection status + + + + + 5 + + + Report connection status + + + + + 6 + + + Check connection status + + + + + 7 + + + Report connection status + + + + + 8 + + + Check connection status + + + + + 9 + + + Report connection status + + + + + alt + + + [Validate Status (success)] + + + + + 10 + + + Return status response + + + + + Example Message: + + + 200 Success + + + { + + + "status": "UP", + + + "uptime": 1234, + + + "started": "2019-05-31T05:09:25.409Z", + + + "versionNumber": "5.2.3", + + + "services": [ + + + { + + + "name": "kafka", + + + "status": "UP", + + + "latency": 10 + + + } + + + ] + + + } + + + + + 11 + + + Return + + + HTTP Status: + + + 200 + + + + + alt + + + [Validate Status (service failure)] + + + + + 12 + + + Return status response + + + + + Example Message: + + + 502 Bad Gateway + + + { + + + "status": "DOWN", + + + "uptime": 1234, + + + "started": "2019-05-31T05:09:25.409Z", + + + "versionNumber": "5.2.3", + + + "services": [ + + + { + + + "name": "kafka", + + + "status": "DOWN", + + + "latency": 1111111 + + + } + + + ] + + + } + + + + + 13 + + + Return + + + HTTP Status: + + + 502 + + diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-get-participant-position-limit-1.1.0.plantuml b/docs/technical/central-ledger/assets/diagrams/sequence/seq-get-participant-position-limit-1.1.0.plantuml new file mode 100644 index 000000000..0c0fbfff9 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-get-participant-position-limit-1.1.0.plantuml @@ -0,0 +1,206 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Shashikant Hirugade + -------------- + ******'/ + +@startuml +' declate title +title 1.1.0 Request Participant Position and Limit Details + +autonumber + + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +entity "HUB OPERATOR" as OPERATOR +boundary "Central Service API" as CSAPI +control "Participant Handler" as PARTICIPANT_HANDLER +entity "Central Service API" as CSAPI +entity "Participant Facade" as PARTICIPANT_DAO +database "Central Store" as DB + +box "Central Services" #LightYellow +participant CSAPI +participant PARTICIPANT_HANDLER +participant PARTICIPANT_DAO +participant DB +end box + +' start flow + +activate OPERATOR +group Get Callback Details + OPERATOR -> CSAPI: Request to get Limits - GET - /participants/{name}/limits?type={typeValue}¤cy={currencyValue} + activate CSAPI + CSAPI -> PARTICIPANT_HANDLER: Fetch Limits for Participant + activate PARTICIPANT_HANDLER + PARTICIPANT_HANDLER -> PARTICIPANT_HANDLER: check if "currency" parameter is sent + alt Check if "currency" parameter is sent (Sent) + PARTICIPANT_HANDLER ->PARTICIPANT_DAO: Fetch Participant/currency id \nError code: 3200 + + activate PARTICIPANT_DAO + PARTICIPANT_DAO ->DB: Fetch Participant/currency id + activate DB + hnote over DB #lightyellow + participant + participantCurrency + end note + DB --> PARTICIPANT_DAO: Retrieved Participant + deactivate DB + PARTICIPANT_DAO -->PARTICIPANT_HANDLER: Return Participant/currency id + deactivate PARTICIPANT_DAO + PARTICIPANT_HANDLER ->PARTICIPANT_HANDLER: Validate DFSP + alt Validate participant (success) + PARTICIPANT_HANDLER ->PARTICIPANT_DAO: Fetch Participant Limits for currency and type \nError code: 3000 + activate PARTICIPANT_DAO + PARTICIPANT_DAO ->DB: Fetch Participant Limit for currencyId and type(if passed) + note right of PARTICIPANT_DAO #lightgrey + Condition: + participantLimit.isActive = 1 + participantLimit.participantCurrencyId = + [ participantLimit.participantLimitTypeId = participantLimitType.participantLimitTypeId + participantLimitType.name = + ] + end note + + activate DB + hnote over DB #lightyellow + participantLimit + participantLimitType + end note + DB --> PARTICIPANT_DAO: Retrieved Participant Limits for currencyId and type + deactivate DB + PARTICIPANT_DAO -->PARTICIPANT_HANDLER: Return Participant Limits for currencyId and type + deactivate PARTICIPANT_DAO + note right of PARTICIPANT_HANDLER #yellow + Message: + [ + { currency: , + limit: {type: , value: } + } + ] + end note + PARTICIPANT_HANDLER -->CSAPI: Return Participant Limits + deactivate PARTICIPANT_HANDLER + CSAPI -->OPERATOR: Return Participant Limits + + + else Validate participant (failure)/ Error + activate PARTICIPANT_HANDLER + note right of PARTICIPANT_HANDLER #red: Validation failure/ Error! + activate PARTICIPANT_HANDLER + note right of PARTICIPANT_HANDLER #yellow + Message: + { + "errorInformation": { + "errorCode": , + "errorDescription": , + } + } + end note + PARTICIPANT_HANDLER -->CSAPI: Return Error code: 3000, 3200 + deactivate PARTICIPANT_HANDLER + CSAPI -->OPERATOR: Return Error code: 3000, 3200 + end + + else Check if "currency" parameter is sent (Not Sent) + PARTICIPANT_HANDLER ->PARTICIPANT_DAO: Fetch Participant \nError code: 3200 + + activate PARTICIPANT_DAO + PARTICIPANT_DAO ->DB: Fetch Participant + activate DB + hnote over DB #lightyellow + participant + end note + DB --> PARTICIPANT_DAO: Retrieved Participant + deactivate DB + PARTICIPANT_DAO -->PARTICIPANT_HANDLER: Return Participant + deactivate PARTICIPANT_DAO + PARTICIPANT_HANDLER ->PARTICIPANT_HANDLER: Validate DFSP + alt Validate participant (success) + PARTICIPANT_HANDLER ->PARTICIPANT_DAO: Fetch Participant Limits for all currencies and type \nError code: 3000 + activate PARTICIPANT_DAO + PARTICIPANT_DAO ->DB: Fetch Participant Limit for all currencies and type(if passed) + note right of PARTICIPANT_DAO #lightgrey + Condition: + participantCurrency.participantId = + participantLimit.participantCurrencyId = participantCurrency.participantCurrencyId + participantLimit.isActive = 1 + [ participantLimit.participantLimitTypeId = participantLimitType.participantLimitTypeId + participantLimitType.name = + ] + end note + + activate DB + hnote over DB #lightyellow + participantCurrency + participantLimit + participantLimitType + end note + DB --> PARTICIPANT_DAO: Retrieved Participant Limits for all currencies and type + deactivate DB + PARTICIPANT_DAO -->PARTICIPANT_HANDLER: Return Participant Limits for all currencies and type + deactivate PARTICIPANT_DAO + note right of PARTICIPANT_HANDLER #yellow + Message: + [ + { currency: , + limit: {type: , value: } + } + ] + end note + PARTICIPANT_HANDLER -->CSAPI: Return Participant Limits + deactivate PARTICIPANT_HANDLER + CSAPI -->OPERATOR: Return Participant Limits + + + else Validate participant (failure)/ Error + activate PARTICIPANT_HANDLER + note right of PARTICIPANT_HANDLER #red: Validation failure/ Error! + activate PARTICIPANT_HANDLER + note right of PARTICIPANT_HANDLER #yellow + Message: + { + "errorInformation": { + "errorCode": , + "errorDescription": , + } + } + end note + PARTICIPANT_HANDLER -->CSAPI: Return Error code: 3000, 3200 + deactivate PARTICIPANT_HANDLER + CSAPI -->OPERATOR: Return Error code: 3000, 3200 + end + end + + + deactivate CSAPI + deactivate OPERATOR +end + +@enduml diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-get-participant-position-limit-1.1.0.svg b/docs/technical/central-ledger/assets/diagrams/sequence/seq-get-participant-position-limit-1.1.0.svg new file mode 100644 index 000000000..e017a501e --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-get-participant-position-limit-1.1.0.svg @@ -0,0 +1,568 @@ + + + + + + + + + + + 1.1.0 Request Participant Position and Limit Details + + + + Central Services + + + + + + + + + + + + + HUB OPERATOR + + + + + HUB OPERATOR + + + + + Central Service API + + + + + Central Service API + + + + + Participant Handler + + + + + Participant Handler + + + + + Participant Facade + + + + + Participant Facade + + + + + Central Store + + + + + Central Store + + + + + + + + + + Get Callback Details + + + + + 1 + + + Request to get Limits - GET - /participants/{name}/limits?type={typeValue}&currency={currencyValue} + + + + + 2 + + + Fetch Limits for Participant + + + + + 3 + + + check if "currency" parameter is sent + + + + + alt + + + [Check if "currency" parameter is sent (Sent)] + + + + + 4 + + + Fetch Participant/currency id + + + Error code: + + + 3200 + + + + + 5 + + + Fetch Participant/currency id + + + + participant + + + participantCurrency + + + + + 6 + + + Retrieved Participant + + + + + 7 + + + Return Participant/currency id + + + + + 8 + + + Validate DFSP + + + + + alt + + + [Validate participant (success)] + + + + + 9 + + + Fetch Participant Limits for currency and type + + + Error code: + + + 3000 + + + + + 10 + + + Fetch Participant Limit for currencyId and type(if passed) + + + + + Condition: + + + participantLimit.isActive = 1 + + + participantLimit.participantCurrencyId = <currencyId> + + + [ participantLimit.participantLimitTypeId = participantLimitType.participantLimitTypeId + + + participantLimitType.name = <type> + + + ] + + + + participantLimit + + + participantLimitType + + + + + 11 + + + Retrieved Participant Limits for currencyId and type + + + + + 12 + + + Return Participant Limits for currencyId and type + + + + + Message: + + + [ + + + { currency: <currencyId>, + + + limit: {type: <type>, value: <value>} + + + } + + + ] + + + + + 13 + + + Return Participant Limits + + + + + 14 + + + Return Participant Limits + + + + [Validate participant (failure)/ Error] + + + + + Validation failure/ Error! + + + + + Message: + + + { + + + "errorInformation": { + + + "errorCode": <errorCode>, + + + "errorDescription": <ErrorMessage>, + + + } + + + } + + + + + 15 + + + Return + + + Error code: + + + 3000, 3200 + + + + + 16 + + + Return + + + Error code: + + + 3000, 3200 + + + + [Check if "currency" parameter is sent (Not Sent)] + + + + + 17 + + + Fetch Participant + + + Error code: + + + 3200 + + + + + 18 + + + Fetch Participant + + + + participant + + + + + 19 + + + Retrieved Participant + + + + + 20 + + + Return Participant + + + + + 21 + + + Validate DFSP + + + + + alt + + + [Validate participant (success)] + + + + + 22 + + + Fetch Participant Limits for all currencies and type + + + Error code: + + + 3000 + + + + + 23 + + + Fetch Participant Limit for all currencies and type(if passed) + + + + + Condition: + + + participantCurrency.participantId = <participantId> + + + participantLimit.participantCurrencyId = participantCurrency.participantCurrencyId + + + participantLimit.isActive = 1 + + + [ participantLimit.participantLimitTypeId = participantLimitType.participantLimitTypeId + + + participantLimitType.name = <type> + + + ] + + + + participantCurrency + + + participantLimit + + + participantLimitType + + + + + 24 + + + Retrieved Participant Limits for all currencies and type + + + + + 25 + + + Return Participant Limits for all currencies and type + + + + + Message: + + + [ + + + { currency: <currencyId>, + + + limit: {type: <type>, value: <value>} + + + } + + + ] + + + + + 26 + + + Return Participant Limits + + + + + 27 + + + Return Participant Limits + + + + [Validate participant (failure)/ Error] + + + + + Validation failure/ Error! + + + + + Message: + + + { + + + "errorInformation": { + + + "errorCode": <errorCode>, + + + "errorDescription": <ErrorMessage>, + + + } + + + } + + + + + 28 + + + Return + + + Error code: + + + 3000, 3200 + + + + + 29 + + + Return + + + Error code: + + + 3000, 3200 + + diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-get-transfer-1.1.5-phase2.plantuml b/docs/technical/central-ledger/assets/diagrams/sequence/seq-get-transfer-1.1.5-phase2.plantuml new file mode 100644 index 000000000..06f4689fb --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-get-transfer-1.1.5-phase2.plantuml @@ -0,0 +1,167 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Samuel Kummary + -------------- + ******'/ + +@startuml +' declate title +title 1.1.5. Request transfer status (getTransferStatusById) - Phase2 version + +autonumber + +' declare actors +actor "DFSP(n)\nParticipant" as DFSP +control "ML API Notification Event Handler" as NOTIFY_HANDLER +boundary "Central Service API" as CSAPI +collections "Event-Topic" as TOPIC_EVENTS +entity "Transfer-DAO" as TRANSFER_DAO +database "Central Store" as DB + +box "Financial Service Provider" #lightGray + participant DFSP +end box + +box "ML API Adapter Service" #LightBlue + participant NOTIFY_HANDLER +end box + +box "Central Service" #LightYellow + participant CSAPI + participant TOPIC_EVENTS + participant TRANSFER_DAO + participant DB +end box + +' start flow +group Request transfer status + activate DFSP + DFSP -> NOTIFY_HANDLER: Callback transfer status request URL - GET - /transfers/{ID} +'alt invalid tansferId +' activate NOTIFY_HANDLER +' NOTIFY_HANDLER -> NOTIFY_HANDLER: Validate TransferId +' break +' note right of NOTIFY_HANDLER #yellow +' { +' "errorInformation": { +' "errorCode": , +' "errorDescription": "Invalid payload or state" +' } +' } +' end note +' DFSP <-- NOTIFY_HANDLER: Respond HTTP - 4xx (Bad Request) +' end +'else valid transfer + ||| + group Persist Event Information +' hnote over NOTIFY_HANDLER #Pink +' Do we need to write the event to the Event-Topic? +' Not transaction related. +' end hnote + NOTIFY_HANDLER -> CSAPI: Request transfer information - GET - /transfers/{ID} + activate CSAPI + + activate TOPIC_EVENTS + CSAPI -> TOPIC_EVENTS: Publish event information + ||| + ref over TOPIC_EVENTS : Event Handler Consume\n + ||| + CSAPI <-- TOPIC_EVENTS: Return success + deactivate TOPIC_EVENTS + CSAPI --> NOTIFY_HANDLER: Return success + deactivate CSAPI + end + DFSP <-- NOTIFY_HANDLER: Respond HTTP - 200 (OK) +'end + NOTIFY_HANDLER -> CSAPI: Request details for Transfer - GET - /transfers/{ID}\nError code: 2003 + activate CSAPI + CSAPI -> TRANSFER_DAO: Request transfer status\nError code: 2003 + activate TRANSFER_DAO + TRANSFER_DAO -> DB: Fetch transfer status + activate DB + hnote over DB #lightyellow + SELECT transferId, transferStateId + FROM **transferStateChange** + WHERE transferId = {ID} + ORDER BY transferStateChangeId desc limit 1 + end note + deactivate DB + CSAPI <-- TRANSFER_DAO: Return transfer status + deactivate TRANSFER_DAO + NOTIFY_HANDLER <-- CSAPI: Return transfer status\nError codes: 3202, 3203 + deactivate CSAPI + + alt Is there a transfer with the given ID recorded in the system? + alt Yes AND transferState is COMMITTED \nThis implies that a succesful transfer with the given ID is recorded in the system + note left of NOTIFY_HANDLER #yellow + { + "fulfilment": "WLctttbu2HvTsa1XWvUoGRcQozHsqeu9Ahl2JW9Bsu8", + "completedTimestamp": "2018-09-24T08:38:08.699-04:00", + "transferState": "COMMITTED", + extensionList: + { + extension: + [ + { + "key": "Description", + "value": "This is a more detailed description" + } + ] + } + } + end note + DFSP <- NOTIFY_HANDLER: callback PUT on /transfers/{ID} + else transferState in [RECEIVED, RESERVED, ABORTED] + note left of NOTIFY_HANDLER #yellow + { + "transferState": "RECEIVED", + extensionList: + { + extension: + [ + { + "key": "Description", + "value": "This is a more detailed description" + } + ] + } + } + end note + DFSP <- NOTIFY_HANDLER: callback PUT on /transfers/{ID} + end + note right of NOTIFY_HANDLER #lightgray + Log ERROR event + end note + else A transfer with the given ID is not present in the System or this is an invalid request + note left of NOTIFY_HANDLER #yellow + { + "errorInformation": { + "errorCode": , + "errorDescription": "Client error description" + } + } + end note + DFSP <- NOTIFY_HANDLER: callback PUT on /transfers/{ID}/error + end + deactivate NOTIFY_HANDLER +deactivate DFSP +end +@enduml diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-get-transfer-1.1.5-phase2.svg b/docs/technical/central-ledger/assets/diagrams/sequence/seq-get-transfer-1.1.5-phase2.svg new file mode 100644 index 000000000..8ad873bd3 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-get-transfer-1.1.5-phase2.svg @@ -0,0 +1,402 @@ + + + + + + + + + + + 1.1.5. Request transfer status (getTransferStatusById) - Phase2 version + + + + Financial Service Provider + + + + ML API Adapter Service + + + + Central Service + + + + + + + + + DFSP(n) + + + Participant + + + + + DFSP(n) + + + Participant + + + + + ML API Notification Event Handler + + + + + ML API Notification Event Handler + + + + + Central Service API + + + + + Central Service API + + + + + + + Event-Topic + + + + + Event-Topic + + + Transfer-DAO + + + + + Transfer-DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Request transfer status + + + + + 1 + + + Callback transfer status request URL - GET - /transfers/{ID} + + + + + Persist Event Information + + + + + 2 + + + Request transfer information - GET - /transfers/{ID} + + + + + 3 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + 4 + + + Return success + + + + + 5 + + + Return success + + + + + 6 + + + Respond HTTP - 200 (OK) + + + + + 7 + + + Request details for Transfer - GET - /transfers/{ID} + + + Error code: + + + 2003 + + + + + 8 + + + Request transfer status + + + Error code: + + + 2003 + + + + + 9 + + + Fetch transfer status + + + + SELECT transferId, transferStateId + + + FROM + + + transferStateChange + + + WHERE transferId = {ID} + + + ORDER BY transferStateChangeId desc limit 1 + + + + + 10 + + + Return transfer status + + + + + 11 + + + Return transfer status + + + Error codes: + + + 3202, 3203 + + + + + alt + + + [Is there a transfer with the given ID recorded in the system?] + + + + + alt + + + [Yes AND transferState is COMMITTED + + + This implies that a succesful transfer with the given ID is recorded in the system] + + + + + { + + + "fulfilment": "WLctttbu2HvTsa1XWvUoGRcQozHsqeu9Ahl2JW9Bsu8", + + + "completedTimestamp": "2018-09-24T08:38:08.699-04:00", + + + "transferState": "COMMITTED", + + + extensionList: + + + { + + + extension: + + + [ + + + { + + + "key": "Description", + + + "value": "This is a more detailed description" + + + } + + + ] + + + } + + + } + + + + + 12 + + + callback PUT on /transfers/{ID} + + + + [transferState in [RECEIVED, RESERVED, ABORTED]] + + + + + { + + + "transferState": "RECEIVED", + + + extensionList: + + + { + + + extension: + + + [ + + + { + + + "key": "Description", + + + "value": "This is a more detailed description" + + + } + + + ] + + + } + + + } + + + + + 13 + + + callback PUT on /transfers/{ID} + + + + + Log ERROR event + + + + [A transfer with the given ID is not present in the System or this is an invalid request] + + + + + { + + + "errorInformation": { + + + "errorCode": <integer>, + + + "errorDescription": "Client error description" + + + } + + + } + + + + + 14 + + + callback PUT on /transfers/{ID}/error + + diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-manage-participant-limit-1.1.0.plantuml b/docs/technical/central-ledger/assets/diagrams/sequence/seq-manage-participant-limit-1.1.0.plantuml new file mode 100644 index 000000000..0d42f4d94 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-manage-participant-limit-1.1.0.plantuml @@ -0,0 +1,174 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Samuel Kummary + * Shashikant Hirugade + -------------- + ******'/ + +@startuml +' declare title +title 1.1.0 Manage Participant Limits + +autonumber + +' declare actors +actor "HUB OPERATOR" as OPERATOR +boundary "Central Service API" as CSAPI +control "Participant Handler" as PARTICIPANT_HANDLER +entity "Central Service API" as CSAPI +entity "Participant DAO" as PARTICIPANT_DAO +database "Central Store" as DB + +box "Central Services" #LightYellow +participant PARTICIPANT_HANDLER +participant PARTICIPANT_DAO +participant DB +end box + +' start flow + +activate OPERATOR +group Manage Net Debit Cap + OPERATOR -> CSAPI: Request to adjust Participant Limit for a certain Currency - POST - /participants/{name}/limits + note right of OPERATOR #yellow + Message: + { + payload: { + currency: , + limit: { + type: , + value: + } + } + } + end note + + activate CSAPI + CSAPI -> PARTICIPANT_HANDLER: Adjust Limit for Participant + activate PARTICIPANT_HANDLER + PARTICIPANT_HANDLER ->PARTICIPANT_DAO: Fetch Participant/currency \nError code: 3200 + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Fetch Participant/currency + activate DB + hnote over DB #lightyellow + participant + participantCurrency + end note + DB --> PARTICIPANT_DAO: Retrieved Participant/currency + deactivate DB + PARTICIPANT_DAO --> PARTICIPANT_HANDLER: Return Participant/currency + deactivate PARTICIPANT_DAO + PARTICIPANT_HANDLER -> PARTICIPANT_HANDLER: Validate DFSP + alt Validate participant (success) + PARTICIPANT_HANDLER ->PARTICIPANT_DAO: (for ParticipantCurrency) Fetch ParticipantLimit \nError code: 3200 + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Fetch ParticipantLimit + activate DB + hnote over DB #lightyellow + participantLimit + end note + DB --> PARTICIPANT_DAO: Retrieved ParticipantLimit + deactivate DB + PARTICIPANT_DAO --> PARTICIPANT_HANDLER: Return ParticipantLimit + deactivate PARTICIPANT_DAO + PARTICIPANT_HANDLER -> PARTICIPANT_HANDLER: Validate ParticipantLimit + alt Validate participantLimit (success) + Group DB TRANSACTION IMPLEMENTATION - Lock on ParticipantLimit table with UPDATE + note right of PARTICIPANT_DAO #lightgrey + If (record exists && isActive = 1) + oldIsActive.isActive = 0 + insert Record + Else + insert Record + End + + end note + + PARTICIPANT_HANDLER ->PARTICIPANT_DAO: (for ParticipantLimit) Insert new ParticipantLimit \nError code: 3200 + + activate PARTICIPANT_DAO + + PARTICIPANT_DAO -> DB: Insert ParticipantLimit + activate DB + hnote over DB #lightyellow + participantLimit + end note + DB --> PARTICIPANT_DAO: Inserted ParticipantLimit + deactivate DB + PARTICIPANT_DAO --> PARTICIPANT_HANDLER: Return ParticipantLimit + + + deactivate PARTICIPANT_DAO + ' Release Lock on ParticipantLimit table + End + + else Validate participantLimit (failure) + note right of PARTICIPANT_HANDLER #red: Validation failure! + + note right of PARTICIPANT_HANDLER #yellow + Message: + { + "errorInformation": { + "errorCode": 3200, + "errorDescription": "ParticipantLimit Not Found", + } + } + end note + end + PARTICIPANT_HANDLER --> CSAPI: Return new Limit values and status 200 + note right of PARTICIPANT_HANDLER #yellow + Message: + { + "currency": "EUR", + "limit": { + "participantLimitId": , + "participantLimitTypeId": , + "type": , + "value": , + "isActive": 1 + } + } + end note + CSAPI --> OPERATOR: Return new Limit values and status 200 + + else Validate participant (failure) + note right of PARTICIPANT_HANDLER #red: Validation failure! + + note right of PARTICIPANT_HANDLER #yellow + Message: + { + "errorInformation": { + "errorCode": 3200, + "errorDescription": "FSP id Not Found", + } + } + end note + + end + PARTICIPANT_HANDLER -->CSAPI: Return Error code: 3200 + deactivate PARTICIPANT_HANDLER + CSAPI -->OPERATOR: Return Error code: 3200 + + deactivate PARTICIPANT_HANDLER + deactivate CSAPI + deactivate OPERATOR +end +@enduml \ No newline at end of file diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-manage-participant-limit-1.1.0.svg b/docs/technical/central-ledger/assets/diagrams/sequence/seq-manage-participant-limit-1.1.0.svg new file mode 100644 index 000000000..a640cdb01 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-manage-participant-limit-1.1.0.svg @@ -0,0 +1,457 @@ + + + + + + + + + + + 1.1.0 Manage Participant Limits + + + + Central Services + + + + + + + + + + HUB OPERATOR + + + + + HUB OPERATOR + + + + + Central Service API + + + + + Central Service API + + + + + Participant Handler + + + + + Participant Handler + + + + + Participant DAO + + + + + Participant DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Manage Net Debit Cap + + + + + 1 + + + Request to adjust Participant Limit for a certain Currency - POST - /participants/{name}/limits + + + + + Message: + + + { + + + payload: { + + + currency: <string>, + + + limit: { + + + type: <string>, + + + value: <Id> + + + } + + + } + + + } + + + + + 2 + + + Adjust Limit for Participant + + + + + 3 + + + Fetch Participant/currency + + + Error code: + + + 3200 + + + + + 4 + + + Fetch Participant/currency + + + + participant + + + participantCurrency + + + + + 5 + + + Retrieved Participant/currency + + + + + 6 + + + Return Participant/currency + + + + + 7 + + + Validate DFSP + + + + + alt + + + [Validate participant (success)] + + + + + 8 + + + (for ParticipantCurrency) Fetch ParticipantLimit + + + Error code: + + + 3200 + + + + + 9 + + + Fetch ParticipantLimit + + + + participantLimit + + + + + 10 + + + Retrieved ParticipantLimit + + + + + 11 + + + Return ParticipantLimit + + + + + 12 + + + Validate ParticipantLimit + + + + + alt + + + [Validate participantLimit (success)] + + + + + DB TRANSACTION IMPLEMENTATION - Lock on ParticipantLimit table with UPDATE + + + + + If (record exists && isActive = 1) + + + oldIsActive.isActive = 0 + + + insert Record + + + Else + + + insert Record + + + End + + + + + 13 + + + (for ParticipantLimit) Insert new ParticipantLimit + + + Error code: + + + 3200 + + + + + 14 + + + Insert ParticipantLimit + + + + participantLimit + + + + + 15 + + + Inserted ParticipantLimit + + + + + 16 + + + Return ParticipantLimit + + + + [Validate participantLimit (failure)] + + + + + Validation failure! + + + + + Message: + + + { + + + "errorInformation": { + + + "errorCode": 3200, + + + "errorDescription": "ParticipantLimit Not Found", + + + } + + + } + + + + + 17 + + + Return new Limit values and status 200 + + + + + Message: + + + { + + + "currency": "EUR", + + + "limit": { + + + "participantLimitId": <number>, + + + "participantLimitTypeId": <number>, + + + "type": <string>, + + + "value": <string>, + + + "isActive": 1 + + + } + + + } + + + + + 18 + + + Return new Limit values and status 200 + + + + [Validate participant (failure)] + + + + + Validation failure! + + + + + Message: + + + { + + + "errorInformation": { + + + "errorCode": 3200, + + + "errorDescription": "FSP id Not Found", + + + } + + + } + + + + + 19 + + + Return + + + Error code: + + + 3200 + + + + + 20 + + + Return + + + Error code: + + + 3200 + + diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-participant-position-limits-1.0.0.plantuml b/docs/technical/central-ledger/assets/diagrams/sequence/seq-participant-position-limits-1.0.0.plantuml new file mode 100644 index 000000000..79bb20553 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-participant-position-limits-1.0.0.plantuml @@ -0,0 +1,187 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Shashikant Hirugade + -------------- + ******'/ + +@startuml +' declate title +title 1.0.0 Create initial position and limits for Participant + +autonumber + + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +actor "HUB OPERATOR" as OPERATOR +boundary "Central Service API" as CSAPI +control "Participant Handler" as PARTICIPANT_HANDLER +entity "Central Service API" as CSAPI +entity "Participant FACADE" as PARTICIPANT_DAO +database "Central Store" as DB + +box "Central Services" #LightYellow +participant CSAPI +participant PARTICIPANT_HANDLER +participant PARTICIPANT_DAO +participant DB +end box + +' start flow + +activate OPERATOR +group Create initial position and limits + OPERATOR -> CSAPI: Request to Create initial position and limits - POST - /paticipants/{name}/initialPositionAndLimits + note right of OPERATOR #yellow + Message: + { + currency: , + limit: { + type: , + value: + }, + initialPosition: + } + end note + + activate CSAPI + CSAPI -> PARTICIPANT_HANDLER: Create initial position and limits for Participant + activate PARTICIPANT_HANDLER + PARTICIPANT_HANDLER ->PARTICIPANT_DAO: Fetch Participant/ Currency Id \nError code: 3200 + + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Fetch Participant/Currency Id + activate DB + hnote over DB #lightyellow + participant + participantCurrency + end note + DB --> PARTICIPANT_DAO: Retrieved Participant/Currency Id + deactivate DB + PARTICIPANT_DAO --> PARTICIPANT_HANDLER: Return Participant/Currency Id + deactivate PARTICIPANT_DAO + PARTICIPANT_HANDLER ->PARTICIPANT_HANDLER: Validate DFSP + alt Validate participant (success) + PARTICIPANT_HANDLER ->PARTICIPANT_DAO: Fetch limit for participantCurrencyId + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Fetch limit for participantCurrencyId + activate DB + hnote over DB #lightyellow + participantLimit + end note + DB --> PARTICIPANT_DAO: Retrieved participant limit + deactivate DB + PARTICIPANT_DAO --> PARTICIPANT_HANDLER: Return participant limit + deactivate PARTICIPANT_DAO + + PARTICIPANT_HANDLER ->PARTICIPANT_DAO: Fetch position for participantCurrencyId + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Fetch position for participantCurrencyId + activate DB + hnote over DB #lightyellow + participantPosition + end note + DB --> PARTICIPANT_DAO: Retrieved participant position + deactivate DB + PARTICIPANT_DAO --> PARTICIPANT_HANDLER: Return participant position + deactivate PARTICIPANT_DAO + + PARTICIPANT_HANDLER ->PARTICIPANT_HANDLER: Participant position or limit exists check + + alt position or limit does not exist (success) + + + PARTICIPANT_HANDLER ->PARTICIPANT_DAO: create initial position and limits for Participantt \nError code: 2003/Msg: Service unavailable \nError code: 2001/Msg: Internal Server Error + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Persist Participant limits/position + activate DB + hnote over DB #lightyellow + participantPosition + participantLimit + end note + deactivate DB + PARTICIPANT_DAO --> PARTICIPANT_HANDLER: Return status + deactivate PARTICIPANT_DAO + alt Details persisted successfully + PARTICIPANT_HANDLER -->CSAPI: Return Status Code 201 + deactivate PARTICIPANT_HANDLER + CSAPI -->OPERATOR: Return Status Code 201 + else Details not persisted/Error + note right of PARTICIPANT_HANDLER #red: Error! + activate PARTICIPANT_HANDLER + note right of PARTICIPANT_HANDLER #yellow + Message: + { + "errorInformation": { + "errorCode": , + "errorDescription": , + } + } + end note + PARTICIPANT_HANDLER -->CSAPI: Return Error code + ' deactivate PARTICIPANT_HANDLER + CSAPI -->OPERATOR: Return Error code + + end + + else position or limit exists (failure) + note right of PARTICIPANT_HANDLER #red: Error! + activate PARTICIPANT_HANDLER + note right of PARTICIPANT_HANDLER #yellow + Message: + { + "errorInformation": { + "errorCode": 3200, + "errorDescription": "Participant Limit or Initial Position already set", + } + } + end note + PARTICIPANT_HANDLER -->CSAPI: Return Error code: 3200 + ' deactivate PARTICIPANT_HANDLER + CSAPI -->OPERATOR: Return Error code: 3200 + + end + + else Validate participant (failure) + note right of PARTICIPANT_HANDLER #red: Validation failure! + activate PARTICIPANT_HANDLER + note right of PARTICIPANT_HANDLER #yellow + Message: + { + "errorInformation": { + "errorCode": 3200, + "errorDescription": "FSP id Not Found", + } + } + end note + PARTICIPANT_HANDLER -->CSAPI: Return Error code: 3200 + deactivate PARTICIPANT_HANDLER + CSAPI -->OPERATOR: Return Error code: 3200 + + end + deactivate CSAPI + deactivate OPERATOR +end +@enduml \ No newline at end of file diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-participant-position-limits-1.0.0.svg b/docs/technical/central-ledger/assets/diagrams/sequence/seq-participant-position-limits-1.0.0.svg new file mode 100644 index 000000000..fcfca97c7 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-participant-position-limits-1.0.0.svg @@ -0,0 +1,527 @@ + + + + + + + + + + + 1.0.0 Create initial position and limits for Participant + + + + Central Services + + + + + + + + + + HUB OPERATOR + + + + + HUB OPERATOR + + + + + Central Service API + + + + + Central Service API + + + + + Participant Handler + + + + + Participant Handler + + + + + Participant FACADE + + + + + Participant FACADE + + + + + Central Store + + + + + Central Store + + + + + + + + Create initial position and limits + + + + + 1 + + + Request to Create initial position and limits - POST - /paticipants/{name}/initialPositionAndLimits + + + + + Message: + + + { + + + currency: <currencyId>, + + + limit: { + + + type: <limitType>, + + + value: <limitValue> + + + }, + + + initialPosition: <positionValue> + + + } + + + + + 2 + + + Create initial position and limits for Participant + + + + + 3 + + + Fetch Participant/ Currency Id + + + Error code: + + + 3200 + + + + + 4 + + + Fetch Participant/Currency Id + + + + participant + + + participantCurrency + + + + + 5 + + + Retrieved Participant/Currency Id + + + + + 6 + + + Return Participant/Currency Id + + + + + 7 + + + Validate DFSP + + + + + alt + + + [Validate participant (success)] + + + + + 8 + + + Fetch limit for participantCurrencyId + + + + + 9 + + + Fetch limit for participantCurrencyId + + + + participantLimit + + + + + 10 + + + Retrieved participant limit + + + + + 11 + + + Return participant limit + + + + + 12 + + + Fetch position for participantCurrencyId + + + + + 13 + + + Fetch position for participantCurrencyId + + + + participantPosition + + + + + 14 + + + Retrieved participant position + + + + + 15 + + + Return participant position + + + + + 16 + + + Participant position or limit exists check + + + + + alt + + + [position or limit does not exist (success)] + + + + + 17 + + + create initial position and limits for Participantt + + + Error code: + + + 2003/ + + + Msg: + + + Service unavailable + + + Error code: + + + 2001/ + + + Msg: + + + Internal Server Error + + + + + 18 + + + Persist Participant limits/position + + + + participantPosition + + + participantLimit + + + + + 19 + + + Return status + + + + + alt + + + [Details persisted successfully] + + + + + 20 + + + Return Status Code 201 + + + + + 21 + + + Return Status Code 201 + + + + [Details not persisted/Error] + + + + + Error! + + + + + Message: + + + { + + + "errorInformation": { + + + "errorCode": <Error Code>, + + + "errorDescription": <Msg>, + + + } + + + } + + + + + 22 + + + Return + + + Error code + + + + + 23 + + + Return + + + Error code + + + + [position or limit exists (failure)] + + + + + Error! + + + + + Message: + + + { + + + "errorInformation": { + + + "errorCode": 3200, + + + "errorDescription": "Participant Limit or Initial Position already set", + + + } + + + } + + + + + 24 + + + Return + + + Error code: + + + 3200 + + + + + 25 + + + Return + + + Error code: + + + 3200 + + + + [Validate participant (failure)] + + + + + Validation failure! + + + + + Message: + + + { + + + "errorInformation": { + + + "errorCode": 3200, + + + "errorDescription": "FSP id Not Found", + + + } + + + } + + + + + 26 + + + Return + + + Error code: + + + 3200 + + + + + 27 + + + Return + + + Error code: + + + 3200 + + diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-participants-positions-query-4.1.0.plantuml b/docs/technical/central-ledger/assets/diagrams/sequence/seq-participants-positions-query-4.1.0.plantuml new file mode 100644 index 000000000..2bab529fe --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-participants-positions-query-4.1.0.plantuml @@ -0,0 +1,164 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Shashikant Hirugade + * Samuel Kummary + -------------- + ******'/ + +@startuml +' declate title +title 4.1.0 Get Participant Position Details + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +entity "HUB OPERATOR" as OPERATOR +boundary "Central Service API" as CSAPI +control "Participant Handler" as PARTICIPANT_HANDLER +entity "Central Service API" as CSAPI +entity "Participant DAO" as PARTICIPANT_DAO +entity "Position Facade" as POSITION_DAO +database "Central Store" as DB +box "HUB Operator" #LightBlue +participant OPERATOR +end box + +box "Central Service" #LightYellow +participant CSAPI +participant PARTICIPANT_HANDLER +participant PARTICIPANT_DAO +participant POSITION_DAO +participant DB +end box + +' start flow + +activate OPERATOR +group Get Position Details + OPERATOR -> CSAPI: Request to get positions - GET - /participants/{name}/positions?currency={currencyId} + activate CSAPI + CSAPI -> PARTICIPANT_HANDLER: Fetch Positions for Participant + activate PARTICIPANT_HANDLER + PARTICIPANT_HANDLER ->PARTICIPANT_DAO: Fetch Participant \nError code: 2003,3201 + + activate PARTICIPANT_DAO + PARTICIPANT_DAO ->DB: Fetch Participant + activate DB + hnote over DB #lightyellow + participant + end note + DB --> PARTICIPANT_DAO: Retrieved Participant + deactivate DB + PARTICIPANT_DAO -->PARTICIPANT_HANDLER: Return Participant + deactivate PARTICIPANT_DAO + PARTICIPANT_HANDLER ->PARTICIPANT_HANDLER: Validate DFSP \nError code: 3201 + alt Validate participant (success) + PARTICIPANT_HANDLER ->PARTICIPANT_HANDLER: currency parameter passed ? + + alt currency parameter passed + + PARTICIPANT_HANDLER ->POSITION_DAO: Fetch Participant position for a currency id\nError code: 2003 + activate POSITION_DAO + POSITION_DAO ->DB: Fetch Participant position for a currency id + activate DB + hnote over DB #lightyellow + participantCurrency + participantPosition + end note + DB --> POSITION_DAO: Retrieved Participant position for a currency id + deactivate DB + POSITION_DAO -->PARTICIPANT_HANDLER: Return Positions for Participant + deactivate POSITION_DAO + note right of PARTICIPANT_HANDLER #yellow + Message: + { + { + currency: , + value: , + updatedTime: + } + } + end note + PARTICIPANT_HANDLER -->CSAPI: Return Participant position for a currency id + CSAPI -->OPERATOR: Return Participant position for a currency id + else currency parameter not passed + PARTICIPANT_HANDLER ->POSITION_DAO: Fetch Participant Positions for all currencies\nError code: 2003 + activate POSITION_DAO + POSITION_DAO ->DB: Fetch Participant Positions for all currencies + activate DB + hnote over DB #lightyellow + participantCurrency + participantPosition + end note + DB --> POSITION_DAO: Retrieved Participant Positions for all currencies + deactivate DB + POSITION_DAO -->PARTICIPANT_HANDLER: Return Participant Positions for all currencies + deactivate POSITION_DAO + note right of PARTICIPANT_HANDLER #yellow + Message: + { + [ + { + currency: , + value: , + updatedTime: + }, + { + currency: , + value: , + updatedTime: + } + ] + } + end note + PARTICIPANT_HANDLER -->CSAPI: Return Participant Positions for all currencies + CSAPI -->OPERATOR: Return Participant Positions for all currencies + end + else Validate participant (failure) + note right of PARTICIPANT_HANDLER #red: Validation failure! + activate PARTICIPANT_HANDLER + note right of PARTICIPANT_HANDLER #yellow + Message: + { + "errorInformation": { + "errorCode": 3201, + "errorDescription": "FSP id does not exist or not found", + } + } + end note + PARTICIPANT_HANDLER -->CSAPI: Return Error code: 3201 + deactivate PARTICIPANT_HANDLER + CSAPI -->OPERATOR: Return Error code: 3201 + end + +end + +deactivate CSAPI +deactivate OPERATOR + +@enduml \ No newline at end of file diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-participants-positions-query-4.1.0.svg b/docs/technical/central-ledger/assets/diagrams/sequence/seq-participants-positions-query-4.1.0.svg new file mode 100644 index 000000000..b623ef955 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-participants-positions-query-4.1.0.svg @@ -0,0 +1,448 @@ + + + + + + + + + + + 4.1.0 Get Participant Position Details + + + + HUB Operator + + + + Central Service + + + + + + + + + HUB OPERATOR + + + + + HUB OPERATOR + + + + + Central Service API + + + + + Central Service API + + + + + Participant Handler + + + + + Participant Handler + + + + + Participant DAO + + + + + Participant DAO + + + + + Position Facade + + + + + Position Facade + + + + + Central Store + + + + + Central Store + + + + + + + + Get Position Details + + + + + 1 + + + Request to get positions - GET - /participants/{name}/positions?currency={currencyId} + + + + + 2 + + + Fetch Positions for Participant + + + + + 3 + + + Fetch Participant + + + Error code: + + + 2003,3201 + + + + + 4 + + + Fetch Participant + + + + participant + + + + + 5 + + + Retrieved Participant + + + + + 6 + + + Return Participant + + + + + 7 + + + Validate DFSP + + + Error code: + + + 3201 + + + + + alt + + + [Validate participant (success)] + + + + + 8 + + + currency parameter passed ? + + + + + alt + + + [currency parameter passed] + + + + + 9 + + + Fetch Participant position for a currency id + + + Error code: + + + 2003 + + + + + 10 + + + Fetch Participant position for a currency id + + + + participantCurrency + + + participantPosition + + + + + 11 + + + Retrieved Participant position for a currency id + + + + + 12 + + + Return Positions for Participant + + + + + Message: + + + { + + + { + + + currency: <currencyId>, + + + value: <positionValue>, + + + updatedTime: <timeStamp1> + + + } + + + } + + + + + 13 + + + Return Participant position for a currency id + + + + + 14 + + + Return Participant position for a currency id + + + + [currency parameter not passed] + + + + + 15 + + + Fetch Participant Positions for all currencies + + + Error code: + + + 2003 + + + + + 16 + + + Fetch Participant Positions for all currencies + + + + participantCurrency + + + participantPosition + + + + + 17 + + + Retrieved Participant Positions for all currencies + + + + + 18 + + + Return Participant Positions for all currencies + + + + + Message: + + + { + + + [ + + + { + + + currency: <currencyId1>, + + + value: <positionValue1>, + + + updatedTime: <timeStamp1> + + + }, + + + { + + + currency: <currencyId2>, + + + value: <positionValue2>, + + + updatedTime: <timeStamp2> + + + } + + + ] + + + } + + + + + 19 + + + Return Participant Positions for all currencies + + + + + 20 + + + Return Participant Positions for all currencies + + + + [Validate participant (failure)] + + + + + Validation failure! + + + + + Message: + + + { + + + "errorInformation": { + + + "errorCode": 3201, + + + "errorDescription": "FSP id does not exist or not found", + + + } + + + } + + + + + 21 + + + Return + + + Error code: + + + 3201 + + + + + 22 + + + Return + + + Error code: + + + 3201 + + diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-participants-positions-query-all-4.2.0.plantuml b/docs/technical/central-ledger/assets/diagrams/sequence/seq-participants-positions-query-all-4.2.0.plantuml new file mode 100644 index 000000000..753a7e850 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-participants-positions-query-all-4.2.0.plantuml @@ -0,0 +1,139 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Samuel Kummary + -------------- + ******'/ + +@startuml +' declate title +title 4.2.0 Get Positions of all Participants + +autonumber + + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +entity "ML-API-ADAPTER" as MLAPI +boundary "Central Service API" as CSAPI +control "Participant Handler" as PARTICIPANT_HANDLER +entity "Central Service API" as CSAPI +entity "Participant DAO" as PARTICIPANT_DAO +database "Central Store" as DB +box "ML API Adapter Service" #LightBlue + participant MLAPI +end box + +box "Central Service" #LightYellow + participant CSAPI + participant PARTICIPANT_HANDLER + participant PARTICIPANT_DAO + participant DB +end box + +' start flow + +activate MLAPI +group Get Position Details +MLAPI -> CSAPI: Request to get positions - GET - /participants/positions + activate CSAPI + CSAPI -> PARTICIPANT_HANDLER: Fetch Positions for all Participants + activate PARTICIPANT_HANDLER + PARTICIPANT_HANDLER ->PARTICIPANT_DAO: Fetch Positions for all active Participants \nError code: 2003,3200 + activate PARTICIPANT_DAO + PARTICIPANT_DAO ->DB: Fetch Positions for: \n all active Participants \n with all active Currencies for each Participant + activate DB + hnote over DB #lightyellow + participant + participantPosition + participantCurrency + end note + DB --> PARTICIPANT_DAO: Retrieved Positions for Participants + deactivate DB + PARTICIPANT_DAO -->PARTICIPANT_HANDLER: Return Positions for Participants + deactivate PARTICIPANT_DAO + note right of PARTICIPANT_HANDLER #yellow + Message: + { + snapshotAt: , + positions: + [ + { + participantId: , + participantPositions: + [ + { + currentPosition: { + currency: , + value: , + reservedValue: , + lastUpdated: + } + }, + { + currentPosition: { + currency: , + value: , + reservedValue: , + lastUpdated: + } + } + ] + }, + { + participantId: , + participantPositions: + [ + { + currentPosition: { + currency: , + value: , + reservedValue: , + lastUpdated: + } + }, + { + currentPosition: { + currency: , + value: , + reservedValue: , + lastUpdated: + } + } + ] + } + ] + } + end note + PARTICIPANT_HANDLER -->CSAPI: Return Positions for Participants + deactivate PARTICIPANT_HANDLER +CSAPI -->MLAPI: Return Positions for Participants + +end + deactivate CSAPI +deactivate MLAPI + +@enduml \ No newline at end of file diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-participants-positions-query-all-4.2.0.svg b/docs/technical/central-ledger/assets/diagrams/sequence/seq-participants-positions-query-all-4.2.0.svg new file mode 100644 index 000000000..76b9e95a5 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-participants-positions-query-all-4.2.0.svg @@ -0,0 +1,321 @@ + + + + + + + + + + + 4.2.0 Get Positions of all Participants + + + + ML API Adapter Service + + + + Central Service + + + + + + ML-API-ADAPTER + + + + + ML-API-ADAPTER + + + + + Central Service API + + + + + Central Service API + + + + + Participant Handler + + + + + Participant Handler + + + + + Participant DAO + + + + + Participant DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Get Position Details + + + + + 1 + + + Request to get positions - GET - /participants/positions + + + + + 2 + + + Fetch Positions for all Participants + + + + + 3 + + + Fetch Positions for all active Participants + + + Error code: + + + 2003,3200 + + + + + 4 + + + Fetch Positions for: + + + all active Participants + + + with all active Currencies for each Participant + + + + participant + + + participantPosition + + + participantCurrency + + + + + 5 + + + Retrieved Positions for Participants + + + + + 6 + + + Return Positions for Participants + + + + + Message: + + + { + + + snapshotAt: <timestamp0>, + + + positions: + + + [ + + + { + + + participantId: <dfsp1>, + + + participantPositions: + + + [ + + + { + + + currentPosition: { + + + currency: <currency1>, + + + value: <amount1>, + + + reservedValue: <amount2>, + + + lastUpdated: <timeStamp1> + + + } + + + }, + + + { + + + currentPosition: { + + + currency: <currency2>, + + + value: <amount3>, + + + reservedValue: <amount4>, + + + lastUpdated: <timeStamp2> + + + } + + + } + + + ] + + + }, + + + { + + + participantId: <dfsp2>, + + + participantPositions: + + + [ + + + { + + + currentPosition: { + + + currency: <currency1>, + + + value: <amount1>, + + + reservedValue: <amount2>, + + + lastUpdated: <timeStamp1> + + + } + + + }, + + + { + + + currentPosition: { + + + currency: <currency2>, + + + value: <amount3>, + + + reservedValue: <amount4>, + + + lastUpdated: <timeStamp2> + + + } + + + } + + + ] + + + } + + + ] + + + } + + + + + 7 + + + Return Positions for Participants + + + + + 8 + + + Return Positions for Participants + + diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.0-v1.1.plantuml b/docs/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.0-v1.1.plantuml new file mode 100644 index 000000000..04d4356c9 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.0-v1.1.plantuml @@ -0,0 +1,116 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Rajiv Mothilal + * Miguel de Barros + * Valentin Genev + -------------- + ******'/ + +@startuml +' declate title +title 1.3.0. Position Handler Consume (single message) v1.1 + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +collections "topic-transfer-position" as TOPIC_TRANSFER_POSITION +control "Position Handler" as POS_HANDLER +collections "Event-Topic" as TOPIC_EVENTS +collections "Notification-Topic" as TOPIC_NOTIFICATIONS + + +box "Central Service" #LightYellow + participant TOPIC_TRANSFER_POSITION + participant POS_HANDLER + participant TOPIC_EVENTS + participant TOPIC_NOTIFICATIONS +end box + +' start flow +activate POS_HANDLER +group Position Handler Consume + alt Consume Prepare message for Payer + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume Position event message for Payer + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + break + group Validate Event + POS_HANDLER <-> POS_HANDLER: Validate event - Rule: type == 'position' && action == 'prepare'\nError codes: 2001 + end + end + group Persist Event Information + ||| + POS_HANDLER -> TOPIC_EVENTS: Publish event information + ref over POS_HANDLER, TOPIC_EVENTS : Event Handler Consume\n + ||| + end + ||| + ref over POS_HANDLER: Prepare Position Handler Consume\n + POS_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + else Consume Fulfil message for Payee + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume Position event message for Payee + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + break + group Validate Event + POS_HANDLER <-> POS_HANDLER: Validate event - Rule: type == 'position' && action IN ['commit', 'reserve']\nError codes: 2001 + end + end + group Persist Event Information + ||| + POS_HANDLER -> TOPIC_EVENTS: Publish event information + ref over POS_HANDLER, TOPIC_EVENTS : Event Handler Consume\n + ||| + end + ||| + ref over POS_HANDLER: Fulfil Position Handler Consume\n + POS_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + else Consume Abort message + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume Position event message + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + break + group Validate Event + POS_HANDLER <-> POS_HANDLER: Validate event - Rule: type == 'position' &&\naction IN ['timeout-reserved', 'reject', 'fail']\nError codes: 2001 + end + end + group Persist Event Information + ||| + POS_HANDLER -> TOPIC_EVENTS: Publish event information + ref over POS_HANDLER, TOPIC_EVENTS : Event Handler Consume\n + ||| + end + ||| + ref over POS_HANDLER: Abort Position Handler Consume\n + POS_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + end + +end +deactivate POS_HANDLER +@enduml diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.0-v1.1.svg b/docs/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.0-v1.1.svg new file mode 100644 index 000000000..6829d68ff --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.0-v1.1.svg @@ -0,0 +1,301 @@ + + + + + + + + + + + 1.3.0. Position Handler Consume (single message) v1.1 + + + + Central Service + + + + + + + + + + + + + + + + + topic-transfer-position + + + + + topic-transfer-position + + + Position Handler + + + + + Position Handler + + + + + + + Event-Topic + + + + + Event-Topic + + + + + Notification-Topic + + + + + Notification-Topic + + + + + + Position Handler Consume + + + + + alt + + + [Consume Prepare message for Payer] + + + + + 1 + + + Consume Position event message for Payer + + + + + break + + + + + Validate Event + + + + + 2 + + + Validate event - Rule: type == 'position' && action == 'prepare' + + + Error codes: + + + 2001 + + + + + Persist Event Information + + + + + 3 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + ref + + + Prepare Position Handler Consume + + + + + 4 + + + Produce message + + + + [Consume Fulfil message for Payee] + + + + + 5 + + + Consume Position event message for Payee + + + + + break + + + + + Validate Event + + + + + 6 + + + Validate event - Rule: type == 'position' && action IN ['commit', 'reserve'] + + + Error codes: + + + 2001 + + + + + Persist Event Information + + + + + 7 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + ref + + + Fulfil Position Handler Consume + + + + + 8 + + + Produce message + + + + [Consume Abort message] + + + + + 9 + + + Consume Position event message + + + + + break + + + + + Validate Event + + + + + 10 + + + Validate event - Rule: type == 'position' && + + + action IN ['timeout-reserved', 'reject', 'fail'] + + + Error codes: + + + 2001 + + + + + Persist Event Information + + + + + 11 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + ref + + + Abort Position Handler Consume + + + + + 12 + + + Produce message + + diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.0.plantuml b/docs/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.0.plantuml new file mode 100644 index 000000000..963700067 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.0.plantuml @@ -0,0 +1,115 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Rajiv Mothilal + * Miguel de Barros + -------------- + ******'/ + +@startuml +' declate title +title 1.3.0. Position Handler Consume (single message) + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +collections "topic-transfer-position" as TOPIC_TRANSFER_POSITION +control "Position Handler" as POS_HANDLER +collections "Event-Topic" as TOPIC_EVENTS +collections "Notification-Topic" as TOPIC_NOTIFICATIONS + + +box "Central Service" #LightYellow + participant TOPIC_TRANSFER_POSITION + participant POS_HANDLER + participant TOPIC_EVENTS + participant TOPIC_NOTIFICATIONS +end box + +' start flow +activate POS_HANDLER +group Position Handler Consume + alt Consume Prepare message for Payer + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume Position event message for Payer + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + break + group Validate Event + POS_HANDLER <-> POS_HANDLER: Validate event - Rule: type == 'position' && action == 'prepare'\nError codes: 2001 + end + end + group Persist Event Information + ||| + POS_HANDLER -> TOPIC_EVENTS: Publish event information + ref over POS_HANDLER, TOPIC_EVENTS : Event Handler Consume\n + ||| + end + ||| + ref over POS_HANDLER: Prepare Position Handler Consume\n + POS_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + else Consume Fulfil message for Payee + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume Position event message for Payee + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + break + group Validate Event + POS_HANDLER <-> POS_HANDLER: Validate event - Rule: type == 'position' && action == 'commit'\nError codes: 2001 + end + end + group Persist Event Information + ||| + POS_HANDLER -> TOPIC_EVENTS: Publish event information + ref over POS_HANDLER, TOPIC_EVENTS : Event Handler Consume\n + ||| + end + ||| + ref over POS_HANDLER: Fulfil Position Handler Consume\n + POS_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + else Consume Abort message + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume Position event message + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + break + group Validate Event + POS_HANDLER <-> POS_HANDLER: Validate event - Rule: type == 'position' &&\naction IN ['timeout-reserved', 'reject', 'fail']\nError codes: 2001 + end + end + group Persist Event Information + ||| + POS_HANDLER -> TOPIC_EVENTS: Publish event information + ref over POS_HANDLER, TOPIC_EVENTS : Event Handler Consume\n + ||| + end + ||| + ref over POS_HANDLER: Abort Position Handler Consume\n + POS_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + end + +end +deactivate POS_HANDLER +@enduml diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.0.svg b/docs/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.0.svg new file mode 100644 index 000000000..f03e043a8 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.0.svg @@ -0,0 +1,301 @@ + + + + + + + + + + + 1.3.0. Position Handler Consume (single message) + + + + Central Service + + + + + + + + + + + + + + + + + topic-transfer-position + + + + + topic-transfer-position + + + Position Handler + + + + + Position Handler + + + + + + + Event-Topic + + + + + Event-Topic + + + + + Notification-Topic + + + + + Notification-Topic + + + + + + Position Handler Consume + + + + + alt + + + [Consume Prepare message for Payer] + + + + + 1 + + + Consume Position event message for Payer + + + + + break + + + + + Validate Event + + + + + 2 + + + Validate event - Rule: type == 'position' && action == 'prepare' + + + Error codes: + + + 2001 + + + + + Persist Event Information + + + + + 3 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + ref + + + Prepare Position Handler Consume + + + + + 4 + + + Produce message + + + + [Consume Fulfil message for Payee] + + + + + 5 + + + Consume Position event message for Payee + + + + + break + + + + + Validate Event + + + + + 6 + + + Validate event - Rule: type == 'position' && action == 'commit' + + + Error codes: + + + 2001 + + + + + Persist Event Information + + + + + 7 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + ref + + + Fulfil Position Handler Consume + + + + + 8 + + + Produce message + + + + [Consume Abort message] + + + + + 9 + + + Consume Position event message + + + + + break + + + + + Validate Event + + + + + 10 + + + Validate event - Rule: type == 'position' && + + + action IN ['timeout-reserved', 'reject', 'fail'] + + + Error codes: + + + 2001 + + + + + Persist Event Information + + + + + 11 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + ref + + + Abort Position Handler Consume + + + + + 12 + + + Produce message + + diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.1-prepare.plantuml b/docs/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.1-prepare.plantuml new file mode 100644 index 000000000..2e420c3b3 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.1-prepare.plantuml @@ -0,0 +1,283 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Rajiv Mothilal + * Miguel de Barros + -------------- + ******'/ + +@startuml +' declate title +title 1.3.1. Prepare Position Handler Consume + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistence Store + +' declare actors +control "Position Handler" as POS_HANDLER + +entity "Position\nManagement\nFacade" as POS_MGMT +collections "Notification-Topic" as TOPIC_NOTIFICATIONS +entity "Position DAO" as POS_DAO +database "Central Store" as DB + +box "Central Service" #LightYellow + participant POS_HANDLER + participant TOPIC_NOTIFICATIONS + participant POS_MGMT + participant POS_DAO + participant DB +end box + +' start flow +activate POS_HANDLER +group Prepare Position Handler Consume + POS_HANDLER -> POS_MGMT: Request transfers to be processed + activate POS_MGMT + POS_MGMT -> POS_MGMT: Check 1st transfer to select the Participant and Currency + group DB TRANSACTION + ' DB Trans: This is where 1st DB Transaction would start in 2 DB transacation future model for horizontal scaling + POS_MGMT -> POS_MGMT: Loop through batch and build list of transferIds and calculate sumTransfersInBatch,\nchecking all in Batch are for the correct Paricipant and Currency\nError code: 2001, 3100 + POS_MGMT -> DB: Retrieve current state of all transfers in array from DB with select whereIn\n(FYI: The two DB transaction model needs to add a mini-state step here (RECEIVED_PREPARE => RECEIVDED_PREPARE_PROCESSING) so that the transfers are left alone if processing has started) + activate DB + hnote over DB #lightyellow + transferStateChange + transferParticipant + end note + DB --> POS_MGMT: Return current state of all selected transfers from DB + deactivate DB + POS_MGMT <-> POS_MGMT: Validate current state (transferStateChange.transferStateId == 'RECEIVED_PREPARE')\nError code: 2001 against failing transfers\nBatch is not rejected as a whole. + + note right of POS_MGMT #lightgray + List of transfers used during processing + **reservedTransfers** is list of transfers to be processed in the batch + **abortedTransfers** is the list of transfers in the incorrect state going into the process. Currently the transferStateChange is set to ABORTED - this should only be done if not already in a final state (idempotency) + **processedTransfers** is the list of transfers that have gone through the position management algorithm. Both successful and failed trasnfers appear here as the order and "running position" against each is necessary for reconciliation + + Scalar intermidate values used in the algorithm + **transferAmount** = payload.amount.amount + **sumTransfersInBatch** = SUM amount against each Transfer in batch + **currentPosition** = participantPosition.value + **reservedPosition** = participantPosition.{original}reservedValue + **effectivePosition** = currentPosition + reservedPosition + **heldPosition** = effectivePosition + sumTransfersInBatch + **availablePosition** = //if settlement model delay is IMMEDIATE then:// settlementBalance + participantLimit(NetDebitCap) - effectivePosition, //otherwise:// participantLimit(NetDebitCap) - effectivePosition + **sumReserved** = SUM of transfers that have met rule criteria and processed + end note + note over POS_MGMT,DB + Going to reserve the sum of the valid transfers in the batch against the Participants Positon in the Currency of this batch + and calculate the available position for the Participant to use + end note + POS_MGMT -> DB: Select effectivePosition FOR UPDATE from DB for Payer + activate DB + hnote over DB #lightyellow + participantPosition + end note + DB --> POS_MGMT: Return effectivePosition (currentPosition and reservedPosition) from DB for Payer + deactivate DB + POS_MGMT -> POS_MGMT: Increment reservedValue to heldPosition\n(reservedValue = reservedPosition + sumTransfersInBatch) + POS_MGMT -> DB: Persist reservedValue + activate DB + hnote over DB #lightyellow + UPDATE **participantPosition** + SET reservedValue += sumTransfersInBatch + end note + deactivate DB + ' DB Trans: This is where 1st DB Transaction would end in 2 DB transacation future model for horizontal scaling + + + POS_MGMT -> DB: Request position limits for Payer Participant + activate DB + hnote over DB #lightyellow + FROM **participantLimit** + WHERE participantLimit.limitTypeId = 'NET-DEBIT-CAP' + AND participantLimit.participantId = payload.payerFsp + AND participantLimit.currencyId = payload.amount.currency + end note + DB --> POS_MGMT: Return position limits + deactivate DB + POS_MGMT <-> POS_MGMT: **availablePosition** = //if settlement model delay is IMMEDIATE then://\n settlementBalance + participantLimit(NetDebitCap) - effectivePosition\n //otherwise://\n participantLimit(NetDebitCap) - effectivePosition\n(same as = (settlementBalance?) + netDebitCap - currentPosition - reservedPosition) + note over POS_MGMT,DB + For each transfer in the batch, validate the availablility of position to meet the transfer amount + this will be as per the position algorithm documented below + end note + POS_MGMT <-> POS_MGMT: Validate availablePosition for each tranfser (see algorithm below)\nError code: 4001 + note right of POS_MGMT #lightgray + 01: sumReserved = 0 // Record the sum of the transfers we allow to progress to RESERVED + 02: sumProcessed =0 // Record the sum of the transfers already processed in this batch + 03: processedTransfers = {} // The list of processed transfers - so that we can store the additional information around the decision. Most importantly the "running" position + 04: foreach transfer in reservedTransfers + 05: sumProcessed += transfer.amount // the total processed so far **(NEED TO UPDATE IN CODE)** + 06: if availablePosition >= transfer.amount + 07: transfer.state = "RESERVED" + 08: availablePosition -= preparedTransfer.amount + 09: sumRESERVED += preparedTransfer.amount + 10: else + 11: preparedTransfer.state = "ABORTED" + 12: preparedTransfer.reason = "Net Debit Cap exceeded by this request at this time, please try again later" + 13: end if + 14: runningPosition = currentPosition + sumReserved // the initial value of the Participants position plus the total value that has been accepted in the batch so far + 15: runningReservedValue = sumTransfersInBatch - sumProcessed + reservedPosition **(NEED TO UPDATE IN CODE)** // the running down of the total reserved value at the begining of the batch. + 16: Add transfer to the processedTransfer list recording the transfer state and running position and reserved values { transferState, transfer, rawMessage, transferAmount, runningPosition, runningReservedValue } + 16: end foreach + end note + note over POS_MGMT,DB + Once the outcome for all transfers is known,update the Participant's position and remove the reserved amount associated with the batch + (If there are any alarm limits, process those returning limits in which the threshold has been breached) + Do a bulk insert of the trasnferStateChanges associated with processing, using the result to complete the participantPositionChange and bulk insert of these to persist the running position + end note + POS_MGMT->POS_MGMT: Assess any limit thresholds on the final position\nadding to alarm list if triggered + + ' DB Trans: This is where 2nd DB Transaction would start in 2 DB transacation future model for horizontal scaling + POS_MGMT->DB: Persist latest position **value** and **reservedValue** to DB for Payer + hnote over DB #lightyellow + UPDATE **participantPosition** + SET value += sumRESERVED, + reservedValue -= sumTransfersInBatch + end note + activate DB + deactivate DB + + POS_MGMT -> DB: Bulk persist transferStateChange for all processedTransfers + hnote over DB #lightyellow + batch INSERT **transferStateChange** + select for update from transfer table where transferId in ([transferBatch.transferId,...]) + build list of transferStateChanges from transferBatch + + end note + activate DB + deactivate DB + + POS_MGMT->POS_MGMT: Populate batchParticipantPositionChange from the resultant transferStateChange and the earlier processedTransfer list + + note right of POS_MGMT #lightgray + Effectively: + SET transferStateChangeId = processedTransfer.transferStateChangeId, + participantPositionId = preparedTransfer.participantPositionId, + value = preparedTransfer.positionValue, + reservedValue = preparedTransfer.positionReservedValue + end note + POS_MGMT -> DB: Bulk persist the participant position change for all processedTransfers + hnote over DB #lightyellow + batch INSERT **participantPositionChange** + end note + activate DB + deactivate DB + ' DB Trans: This is where 2nd DB Transaction would end in 2 DB transacation future model for horizontal scaling + end + POS_MGMT --> POS_HANDLER: Return a map of transferIds and their transferStateChanges + deactivate POS_MGMT + alt Calculate & Validate Latest Position Prepare (success) + note right of POS_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: transfer, + action: prepare, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + POS_HANDLER -> TOPIC_NOTIFICATIONS: Publish Notification event\nError code: 2003 + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + else Calculate & Validate Latest Position Prepare (failure) + note right of POS_HANDLER #red: Validation failure! + + group Persist Transfer State (with transferState='ABORTED' on position check fail) + POS_HANDLER -> POS_DAO: Request to persist transfer\nError code: 2003 + activate POS_DAO + note right of POS_HANDLER #lightgray + transferStateChange.state = "ABORTED", + transferStateChange.reason = "Net Debit Cap exceeded by this request at this time, please try again later" + end note + POS_DAO -> DB: Persist transfer state + hnote over DB #lightyellow + transferStateChange + end note + activate DB + deactivate DB + POS_DAO --> POS_HANDLER: Return success + deactivate POS_DAO + end + + note right of POS_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: { + "errorInformation": { + "errorCode": 4001, + "errorDescription": "Payer FSP insufficient liquidity", + "extensionList": + } + }, + metadata: { + event: { + id: , + responseTo: , + type: notification, + action: prepare, + createdAt: , + state: { + status: 'error', + code: + description: + } + } + } + } + end note + POS_HANDLER -> TOPIC_NOTIFICATIONS: Publish Notification (failure) event for Payer\nError code: 2003 + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + deactivate POS_HANDLER + end +end +deactivate POS_HANDLER +@enduml diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.1-prepare.svg b/docs/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.1-prepare.svg new file mode 100644 index 000000000..0e6b46ec3 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.1-prepare.svg @@ -0,0 +1,842 @@ + + + + + + + + + + + 1.3.1. Prepare Position Handler Consume + + + + Central Service + + + + + + + + + Position Handler + + + + + Position Handler + + + + + + + Notification-Topic + + + + + Notification-Topic + + + Position + + + Management + + + Facade + + + + + Position + + + Management + + + Facade + + + + + Position DAO + + + + + Position DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Prepare Position Handler Consume + + + + + 1 + + + Request transfers to be processed + + + + + 2 + + + Check 1st transfer to select the Participant and Currency + + + + + DB TRANSACTION + + + + + 3 + + + Loop through batch and build list of transferIds and calculate sumTransfersInBatch, + + + checking all in Batch are for the correct Paricipant and Currency + + + Error code: + + + 2001, 3100 + + + + + 4 + + + Retrieve current state of all transfers in array from DB with select whereIn + + + (FYI: The two DB transaction model needs to add a mini-state step here (RECEIVED_PREPARE => RECEIVDED_PREPARE_PROCESSING) so that the transfers are left alone if processing has started) + + + + transferStateChange + + + transferParticipant + + + + + 5 + + + Return current state of all selected transfers from DB + + + + + 6 + + + Validate current state (transferStateChange.transferStateId == 'RECEIVED_PREPARE') + + + Error code: + + + 2001 + + + against failing transfers + + + Batch is not rejected as a whole. + + + + + List of transfers used during processing + + + reservedTransfers + + + is list of transfers to be processed in the batch + + + abortedTransfers + + + is the list of transfers in the incorrect state going into the process. Currently the transferStateChange is set to ABORTED - this should only be done if not already in a final state (idempotency) + + + processedTransfers + + + is the list of transfers that have gone through the position management algorithm. Both successful and failed trasnfers appear here as the order and "running position" against each is necessary for reconciliation + + + Scalar intermidate values used in the algorithm + + + transferAmount + + + = payload.amount.amount + + + sumTransfersInBatch + + + = SUM amount against each Transfer in batch + + + currentPosition + + + = participantPosition.value + + + reservedPosition + + + = participantPosition.{original}reservedValue + + + effectivePosition + + + = currentPosition + reservedPosition + + + heldPosition + + + = effectivePosition + sumTransfersInBatch + + + availablePosition + + + = + + + if settlement model delay is IMMEDIATE then: + + + settlementBalance + participantLimit(NetDebitCap) - effectivePosition, + + + otherwise: + + + participantLimit(NetDebitCap) - effectivePosition + + + sumReserved + + + = SUM of transfers that have met rule criteria and processed + + + + + Going to reserve the sum of the valid transfers in the batch against the Participants Positon in the Currency of this batch + + + and calculate the available position for the Participant to use + + + + + 7 + + + Select effectivePosition FOR UPDATE from DB for Payer + + + + participantPosition + + + + + 8 + + + Return effectivePosition (currentPosition and reservedPosition) from DB for Payer + + + + + 9 + + + Increment reservedValue to heldPosition + + + (reservedValue = reservedPosition + sumTransfersInBatch) + + + + + 10 + + + Persist reservedValue + + + + UPDATE + + + participantPosition + + + SET reservedValue += sumTransfersInBatch + + + + + 11 + + + Request position limits for Payer Participant + + + + FROM + + + participantLimit + + + WHERE participantLimit.limitTypeId = 'NET-DEBIT-CAP' + + + AND participantLimit.participantId = payload.payerFsp + + + AND participantLimit.currencyId = payload.amount.currency + + + + + 12 + + + Return position limits + + + + + 13 + + + availablePosition + + + = + + + if settlement model delay is IMMEDIATE then: + + + settlementBalance + participantLimit(NetDebitCap) - effectivePosition + + + otherwise: + + + participantLimit(NetDebitCap) - effectivePosition + + + (same as = (settlementBalance?) + netDebitCap - currentPosition - reservedPosition) + + + + + For each transfer in the batch, validate the availablility of position to meet the transfer amount + + + this will be as per the position algorithm documented below + + + + + 14 + + + Validate availablePosition for each tranfser (see algorithm below) + + + Error code: + + + 4001 + + + + + 01: sumReserved = 0 // Record the sum of the transfers we allow to progress to RESERVED + + + 02: sumProcessed =0 // Record the sum of the transfers already processed in this batch + + + 03: processedTransfers = {} // The list of processed transfers - so that we can store the additional information around the decision. Most importantly the "running" position + + + 04: foreach transfer in reservedTransfers + + + 05: sumProcessed += transfer.amount // the total processed so far + + + (NEED TO UPDATE IN CODE) + + + 06: if availablePosition >= transfer.amount + + + 07: transfer.state = "RESERVED" + + + 08: availablePosition -= preparedTransfer.amount + + + 09: sumRESERVED += preparedTransfer.amount + + + 10: else + + + 11: preparedTransfer.state = "ABORTED" + + + 12: preparedTransfer.reason = "Net Debit Cap exceeded by this request at this time, please try again later" + + + 13: end if + + + 14: runningPosition = currentPosition + sumReserved // the initial value of the Participants position plus the total value that has been accepted in the batch so far + + + 15: runningReservedValue = sumTransfersInBatch - sumProcessed + reservedPosition + + + (NEED TO UPDATE IN CODE) + + + // the running down of the total reserved value at the begining of the batch. + + + 16: Add transfer to the processedTransfer list recording the transfer state and running position and reserved values { transferState, transfer, rawMessage, transferAmount, runningPosition, runningReservedValue } + + + 16: end foreach + + + + + Once the outcome for all transfers is known,update the Participant's position and remove the reserved amount associated with the batch + + + (If there are any alarm limits, process those returning limits in which the threshold has been breached) + + + Do a bulk insert of the trasnferStateChanges associated with processing, using the result to complete the participantPositionChange and bulk insert of these to persist the running position + + + + + 15 + + + Assess any limit thresholds on the final position + + + adding to alarm list if triggered + + + + + 16 + + + Persist latest position + + + value + + + and + + + reservedValue + + + to DB for Payer + + + + UPDATE + + + participantPosition + + + SET value += sumRESERVED, + + + reservedValue -= sumTransfersInBatch + + + + + 17 + + + Bulk persist transferStateChange for all processedTransfers + + + + batch INSERT + + + transferStateChange + + + select for update from transfer table where transferId in ([transferBatch.transferId,...]) + + + build list of transferStateChanges from transferBatch + + + + + 18 + + + Populate batchParticipantPositionChange from the resultant transferStateChange and the earlier processedTransfer list + + + + + Effectively: + + + SET transferStateChangeId = processedTransfer.transferStateChangeId, + + + participantPositionId = preparedTransfer.participantPositionId, + + + value = preparedTransfer.positionValue, + + + reservedValue = preparedTransfer.positionReservedValue + + + + + 19 + + + Bulk persist the participant position change for all processedTransfers + + + + batch INSERT + + + participantPositionChange + + + + + 20 + + + Return a map of transferIds and their transferStateChanges + + + + + alt + + + [Calculate & Validate Latest Position Prepare (success)] + + + + + Message: + + + { + + + id: <transferMessage.transferId> + + + from: <transferMessage.payerFsp>, + + + to: <transferMessage.payeeFsp>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: transfer, + + + action: prepare, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 21 + + + Publish Notification event + + + Error code: + + + 2003 + + + + [Calculate & Validate Latest Position Prepare (failure)] + + + + + Validation failure! + + + + + Persist Transfer State (with transferState='ABORTED' on position check fail) + + + + + 22 + + + Request to persist transfer + + + Error code: + + + 2003 + + + + + transferStateChange.state = "ABORTED", + + + transferStateChange.reason = "Net Debit Cap exceeded by this request at this time, please try again later" + + + + + 23 + + + Persist transfer state + + + + transferStateChange + + + + + 24 + + + Return success + + + + + Message: + + + { + + + id: <transferMessage.transferId> + + + from: <ledgerName>, + + + to: <transferMessage.payerFsp>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: { + + + "errorInformation": { + + + "errorCode": 4001, + + + "errorDescription": "Payer FSP insufficient liquidity", + + + "extensionList": <transferMessage.extensionList> + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: notification, + + + action: prepare, + + + createdAt: <timestamp>, + + + state: { + + + status: 'error', + + + code: <errorInformation.errorCode> + + + description: <errorInformation.errorDescription> + + + } + + + } + + + } + + + } + + + + + 25 + + + Publish Notification (failure) event for Payer + + + Error code: + + + 2003 + + diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.2-fulfil-v1.1.plantuml b/docs/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.2-fulfil-v1.1.plantuml new file mode 100644 index 000000000..fab0fbf38 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.2-fulfil-v1.1.plantuml @@ -0,0 +1,141 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Rajiv Mothilal + * Miguel de Barros + * Valentin Genev + -------------- + ******'/ + +@startuml +' declate title +title 1.3.2. Fulfil Position Handler Consume v1.1 + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistence Store + +' declare actors +control "Position Handler" as POS_HANDLER +collections "Notifications-Topic" as TOPIC_NOTIFICATIONS +entity "Position Facade" as POS_FACADE +entity "Position DAO" as POS_DAO +database "Central Store" as DB + +box "Central Service" #LightYellow + participant POS_HANDLER + participant TOPIC_NOTIFICATIONS + participant POS_DAO + participant POS_FACADE + participant DB +end box + +' start flow +activate POS_HANDLER +group Fulfil Position Handler Consume + POS_HANDLER -> POS_DAO: Request current state of transfer from DB \nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Retrieve current state of transfer from DB + activate DB + hnote over DB #lightyellow + transferStateChange + transferParticipant + end note + DB --> POS_DAO: Return current state of transfer from DB + deactivate DB + POS_DAO --> POS_HANDLER: Return current state of transfer from DB + deactivate POS_DAO + POS_HANDLER <-> POS_HANDLER: Validate current state (transferState is 'RECEIVED-FULFIL')\nError code: 2001 + group Persist Position change and Transfer State (with transferState='COMMITTED' on position check pass) + POS_HANDLER -> POS_FACADE: Request to persist latest position and state to DB\nError code: 2003 + group DB TRANSACTION + activate POS_FACADE + POS_FACADE -> DB: Select participantPosition.value FOR UPDATE from DB for Payee + activate DB + hnote over DB #lightyellow + participantPosition + end note + DB --> POS_FACADE: Return participantPosition.value from DB for Payee + deactivate DB + POS_FACADE <-> POS_FACADE: **latestPosition** = participantPosition.value - payload.amount.amount + POS_FACADE->DB: Persist latestPosition to DB for Payee + hnote over DB #lightyellow + UPDATE **participantPosition** + SET value = latestPosition + end note + activate DB + deactivate DB + POS_FACADE -> DB: Persist transfer state and participant position change + hnote over DB #lightyellow + INSERT **transferStateChange** transferStateId = 'COMMITTED' + + INSERT **participantPositionChange** + SET participantPositionId = participantPosition.participantPositionId, + transferStateChangeId = transferStateChange.transferStateChangeId, + value = latestPosition, + reservedValue = participantPosition.reservedValue + createdDate = new Date() + end note + activate DB + deactivate DB + deactivate POS_DAO + end + POS_FACADE --> POS_HANDLER: Return success + deactivate POS_FACADE + end + + note right of POS_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: transfer, + action: commit || reserve, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + POS_HANDLER -> TOPIC_NOTIFICATIONS: Publish Transfer event\nError code: 2003 + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS +end +deactivate POS_HANDLER +@enduml diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.2-fulfil-v1.1.svg b/docs/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.2-fulfil-v1.1.svg new file mode 100644 index 000000000..de29ad2c9 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.2-fulfil-v1.1.svg @@ -0,0 +1,345 @@ + + + + + + + + + + + 1.3.2. Fulfil Position Handler Consume v1.1 + + + + Central Service + + + + + + + + Position Handler + + + + + Position Handler + + + + + + + Notifications-Topic + + + + + Notifications-Topic + + + Position DAO + + + + + Position DAO + + + + + Position Facade + + + + + Position Facade + + + + + Central Store + + + + + Central Store + + + + + + + + Fulfil Position Handler Consume + + + + + 1 + + + Request current state of transfer from DB + + + Error code: + + + 2003 + + + + + 2 + + + Retrieve current state of transfer from DB + + + + transferStateChange + + + transferParticipant + + + + + 3 + + + Return current state of transfer from DB + + + + + 4 + + + Return current state of transfer from DB + + + + + 5 + + + Validate current state (transferState is 'RECEIVED-FULFIL') + + + Error code: + + + 2001 + + + + + Persist Position change and Transfer State (with transferState='COMMITTED' on position check pass) + + + + + 6 + + + Request to persist latest position and state to DB + + + Error code: + + + 2003 + + + + + DB TRANSACTION + + + + + 7 + + + Select participantPosition.value FOR UPDATE from DB for Payee + + + + participantPosition + + + + + 8 + + + Return participantPosition.value from DB for Payee + + + + + 9 + + + latestPosition + + + = participantPosition.value - payload.amount.amount + + + + + 10 + + + Persist latestPosition to DB for Payee + + + + UPDATE + + + participantPosition + + + SET value = latestPosition + + + + + 11 + + + Persist transfer state and participant position change + + + + INSERT + + + transferStateChange + + + transferStateId = 'COMMITTED' + + + INSERT + + + participantPositionChange + + + SET participantPositionId = participantPosition.participantPositionId, + + + transferStateChangeId = transferStateChange.transferStateChangeId, + + + value = latestPosition, + + + reservedValue = participantPosition.reservedValue + + + createdDate = new Date() + + + + + 12 + + + Return success + + + + + Message: + + + { + + + id: <transferMessage.transferId> + + + from: <transferMessage.payerFsp>, + + + to: <transferMessage.payeeFsp>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: transfer, + + + action: commit || reserve, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 13 + + + Publish Transfer event + + + Error code: + + + 2003 + + diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.2-fulfil.plantuml b/docs/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.2-fulfil.plantuml new file mode 100644 index 000000000..091fd6adf --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.2-fulfil.plantuml @@ -0,0 +1,140 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Rajiv Mothilal + * Miguel de Barros + -------------- + ******'/ + +@startuml +' declate title +title 1.3.2. Fulfil Position Handler Consume + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistence Store + +' declare actors +control "Position Handler" as POS_HANDLER +collections "Notifications-Topic" as TOPIC_NOTIFICATIONS +entity "Position Facade" as POS_FACADE +entity "Position DAO" as POS_DAO +database "Central Store" as DB + +box "Central Service" #LightYellow + participant POS_HANDLER + participant TOPIC_NOTIFICATIONS + participant POS_DAO + participant POS_FACADE + participant DB +end box + +' start flow +activate POS_HANDLER +group Fulfil Position Handler Consume + POS_HANDLER -> POS_DAO: Request current state of transfer from DB \nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Retrieve current state of transfer from DB + activate DB + hnote over DB #lightyellow + transferStateChange + transferParticipant + end note + DB --> POS_DAO: Return current state of transfer from DB + deactivate DB + POS_DAO --> POS_HANDLER: Return current state of transfer from DB + deactivate POS_DAO + POS_HANDLER <-> POS_HANDLER: Validate current state (transferState is 'RECEIVED-FULFIL')\nError code: 2001 + group Persist Position change and Transfer State (with transferState='COMMITTED' on position check pass) + POS_HANDLER -> POS_FACADE: Request to persist latest position and state to DB\nError code: 2003 + group DB TRANSACTION + activate POS_FACADE + POS_FACADE -> DB: Select participantPosition.value FOR UPDATE from DB for Payee + activate DB + hnote over DB #lightyellow + participantPosition + end note + DB --> POS_FACADE: Return participantPosition.value from DB for Payee + deactivate DB + POS_FACADE <-> POS_FACADE: **latestPosition** = participantPosition.value - payload.amount.amount + POS_FACADE->DB: Persist latestPosition to DB for Payee + hnote over DB #lightyellow + UPDATE **participantPosition** + SET value = latestPosition + end note + activate DB + deactivate DB + POS_FACADE -> DB: Persist transfer state and participant position change + hnote over DB #lightyellow + INSERT **transferStateChange** transferStateId = 'COMMITTED' + + INSERT **participantPositionChange** + SET participantPositionId = participantPosition.participantPositionId, + transferStateChangeId = transferStateChange.transferStateChangeId, + value = latestPosition, + reservedValue = participantPosition.reservedValue + createdDate = new Date() + end note + activate DB + deactivate DB + deactivate POS_DAO + end + POS_FACADE --> POS_HANDLER: Return success + deactivate POS_FACADE + end + + note right of POS_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: transfer, + action: commit, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + POS_HANDLER -> TOPIC_NOTIFICATIONS: Publish Transfer event\nError code: 2003 + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS +end +deactivate POS_HANDLER +@enduml diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.2-fulfil.svg b/docs/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.2-fulfil.svg new file mode 100644 index 000000000..89ddaffd3 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.2-fulfil.svg @@ -0,0 +1,345 @@ + + + + + + + + + + + 1.3.2. Fulfil Position Handler Consume + + + + Central Service + + + + + + + + Position Handler + + + + + Position Handler + + + + + + + Notifications-Topic + + + + + Notifications-Topic + + + Position DAO + + + + + Position DAO + + + + + Position Facade + + + + + Position Facade + + + + + Central Store + + + + + Central Store + + + + + + + + Fulfil Position Handler Consume + + + + + 1 + + + Request current state of transfer from DB + + + Error code: + + + 2003 + + + + + 2 + + + Retrieve current state of transfer from DB + + + + transferStateChange + + + transferParticipant + + + + + 3 + + + Return current state of transfer from DB + + + + + 4 + + + Return current state of transfer from DB + + + + + 5 + + + Validate current state (transferState is 'RECEIVED-FULFIL') + + + Error code: + + + 2001 + + + + + Persist Position change and Transfer State (with transferState='COMMITTED' on position check pass) + + + + + 6 + + + Request to persist latest position and state to DB + + + Error code: + + + 2003 + + + + + DB TRANSACTION + + + + + 7 + + + Select participantPosition.value FOR UPDATE from DB for Payee + + + + participantPosition + + + + + 8 + + + Return participantPosition.value from DB for Payee + + + + + 9 + + + latestPosition + + + = participantPosition.value - payload.amount.amount + + + + + 10 + + + Persist latestPosition to DB for Payee + + + + UPDATE + + + participantPosition + + + SET value = latestPosition + + + + + 11 + + + Persist transfer state and participant position change + + + + INSERT + + + transferStateChange + + + transferStateId = 'COMMITTED' + + + INSERT + + + participantPositionChange + + + SET participantPositionId = participantPosition.participantPositionId, + + + transferStateChangeId = transferStateChange.transferStateChangeId, + + + value = latestPosition, + + + reservedValue = participantPosition.reservedValue + + + createdDate = new Date() + + + + + 12 + + + Return success + + + + + Message: + + + { + + + id: <transferMessage.transferId> + + + from: <transferMessage.payerFsp>, + + + to: <transferMessage.payeeFsp>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: transfer, + + + action: commit, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 13 + + + Publish Transfer event + + + Error code: + + + 2003 + + diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.3-abort.plantuml b/docs/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.3-abort.plantuml new file mode 100644 index 000000000..3301874a4 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.3-abort.plantuml @@ -0,0 +1,306 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Rajiv Mothilal + * Georgi Georgiev + * Sam Kummary + ------------- + ******'/ + +@startuml +' declate title +title 1.3.3. Abort Position Handler Consume + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistence Store + +' declare actors +control "Position Handler" as POS_HANDLER +entity "Position DAO" as POS_DAO +collections "Notification-Topic" as TOPIC_NOTIFICATIONS +database "Central Store" as DB + +box "Central Service" #LightYellow + participant POS_HANDLER + participant TOPIC_NOTIFICATIONS + participant POS_DAO + participant DB +end box + +' start flow +activate POS_HANDLER +group Abort Position Handler Consume + opt type == 'position' && action == 'timeout-reserved' + POS_HANDLER -> POS_DAO: Request current state of transfer from DB\nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Retrieve current state of transfer from DB + activate DB + hnote over DB #lightyellow + transferStateChange + transferParticipant + end note + DB --> POS_DAO: Return current state of transfer from DB + deactivate DB + POS_DAO --> POS_HANDLER: Return current state of transfer from DB + deactivate POS_DAO + POS_HANDLER <-> POS_HANDLER: Validate current state (transferStateChange.transferStateId == 'RESERVED_TIMEOUT')\nError code: 2001 + + group Persist Position change and Transfer state + POS_HANDLER -> POS_HANDLER: **transferStateId** = 'EXPIRED_RESERVED' + POS_HANDLER -> POS_DAO: Request to persist latest position and state to DB\nError code: 2003 + group DB TRANSACTION IMPLEMENTATION + activate POS_DAO + POS_DAO -> DB: Select participantPosition.value FOR UPDATE for payerCurrencyId + activate DB + hnote over DB #lightyellow + participantPosition + end note + DB --> POS_DAO: Return participantPosition + deactivate DB + POS_DAO <-> POS_DAO: **latestPosition** = participantPosition - payload.amount.amount + POS_DAO->DB: Persist latestPosition to DB for Payer + hnote over DB #lightyellow + UPDATE **participantPosition** + SET value = latestPosition + end note + activate DB + deactivate DB + POS_DAO -> DB: Persist participant position change and state change + hnote over DB #lightyellow + INSERT **transferStateChange** + VALUES (transferStateId) + + INSERT **participantPositionChange** + SET participantPositionId = participantPosition.participantPositionId, + transferStateChangeId = transferStateChange.transferStateChangeId, + value = latestPosition, + reservedValue = participantPosition.reservedValue + createdDate = new Date() + end note + activate DB + deactivate DB + end + POS_DAO --> POS_HANDLER: Return success + deactivate POS_DAO + end + note right of POS_HANDLER #yellow + Message: { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: { + "errorInformation": { + "errorCode": 3300, + "errorDescription": "Transfer expired", + "extensionList": + } + } + }, + metadata: { + event: { + id: , + responseTo: , + type: notification, + action: abort, + createdAt: , + state: { + status: 'error', + code: + description: + } + } + } + } + end note + POS_HANDLER -> TOPIC_NOTIFICATIONS: Publish Notification event\nError code: 2003 + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + end + opt type == 'position' && (action IN ['reject', 'abort']) + POS_HANDLER -> POS_DAO: Request current state of transfer from DB\nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Retrieve current state of transfer from DB + activate DB + hnote over DB #lightyellow + transferStateChange + end note + DB --> POS_DAO: Return current state of transfer from DB + deactivate DB + POS_DAO --> POS_HANDLER: Return current state of transfer from DB + deactivate POS_DAO + POS_HANDLER <-> POS_HANDLER: Validate current state (transferStateChange.transferStateId IN ['RECEIVED_REJECT', 'RECEIVED_ERROR'])\nError code: 2001 + + group Persist Position change and Transfer state + POS_HANDLER -> POS_HANDLER: **transferStateId** = (action == 'reject' ? 'ABORTED_REJECTED' : 'ABORTED_ERROR' ) + POS_HANDLER -> POS_DAO: Request to persist latest position and state to DB\nError code: 2003 + group Refer to DB TRANSACTION IMPLEMENTATION above + activate POS_DAO + POS_DAO -> DB: Persist to database + activate DB + deactivate DB + hnote over DB #lightyellow + participantPosition + transferStateChange + participantPositionChange + end note + end + POS_DAO --> POS_HANDLER: Return success + deactivate POS_DAO + end + alt action == 'reject' + note right of POS_HANDLER #yellow + Message: { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: notification, + action: reject, + createdAt: , + state: { + status: "success", + code: 0, + description: "action successful" + } + } + } + } + end note + else action == 'abort' + note right of POS_HANDLER #yellow + Message: { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: notification, + action: abort, + createdAt: , + state: { + status: 'error', + code: + description: + } + } + } + } + end note + end + POS_HANDLER -> TOPIC_NOTIFICATIONS: Publish Notification event\nError code: 2003 + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + end + + ' TODO: We do not see how this scenario will be triggered + opt type == 'position' && action == 'fail' (Unable to currently trigger this scenario) + POS_HANDLER -> POS_DAO: Request current state of transfer from DB\nError code: 2003 + activate POS_DAO + POS_DAO -> DB: Retrieve current state of transfer from DB + activate DB + hnote over DB #lightyellow + transferStateChange + end note + DB --> POS_DAO: Return current state of transfer from DB + deactivate DB + POS_DAO --> POS_HANDLER: Return current state of transfer from DB + deactivate POS_DAO + POS_HANDLER <-> POS_HANDLER: Validate current state (transferStateChange.transferStateId == 'FAILED') + + group Persist Position change and Transfer state + POS_HANDLER -> POS_HANDLER: **transferStateId** = 'FAILED' + POS_HANDLER -> POS_DAO: Request to persist latest position and state to DB\nError code: 2003 + group Refer to DB TRANSACTION IMPLEMENTATION above + activate POS_DAO + POS_DAO -> DB: Persist to database + activate DB + deactivate DB + hnote over DB #lightyellow + participantPosition + transferStateChange + participantPositionChange + end note + end + POS_DAO --> POS_HANDLER: Return success + deactivate POS_DAO + end + note right of POS_HANDLER #yellow + Message: { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: { + "errorInformation": { + "errorCode": 3100, + "errorDescription": "Transfer failed", + "extensionList": + } + } + }, + metadata: { + event: { + id: , + responseTo: , + type: notification, + action: abort, + createdAt: , + state: { + status: 'error', + code: + description: + } + } + } + } + end note + POS_HANDLER -> TOPIC_NOTIFICATIONS: Publish Notification event\nError code: 2003 + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + end +end +deactivate POS_HANDLER +@enduml diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.3-abort.svg b/docs/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.3-abort.svg new file mode 100644 index 000000000..57c541a8c --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-position-1.3.3-abort.svg @@ -0,0 +1,915 @@ + + + + + + + + + + + 1.3.3. Abort Position Handler Consume + + + + Central Service + + + + + + + + + + + + + + + Position Handler + + + + + Position Handler + + + + + + + Notification-Topic + + + + + Notification-Topic + + + Position DAO + + + + + Position DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Abort Position Handler Consume + + + + + opt + + + [type == 'position' && action == 'timeout-reserved'] + + + + + 1 + + + Request current state of transfer from DB + + + Error code: + + + 2003 + + + + + 2 + + + Retrieve current state of transfer from DB + + + + transferStateChange + + + transferParticipant + + + + + 3 + + + Return current state of transfer from DB + + + + + 4 + + + Return current state of transfer from DB + + + + + 5 + + + Validate current state (transferStateChange.transferStateId == 'RESERVED_TIMEOUT') + + + Error code: + + + 2001 + + + + + Persist Position change and Transfer state + + + + + 6 + + + transferStateId + + + = 'EXPIRED_RESERVED' + + + + + 7 + + + Request to persist latest position and state to DB + + + Error code: + + + 2003 + + + + + DB TRANSACTION IMPLEMENTATION + + + + + 8 + + + Select participantPosition.value FOR UPDATE for payerCurrencyId + + + + participantPosition + + + + + 9 + + + Return participantPosition + + + + + 10 + + + latestPosition + + + = participantPosition - payload.amount.amount + + + + + 11 + + + Persist latestPosition to DB for Payer + + + + UPDATE + + + participantPosition + + + SET value = latestPosition + + + + + 12 + + + Persist participant position change and state change + + + + INSERT + + + transferStateChange + + + VALUES (transferStateId) + + + INSERT + + + participantPositionChange + + + SET participantPositionId = participantPosition.participantPositionId, + + + transferStateChangeId = transferStateChange.transferStateChangeId, + + + value = latestPosition, + + + reservedValue = participantPosition.reservedValue + + + createdDate = new Date() + + + + + 13 + + + Return success + + + + + Message: { + + + id: <transferMessage.transferId> + + + from: <transferMessage.payerFsp>, + + + to: <transferMessage.payeeFsp>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: { + + + "errorInformation": { + + + "errorCode": 3300, + + + "errorDescription": "Transfer expired", + + + "extensionList": <transferMessage.extensionList> + + + } + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: notification, + + + action: abort, + + + createdAt: <timestamp>, + + + state: { + + + status: 'error', + + + code: <errorInformation.errorCode> + + + description: <errorInformation.errorDescription> + + + } + + + } + + + } + + + } + + + + + 14 + + + Publish Notification event + + + Error code: + + + 2003 + + + + + opt + + + [type == 'position' && (action IN ['reject', 'abort'])] + + + + + 15 + + + Request current state of transfer from DB + + + Error code: + + + 2003 + + + + + 16 + + + Retrieve current state of transfer from DB + + + + transferStateChange + + + + + 17 + + + Return current state of transfer from DB + + + + + 18 + + + Return current state of transfer from DB + + + + + 19 + + + Validate current state (transferStateChange.transferStateId IN ['RECEIVED_REJECT', 'RECEIVED_ERROR']) + + + Error code: + + + 2001 + + + + + Persist Position change and Transfer state + + + + + 20 + + + transferStateId + + + = (action == 'reject' ? 'ABORTED_REJECTED' : 'ABORTED_ERROR' ) + + + + + 21 + + + Request to persist latest position and state to DB + + + Error code: + + + 2003 + + + + + Refer to + + + DB TRANSACTION IMPLEMENTATION + + + above + + + + + 22 + + + Persist to database + + + + participantPosition + + + transferStateChange + + + participantPositionChange + + + + + 23 + + + Return success + + + + + alt + + + [action == 'reject'] + + + + + Message: { + + + id: <transferMessage.transferId> + + + from: <transferMessage.payerFsp>, + + + to: <transferMessage.payeeFsp>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: notification, + + + action: reject, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0, + + + description: "action successful" + + + } + + + } + + + } + + + } + + + + [action == 'abort'] + + + + + Message: { + + + id: <transferMessage.transferId> + + + from: <transferMessage.payerFsp>, + + + to: <transferMessage.payeeFsp>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: notification, + + + action: abort, + + + createdAt: <timestamp>, + + + state: { + + + status: 'error', + + + code: <payload.errorInformation.errorCode || 5000> + + + description: <payload.errorInformation.errorDescription> + + + } + + + } + + + } + + + } + + + + + 24 + + + Publish Notification event + + + Error code: + + + 2003 + + + + + opt + + + [type == 'position' && action == 'fail' (Unable to currently trigger this scenario)] + + + + + 25 + + + Request current state of transfer from DB + + + Error code: + + + 2003 + + + + + 26 + + + Retrieve current state of transfer from DB + + + + transferStateChange + + + + + 27 + + + Return current state of transfer from DB + + + + + 28 + + + Return current state of transfer from DB + + + + + 29 + + + Validate current state (transferStateChange.transferStateId == 'FAILED') + + + + + Persist Position change and Transfer state + + + + + 30 + + + transferStateId + + + = 'FAILED' + + + + + 31 + + + Request to persist latest position and state to DB + + + Error code: + + + 2003 + + + + + Refer to + + + DB TRANSACTION IMPLEMENTATION + + + above + + + + + 32 + + + Persist to database + + + + participantPosition + + + transferStateChange + + + participantPositionChange + + + + + 33 + + + Return success + + + + + Message: { + + + id: <transferMessage.transferId> + + + from: <transferMessage.payerFsp>, + + + to: <transferMessage.payeeFsp>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: { + + + "errorInformation": { + + + "errorCode": 3100, + + + "errorDescription": "Transfer failed", + + + "extensionList": <transferMessage.extensionList> + + + } + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: notification, + + + action: abort, + + + createdAt: <timestamp>, + + + state: { + + + status: 'error', + + + code: <errorInformation.errorCode> + + + description: <errorInformation.errorDescription> + + + } + + + } + + + } + + + } + + + + + 34 + + + Publish Notification event + + + Error code: + + + 2003 + + diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.0.plantuml b/docs/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.0.plantuml new file mode 100644 index 000000000..5b530af7b --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.0.plantuml @@ -0,0 +1,163 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Miguel de Barros + -------------- + ******'/ + +@startuml +' declate title +title 1.1.0. DFSP1 sends a Prepare Transfer request to DFSP2 + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +actor "DFSP1\nPayer" as DFSP1 +actor "DFSP2\nPayee" as DFSP2 +boundary "ML API Adapter" as MLAPI +control "ML API Notification Event Handler" as NOTIFY_HANDLER +boundary "Central Service API" as CSAPI +collections "topic-transfer-prepare" as TOPIC_TRANSFER_PREPARE +control "Prepare Event Handler" as PREP_HANDLER +collections "topic-transfer-position" as TOPIC_TRANSFER_POSITION +control "Position Event Handler" as POS_HANDLER +collections "Notification-Topic" as TOPIC_NOTIFICATIONS + +box "Financial Service Providers" #lightGray + participant DFSP1 + participant DFSP2 +end box + +box "ML API Adapter Service" #LightBlue + participant MLAPI + participant NOTIFY_HANDLER +end box + +box "Central Service" #LightYellow + participant CSAPI + participant TOPIC_TRANSFER_PREPARE + participant PREP_HANDLER + participant TOPIC_TRANSFER_POSITION + participant POS_HANDLER + participant TOPIC_NOTIFICATIONS +end box + +' start flow +activate NOTIFY_HANDLER +activate PREP_HANDLER +activate POS_HANDLER +group DFSP1 sends a Prepare Transfer request to DFSP2 + note right of DFSP1 #yellow + Headers - transferHeaders: { + Content-Length: , + Content-Type: , + Date: , + X-Forwarded-For: , + FSPIOP-Source: , + FSPIOP-Destination: , + FSPIOP-Encryption: , + FSPIOP-Signature: , + FSPIOP-URI: , + FSPIOP-HTTP-Method: + } + + Payload - transferMessage: + { + "transferId": , + "payeeFsp": dfsp2, + "payerFsp": dfsp1, + "amount": { + "currency": "AED", + "amount": "string" + }, + "ilpPacket": "string", + "condition": "string", + "expiration": "string", + "extensionList": { + "extension": [ + { + "key": "string", + "value": "string" + } + ] + } + } + end note + DFSP1 ->> MLAPI: POST - /transfers + activate MLAPI + MLAPI -> MLAPI: Validate incoming token and originator matching Payer\nError codes: 3000-3002, 3100-3107 + note right of MLAPI #yellow + Message: + { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + type: prepare, + action: prepare, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + MLAPI -> TOPIC_TRANSFER_PREPARE: Route & Publish Prepare event for Payer\nError code: 2003 + activate TOPIC_TRANSFER_PREPARE + TOPIC_TRANSFER_PREPARE <-> TOPIC_TRANSFER_PREPARE: Ensure event is replicated as configured (ACKS=all)\nError code: 2003 + TOPIC_TRANSFER_PREPARE --> MLAPI: Respond replication acknowledgements have been received + deactivate TOPIC_TRANSFER_PREPARE + MLAPI -->> DFSP1: Respond HTTP - 202 (Accepted) + deactivate MLAPI + ||| + TOPIC_TRANSFER_PREPARE <- PREP_HANDLER: Consume message + ref over TOPIC_TRANSFER_PREPARE, PREP_HANDLER, TOPIC_TRANSFER_POSITION : Prepare Handler Consume\n + PREP_HANDLER -> TOPIC_TRANSFER_POSITION: Produce message + ||| + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume message + ref over TOPIC_TRANSFER_POSITION, POS_HANDLER : Position Handler Consume\n + POS_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + ||| + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message + ref over DFSP2, TOPIC_NOTIFICATIONS : Send notification to Participant (Payee)\n + NOTIFY_HANDLER -> DFSP2: Send callback notification + ||| +end +deactivate POS_HANDLER +deactivate PREP_HANDLER +deactivate NOTIFY_HANDLER +@enduml diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.0.svg b/docs/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.0.svg new file mode 100644 index 000000000..597c20f74 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.0.svg @@ -0,0 +1,455 @@ + + + + + + + + + + + 1.1.0. DFSP1 sends a Prepare Transfer request to DFSP2 + + + + Financial Service Providers + + + + ML API Adapter Service + + + + Central Service + + + + + + DFSP1 + + + Payer + + + + + DFSP1 + + + Payer + + + + + DFSP2 + + + Payee + + + + + DFSP2 + + + Payee + + + + + ML API Adapter + + + + + ML API Adapter + + + + + ML API Notification Event Handler + + + + + ML API Notification Event Handler + + + + + Central Service API + + + + + Central Service API + + + + + + + topic-transfer-prepare + + + + + topic-transfer-prepare + + + Prepare Event Handler + + + + + Prepare Event Handler + + + + + + + topic-transfer-position + + + + + topic-transfer-position + + + Position Event Handler + + + + + Position Event Handler + + + + + + + Notification-Topic + + + + + Notification-Topic + + + + + + DFSP1 sends a Prepare Transfer request to DFSP2 + + + + + Headers - transferHeaders: { + + + Content-Length: <Content-Length>, + + + Content-Type: <Content-Type>, + + + Date: <Date>, + + + X-Forwarded-For: <X-Forwarded-For>, + + + FSPIOP-Source: <FSPIOP-Source>, + + + FSPIOP-Destination: <FSPIOP-Destination>, + + + FSPIOP-Encryption: <FSPIOP-Encryption>, + + + FSPIOP-Signature: <FSPIOP-Signature>, + + + FSPIOP-URI: <FSPIOP-URI>, + + + FSPIOP-HTTP-Method: <FSPIOP-HTTP-Method> + + + } + + + Payload - transferMessage: + + + { + + + "transferId": <uuid>, + + + "payeeFsp": dfsp2, + + + "payerFsp": dfsp1, + + + "amount": { + + + "currency": "AED", + + + "amount": "string" + + + }, + + + "ilpPacket": "string", + + + "condition": "string", + + + "expiration": "string", + + + "extensionList": { + + + "extension": [ + + + { + + + "key": "string", + + + "value": "string" + + + } + + + ] + + + } + + + } + + + + 1 + + + POST - /transfers + + + + + 2 + + + Validate incoming token and originator matching Payer + + + Error codes: + + + 3000-3002, 3100-3107 + + + + + Message: + + + { + + + id: <transferMessage.transferId> + + + from: <transferMessage.payerFsp>, + + + to: <transferMessage.payeeFsp>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + type: prepare, + + + action: prepare, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 3 + + + Route & Publish Prepare event for Payer + + + Error code: + + + 2003 + + + + + 4 + + + Ensure event is replicated as configured (ACKS=all) + + + Error code: + + + 2003 + + + + + 5 + + + Respond replication acknowledgements have been received + + + + + 6 + + + Respond HTTP - 202 (Accepted) + + + + + 7 + + + Consume message + + + + + ref + + + Prepare Handler Consume + + + + + 8 + + + Produce message + + + + + 9 + + + Consume message + + + + + ref + + + Position Handler Consume + + + + + 10 + + + Produce message + + + + + 11 + + + Consume message + + + + + ref + + + Send notification to Participant (Payee) + + + + + 12 + + + Send callback notification + + diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.1.a.plantuml b/docs/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.1.a.plantuml new file mode 100644 index 000000000..4df26eef9 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.1.a.plantuml @@ -0,0 +1,257 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Shashikant Hirugade + * Georgi Georgiev + * Rajiv Mothilal + * Samuel Kummary + * Miguel de Barros + -------------- + ******'/ + +@startuml +' declate title +title 1.1.1.a. Prepare Handler Consume (single message) + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +collections "topic-transfer-prepare" as TOPIC_TRANSFER_PREPARE +control "Prepare Event Handler" as PREP_HANDLER +collections "topic-transfer-position" as TOPIC_TRANSFER_POSITION +collections "Event-Topic" as TOPIC_EVENTS +collections "Notification-Topic" as TOPIC_NOTIFICATIONS +entity "Position DAO" as POS_DAO +entity "Participant DAO" as PARTICIPANT_DAO +database "Central Store" as DB + +box "Central Service" #LightYellow + participant TOPIC_TRANSFER_PREPARE + participant PREP_HANDLER + participant TOPIC_TRANSFER_POSITION + participant TOPIC_EVENTS + participant TOPIC_NOTIFICATIONS + participant POS_DAO + participant PARTICIPANT_DAO + participant DB +end box + +' start flow +activate PREP_HANDLER +group Prepare Handler Consume + TOPIC_TRANSFER_PREPARE <- PREP_HANDLER: Consume Prepare event message + activate TOPIC_TRANSFER_PREPARE + deactivate TOPIC_TRANSFER_PREPARE + + break + group Validate Event + PREP_HANDLER <-> PREP_HANDLER: Validate event - Rule: type == 'prepare' && action == 'prepare'\nError codes: 2001 + end + end + + group Persist Event Information + ||| + PREP_HANDLER -> TOPIC_EVENTS: Publish event information + ref over PREP_HANDLER, TOPIC_EVENTS: Event Handler Consume\n + ||| + end + + group Validate Prepare Transfer + PREP_HANDLER <-> PREP_HANDLER: Schema validation of the incoming message + PREP_HANDLER <-> PREP_HANDLER: Verify the message's signature (to be confirmed in future requirement) + note right of PREP_HANDLER #lightgrey + The above validation steps are already handled by + the ML-Adapter for the open source implementation. + It may need to be added in future for custom adapters. + end note + + group Validate Duplicate Check + ||| + PREP_HANDLER -> DB: Request Duplicate Check + ref over PREP_HANDLER, DB: Request Duplicate Check\n + DB --> PREP_HANDLER: Return { hasDuplicateId: Boolean, hasDuplicateHash: Boolean } + end + + alt hasDuplicateId == TRUE && hasDuplicateHash == TRUE + break + PREP_HANDLER -> PREP_HANDLER: stateRecord = await getTransferState(transferId) + alt endStateList.includes(stateRecord.transferStateId) + ||| + ref over PREP_HANDLER, TOPIC_NOTIFICATIONS: getTransfer callback\n + PREP_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + else + note right of PREP_HANDLER #lightgrey + Ignore - resend in progress + end note + end + end + else hasDuplicateId == TRUE && hasDuplicateHash == FALSE + note right of PREP_HANDLER #lightgrey + Validate Prepare Transfer (failure) - Modified Request + end note + else hasDuplicateId == FALSE + group Validate Payer + PREP_HANDLER -> PARTICIPANT_DAO: Request to retrieve Payer Participant details (if it exists) + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Request Participant details + hnote over DB #lightyellow + participant + participantCurrency + end note + activate DB + PARTICIPANT_DAO <-- DB: Return Participant details if it exists + deactivate DB + PARTICIPANT_DAO --> PREP_HANDLER: Return Participant details if it exists + deactivate PARTICIPANT_DAO + PREP_HANDLER <-> PREP_HANDLER: Validate Payer\nError codes: 3202 + end + group Validate Payee + PREP_HANDLER -> PARTICIPANT_DAO: Request to retrieve Payee Participant details (if it exists) + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Request Participant details + hnote over DB #lightyellow + participant + participantCurrency + end note + activate DB + PARTICIPANT_DAO <-- DB: Return Participant details if it exists + deactivate DB + PARTICIPANT_DAO --> PREP_HANDLER: Return Participant details if it exists + deactivate PARTICIPANT_DAO + PREP_HANDLER <-> PREP_HANDLER: Validate Payee\nError codes: 3203 + end + + alt Validate Prepare Transfer (success) + group Persist Transfer State (with transferState='RECEIVED-PREPARE') + PREP_HANDLER -> POS_DAO: Request to persist transfer\nError codes: 2003 + activate POS_DAO + POS_DAO -> DB: Persist transfer + hnote over DB #lightyellow + transfer + transferParticipant + transferStateChange + transferExtension + ilpPacket + end note + activate DB + deactivate DB + POS_DAO --> PREP_HANDLER: Return success + deactivate POS_DAO + end + else Validate Prepare Transfer (failure) + group Persist Transfer State (with transferState='INVALID') (Introducing a new status INVALID to mark these entries) + PREP_HANDLER -> POS_DAO: Request to persist transfer\n(when Payee/Payer/crypto-condition validation fails)\nError codes: 2003 + activate POS_DAO + POS_DAO -> DB: Persist transfer + hnote over DB #lightyellow + transfer + transferParticipant + transferStateChange + transferExtension + transferError + ilpPacket + end note + activate DB + deactivate DB + POS_DAO --> PREP_HANDLER: Return success + deactivate POS_DAO + end + end + end + end + + alt Validate Prepare Transfer (success) + note right of PREP_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: position, + action: prepare, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + PREP_HANDLER -> TOPIC_TRANSFER_POSITION: Route & Publish Position event for Payer\nError codes: 2003 + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + else Validate Prepare Transfer (failure) + note right of PREP_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: { + "errorInformation": { + "errorCode": + "errorDescription": "", + "extensionList": + } + }, + metadata: { + event: { + id: , + responseTo: , + type: notification, + action: prepare, + createdAt: , + state: { + status: 'error', + code: + description: + } + } + } + } + end note + PREP_HANDLER -> TOPIC_NOTIFICATIONS: Publish Notification (failure) event for Payer\nError codes: 2003 + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + end +end +deactivate PREP_HANDLER +@enduml + diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.1.a.svg b/docs/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.1.a.svg new file mode 100644 index 000000000..65895c97b --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.1.a.svg @@ -0,0 +1,738 @@ + + + + + + + + + + + 1.1.1.a. Prepare Handler Consume (single message) + + + + Central Service + + + + + + + + + + + + + + + + + + + + topic-transfer-prepare + + + + + topic-transfer-prepare + + + Prepare Event Handler + + + + + Prepare Event Handler + + + + + + + topic-transfer-position + + + + + topic-transfer-position + + + + + Event-Topic + + + + + Event-Topic + + + + + Notification-Topic + + + + + Notification-Topic + + + Position DAO + + + + + Position DAO + + + + + Participant DAO + + + + + Participant DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Prepare Handler Consume + + + + + 1 + + + Consume Prepare event message + + + + + break + + + + + Validate Event + + + + + 2 + + + Validate event - Rule: type == 'prepare' && action == 'prepare' + + + Error codes: + + + 2001 + + + + + Persist Event Information + + + + + 3 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + Validate Prepare Transfer + + + + + 4 + + + Schema validation of the incoming message + + + + + 5 + + + Verify the message's signature (to be confirmed in future requirement) + + + + + The above validation steps are already handled by + + + the ML-Adapter for the open source implementation. + + + It may need to be added in future for custom adapters. + + + + + Validate Duplicate Check + + + + + 6 + + + Request Duplicate Check + + + + + ref + + + Request Duplicate Check + + + + + 7 + + + Return { hasDuplicateId: Boolean, hasDuplicateHash: Boolean } + + + + + alt + + + [hasDuplicateId == TRUE && hasDuplicateHash == TRUE] + + + + + break + + + + + 8 + + + stateRecord = await getTransferState(transferId) + + + + + alt + + + [endStateList.includes(stateRecord.transferStateId)] + + + + + ref + + + getTransfer callback + + + + + 9 + + + Produce message + + + + + + Ignore - resend in progress + + + + [hasDuplicateId == TRUE && hasDuplicateHash == FALSE] + + + + + Validate Prepare Transfer (failure) - Modified Request + + + + [hasDuplicateId == FALSE] + + + + + Validate Payer + + + + + 10 + + + Request to retrieve Payer Participant details (if it exists) + + + + + 11 + + + Request Participant details + + + + participant + + + participantCurrency + + + + + 12 + + + Return Participant details if it exists + + + + + 13 + + + Return Participant details if it exists + + + + + 14 + + + Validate Payer + + + Error codes: + + + 3202 + + + + + Validate Payee + + + + + 15 + + + Request to retrieve Payee Participant details (if it exists) + + + + + 16 + + + Request Participant details + + + + participant + + + participantCurrency + + + + + 17 + + + Return Participant details if it exists + + + + + 18 + + + Return Participant details if it exists + + + + + 19 + + + Validate Payee + + + Error codes: + + + 3203 + + + + + alt + + + [Validate Prepare Transfer (success)] + + + + + Persist Transfer State (with transferState='RECEIVED-PREPARE') + + + + + 20 + + + Request to persist transfer + + + Error codes: + + + 2003 + + + + + 21 + + + Persist transfer + + + + transfer + + + transferParticipant + + + transferStateChange + + + transferExtension + + + ilpPacket + + + + + 22 + + + Return success + + + + [Validate Prepare Transfer (failure)] + + + + + Persist Transfer State (with transferState='INVALID') (Introducing a new status INVALID to mark these entries) + + + + + 23 + + + Request to persist transfer + + + (when Payee/Payer/crypto-condition validation fails) + + + Error codes: + + + 2003 + + + + + 24 + + + Persist transfer + + + + transfer + + + transferParticipant + + + transferStateChange + + + transferExtension + + + transferError + + + ilpPacket + + + + + 25 + + + Return success + + + + + alt + + + [Validate Prepare Transfer (success)] + + + + + Message: + + + { + + + id: <transferMessage.transferId> + + + from: <transferMessage.payerFsp>, + + + to: <transferMessage.payeeFsp>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: position, + + + action: prepare, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 26 + + + Route & Publish Position event for Payer + + + Error codes: + + + 2003 + + + + [Validate Prepare Transfer (failure)] + + + + + Message: + + + { + + + id: <transferMessage.transferId> + + + from: <ledgerName>, + + + to: <transferMessage.payerFsp>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: { + + + "errorInformation": { + + + "errorCode": <possible codes: [2003, 3100, 3105, 3106, 3202, 3203, 3300, 3301]> + + + "errorDescription": "<refer to section 35.1.3 for description>", + + + "extensionList": <transferMessage.extensionList> + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: notification, + + + action: prepare, + + + createdAt: <timestamp>, + + + state: { + + + status: 'error', + + + code: <errorInformation.errorCode> + + + description: <errorInformation.errorDescription> + + + } + + + } + + + } + + + } + + + + + 27 + + + Publish Notification (failure) event for Payer + + + Error codes: + + + 2003 + + diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.1.b.plantuml b/docs/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.1.b.plantuml new file mode 100644 index 000000000..1b01ef9c5 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.1.b.plantuml @@ -0,0 +1,186 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Miguel de Barros + -------------- + ******'/ + +@startuml +' declate title +title 1.1.1.b. Prepare Handler Consume (batch messages) + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +collections "topic-transfer-prepare" as TOPIC_TRANSFER_PREPARE +control "Prepare Event Handler" as PREP_HANDLER +collections "topic-transfer-position" as TOPIC_TRANSFER_POSITION +collections "Event-Topic" as TOPIC_EVENTS +collections "Notification-Topic" as TOPIC_NOTIFICATIONS +entity "Position DAO" as POS_DAO +entity "Participant DAO" as PARTICIPANT_DAO +database "Central Store" as DB + +box "Central Service" #LightYellow + participant TOPIC_TRANSFER_PREPARE + participant PREP_HANDLER + participant TOPIC_TRANSFER_POSITION + participant TOPIC_EVENTS + participant TOPIC_NOTIFICATIONS + participant POS_DAO + participant PARTICIPANT_DAO + participant DB +end box + +' start flow +activate PREP_HANDLER +group Prepare Handler Consume + note over TOPIC_TRANSFER_PREPARE #LightSalmon + This flow has not been implemented + end note + + TOPIC_TRANSFER_PREPARE <- PREP_HANDLER: Consume Prepare event batch of messages for Payer + activate TOPIC_TRANSFER_PREPARE + deactivate TOPIC_TRANSFER_PREPARE + group Persist Event Information + ||| + PREP_HANDLER -> TOPIC_EVENTS: Publish event information + ref over PREP_HANDLER, TOPIC_EVENTS : Event Handler Consume\n + ||| + end + + group Fetch batch Payer information + PREP_HANDLER -> PARTICIPANT_DAO: Request to retrieve batch of Payer Participant details (if it exists) + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Request Participant details + hnote over DB #lightyellow + participant + end note + activate DB + PARTICIPANT_DAO <-- DB: Return Participant details if it exists + deactivate DB + PARTICIPANT_DAO --> PREP_HANDLER: Return Participant details if it exists + deactivate PARTICIPANT_DAO + PREP_HANDLER <-> PREP_HANDLER: Validate Payer + PREP_HANDLER -> PREP_HANDLER: store result set in var: $LIST_PARTICIPANTS_DETAILS_PAYER + end + + group Fetch batch Payee information + PREP_HANDLER -> PARTICIPANT_DAO: Request to retrieve batch of Payee Participant details (if it exists) + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Request Participant details + hnote over DB #lightyellow + participant + end note + activate DB + PARTICIPANT_DAO <-- DB: Return Participant details if it exists + deactivate DB + PARTICIPANT_DAO --> PREP_HANDLER: Return Participant details if it exists + deactivate PARTICIPANT_DAO + PREP_HANDLER <-> PREP_HANDLER: Validate Payee + PREP_HANDLER -> PREP_HANDLER: store result set in var: $LIST_PARTICIPANTS_DETAILS_PAYEE + end + + group Fetch batch of transfers + PREP_HANDLER -> POS_DAO: Request to retrieve batch of Transfers (if it exists) + activate POS_DAO + POS_DAO -> DB: Request batch of Transfers + hnote over DB #lightyellow + transfer + end note + activate DB + POS_DAO <-- DB: Return batch of Transfers (if it exists) + deactivate DB + POS_DAO --> PREP_HANDLER: Return batch of Transfer (if it exists) + deactivate POS_DAO + PREP_HANDLER -> PREP_HANDLER: store result set in var: $LIST_TRANSFERS + end + + loop for each message in batch + + group Validate Prepare Transfer + group Validate Payer + PREP_HANDLER <-> PREP_HANDLER: Validate Payer against in-memory var $LIST_PARTICIPANTS_DETAILS_PAYER + end + group Validate Payee + PREP_HANDLER <-> PREP_HANDLER: Validate Payee against in-memory var $LIST_PARTICIPANTS_DETAILS_PAYEE + end + group Duplicate check + PREP_HANDLER <-> PREP_HANDLER: Validate duplicate Check against in-memory var $LIST_TRANSFERS + end + PREP_HANDLER <-> PREP_HANDLER: Validate amount + PREP_HANDLER <-> PREP_HANDLER: Validate crypto-condition + PREP_HANDLER <-> PREP_HANDLER: Validate message signature (to be confirmed in future requirement) + end + + group Persist Transfer State (with transferState='RECEIVED' on validation pass) + PREP_HANDLER -> POS_DAO: Request to persist transfer + activate POS_DAO + POS_DAO -> DB: Persist transfer + hnote over DB #lightyellow + transferStateChange + end note + activate DB + deactivate DB + POS_DAO --> PREP_HANDLER: Return success + deactivate POS_DAO + end + + note right of PREP_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: position, + action: prepare, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + PREP_HANDLER -> TOPIC_TRANSFER_POSITION: Route & Publish Position event for Payer + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + end +end +deactivate PREP_HANDLER +@enduml diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.1.b.svg b/docs/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.1.b.svg new file mode 100644 index 000000000..13489faa8 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.1.b.svg @@ -0,0 +1,497 @@ + + + + + + + + + + + 1.1.1.b. Prepare Handler Consume (batch messages) + + + + Central Service + + + + + + + + + + + topic-transfer-prepare + + + + + topic-transfer-prepare + + + Prepare Event Handler + + + + + Prepare Event Handler + + + + + + + topic-transfer-position + + + + + topic-transfer-position + + + + + Event-Topic + + + + + Event-Topic + + + + + Notification-Topic + + + + + Notification-Topic + + + Position DAO + + + + + Position DAO + + + + + Participant DAO + + + + + Participant DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Prepare Handler Consume + + + + + This flow has not been implemented + + + + + 1 + + + Consume Prepare event batch of messages for Payer + + + + + Persist Event Information + + + + + 2 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + Fetch batch Payer information + + + + + 3 + + + Request to retrieve batch of Payer Participant details (if it exists) + + + + + 4 + + + Request Participant details + + + + participant + + + + + 5 + + + Return Participant details if it exists + + + + + 6 + + + Return Participant details if it exists + + + + + 7 + + + Validate Payer + + + + + 8 + + + store result set in var: $LIST_PARTICIPANTS_DETAILS_PAYER + + + + + Fetch batch Payee information + + + + + 9 + + + Request to retrieve batch of Payee Participant details (if it exists) + + + + + 10 + + + Request Participant details + + + + participant + + + + + 11 + + + Return Participant details if it exists + + + + + 12 + + + Return Participant details if it exists + + + + + 13 + + + Validate Payee + + + + + 14 + + + store result set in var: $LIST_PARTICIPANTS_DETAILS_PAYEE + + + + + Fetch batch of transfers + + + + + 15 + + + Request to retrieve batch of Transfers (if it exists) + + + + + 16 + + + Request batch of Transfers + + + + transfer + + + + + 17 + + + Return batch of Transfers (if it exists) + + + + + 18 + + + Return batch of Transfer (if it exists) + + + + + 19 + + + store result set in var: $LIST_TRANSFERS + + + + + loop + + + [for each message in batch] + + + + + Validate Prepare Transfer + + + + + Validate Payer + + + + + 20 + + + Validate Payer against in-memory var $LIST_PARTICIPANTS_DETAILS_PAYER + + + + + Validate Payee + + + + + 21 + + + Validate Payee against in-memory var $LIST_PARTICIPANTS_DETAILS_PAYEE + + + + + Duplicate check + + + + + 22 + + + Validate duplicate Check against in-memory var $LIST_TRANSFERS + + + + + 23 + + + Validate amount + + + + + 24 + + + Validate crypto-condition + + + + + 25 + + + Validate message signature (to be confirmed in future requirement) + + + + + Persist Transfer State (with transferState='RECEIVED' on validation pass) + + + + + 26 + + + Request to persist transfer + + + + + 27 + + + Persist transfer + + + + transferStateChange + + + + + 28 + + + Return success + + + + + Message: + + + { + + + id: <transferMessage.transferId> + + + from: <transferMessage.payerFsp>, + + + to: <transferMessage.payeeFsp>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: position, + + + action: prepare, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 29 + + + Route & Publish Position event for Payer + + diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.2.a.plantuml b/docs/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.2.a.plantuml new file mode 100644 index 000000000..abec38aa9 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.2.a.plantuml @@ -0,0 +1,249 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Miguel de Barros + -------------- + ******'/ + +@startuml +' declate title +title 1.1.2.a. Position Handler Consume (single message) + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +collections "topic-transfer-position" as TOPIC_TRANSFER_POSITION +control "Position Event Handler" as POS_HANDLER +entity "Position DAO" as POS_DAO +collections "Event-Topic" as TOPIC_EVENTS +collections "Notification-Topic" as TOPIC_NOTIFICATIONS +entity "Participant DAO" as PARTICIPANT_DAO +database "Central Store" as DB + +box "Central Service" #LightYellow + participant TOPIC_TRANSFER_POSITION + participant POS_HANDLER + participant TOPIC_EVENTS + participant TOPIC_NOTIFICATIONS + participant POS_DAO + participant PARTICIPANT_DAO + participant DB +end box + +' start flow +activate POS_HANDLER +group Position Handler Consume + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume Position event message for Payer + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + + break + group Validate Event + POS_HANDLER <-> POS_HANDLER: Validate event - Rule: type == 'position' && action == 'prepare' + end + end + + group Persist Event Information + ||| + POS_HANDLER -> TOPIC_EVENTS: Publish event information + ref over POS_HANDLER, TOPIC_EVENTS : Event Handler Consume\n + ||| + end + + alt Calulate & Validate Latest Position (success) + group Calculate position and persist change + POS_HANDLER -> POS_DAO: Request latest position from DB for Payer + activate POS_DAO + POS_DAO -> DB: Retrieve latest position from DB for Payer + activate DB + hnote over DB #lightyellow + transferPosition + end note + DB --> POS_DAO: Retrieve latest position from DB for Payer + deactivate DB + POS_DAO --> POS_HANDLER: Return latest position + deactivate POS_DAO + + POS_HANDLER -> PARTICIPANT_DAO: Request position limits for Payer Participant + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Request position limits for Payer Participant + activate DB + hnote over DB #lightyellow + participant + participantLimit + end note + DB --> PARTICIPANT_DAO: Return position limits + deactivate DB + deactivate DB + PARTICIPANT_DAO --> POS_HANDLER: Return position limits + deactivate PARTICIPANT_DAO + + POS_HANDLER <-> POS_HANDLER: Calculate latest position (lpos) for prepare + POS_HANDLER <-> POS_HANDLER: Validate Calculated latest position against the net-debit cap (netcap) - Rule: lpos < netcap + + POS_HANDLER -> POS_DAO: Request to persist latest position for Payer + activate POS_DAO + POS_DAO -> DB: Persist latest position to DB for Payer + hnote over DB #lightyellow + transferPosition + end note + activate DB + deactivate DB + POS_DAO --> POS_HANDLER: Return success + deactivate POS_DAO + end + + group Persist Transfer State (with transferState='RESERVED' on position check pass) + POS_HANDLER -> POS_DAO: Request to persist transfer + activate POS_DAO + POS_DAO -> DB: Persist transfer state + hnote over DB #lightyellow + transferStateChange + end note + activate DB + deactivate DB + POS_DAO --> POS_HANDLER: Return success + deactivate POS_DAO + end + + note right of POS_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: transfer, + action: prepare, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + POS_HANDLER -> TOPIC_NOTIFICATIONS: Publish Notification event to Payee + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + else Calculate & Validate Latest Position (failure) + group Calculate position and persist change + POS_HANDLER -> POS_DAO: Request latest position from DB for Payer + activate POS_DAO + POS_DAO -> DB: Retrieve latest position from DB for Payer + activate DB + hnote over DB #lightyellow + transferPosition + end note + DB --> POS_DAO: Retrieve latest position from DB for Payer + deactivate DB + deactivate DB + POS_DAO --> POS_HANDLER: Return latest position + deactivate POS_DAO + + POS_HANDLER -> PARTICIPANT_DAO: Request position limits for Payer Participant + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Request position limits for Payer Participant + activate DB + hnote over DB #lightyellow + participant + participantLimit + end note + DB --> PARTICIPANT_DAO: Return position limits + deactivate DB + deactivate DB + PARTICIPANT_DAO --> POS_HANDLER: Return position limits + deactivate PARTICIPANT_DAO + + POS_HANDLER <-> POS_HANDLER: Calculate latest position (lpos) for prepare + POS_HANDLER <-> POS_HANDLER: Validate Calculated latest position against the net-debit cap (netcap) - Rule: lpos < netcap + note right of POS_HANDLER #red: Validation failure! + end + + group Persist Transfer State (with transferState='ABORTED' on position check pass) + POS_HANDLER -> POS_DAO: Request to persist transfer + activate POS_DAO + POS_DAO -> DB: Persist transfer state + hnote over DB #lightyellow + transferStateChange + end note + activate DB + deactivate DB + POS_DAO --> POS_HANDLER: Return success + deactivate POS_DAO + end + + note right of POS_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: { + "errorInformation": { + "errorCode": 4001, + "errorDescription": "Payer FSP insufficient liquidity", + "extensionList": + } + }, + metadata: { + event: { + id: , + responseTo: , + type: notification, + action: prepare, + createdAt: , + state: { + status: 'error', + code: + description: + } + } + } + } + end note + POS_HANDLER -> TOPIC_NOTIFICATIONS: Publish Notification (failure) event for Payer + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + deactivate POS_HANDLER + end +end +deactivate POS_HANDLER +@enduml diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.2.a.svg b/docs/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.2.a.svg new file mode 100644 index 000000000..2a0857acf --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.2.a.svg @@ -0,0 +1,633 @@ + + + + + + + + + + + 1.1.2.a. Position Handler Consume (single message) + + + + Central Service + + + + + + + + + + + + + topic-transfer-position + + + + + topic-transfer-position + + + Position Event Handler + + + + + Position Event Handler + + + + + + + Event-Topic + + + + + Event-Topic + + + + + Notification-Topic + + + + + Notification-Topic + + + Position DAO + + + + + Position DAO + + + + + Participant DAO + + + + + Participant DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Position Handler Consume + + + + + 1 + + + Consume Position event message for Payer + + + + + break + + + + + Validate Event + + + + + 2 + + + Validate event - Rule: type == 'position' && action == 'prepare' + + + + + Persist Event Information + + + + + 3 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + alt + + + [Calulate & Validate Latest Position (success)] + + + + + Calculate position and persist change + + + + + 4 + + + Request latest position from DB for Payer + + + + + 5 + + + Retrieve latest position from DB for Payer + + + + transferPosition + + + + + 6 + + + Retrieve latest position from DB for Payer + + + + + 7 + + + Return latest position + + + + + 8 + + + Request position limits for Payer Participant + + + + + 9 + + + Request position limits for Payer Participant + + + + participant + + + participantLimit + + + + + 10 + + + Return position limits + + + + + 11 + + + Return position limits + + + + + 12 + + + Calculate latest position (lpos) for prepare + + + + + 13 + + + Validate Calculated latest position against the net-debit cap (netcap) - Rule: lpos < netcap + + + + + 14 + + + Request to persist latest position for Payer + + + + + 15 + + + Persist latest position to DB for Payer + + + + transferPosition + + + + + 16 + + + Return success + + + + + Persist Transfer State (with transferState='RESERVED' on position check pass) + + + + + 17 + + + Request to persist transfer + + + + + 18 + + + Persist transfer state + + + + transferStateChange + + + + + 19 + + + Return success + + + + + Message: + + + { + + + id: <transferMessage.transferId> + + + from: <transferMessage.payerFsp>, + + + to: <transferMessage.payeeFsp>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: transfer, + + + action: prepare, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 20 + + + Publish Notification event to Payee + + + + [Calculate & Validate Latest Position (failure)] + + + + + Calculate position and persist change + + + + + 21 + + + Request latest position from DB for Payer + + + + + 22 + + + Retrieve latest position from DB for Payer + + + + transferPosition + + + + + 23 + + + Retrieve latest position from DB for Payer + + + + + 24 + + + Return latest position + + + + + 25 + + + Request position limits for Payer Participant + + + + + 26 + + + Request position limits for Payer Participant + + + + participant + + + participantLimit + + + + + 27 + + + Return position limits + + + + + 28 + + + Return position limits + + + + + 29 + + + Calculate latest position (lpos) for prepare + + + + + 30 + + + Validate Calculated latest position against the net-debit cap (netcap) - Rule: lpos < netcap + + + + + Validation failure! + + + + + Persist Transfer State (with transferState='ABORTED' on position check pass) + + + + + 31 + + + Request to persist transfer + + + + + 32 + + + Persist transfer state + + + + transferStateChange + + + + + 33 + + + Return success + + + + + Message: + + + { + + + id: <transferMessage.transferId> + + + from: <ledgerName>, + + + to: <transferMessage.payerFsp>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: { + + + "errorInformation": { + + + "errorCode": 4001, + + + "errorDescription": "Payer FSP insufficient liquidity", + + + "extensionList": <transferMessage.extensionList> + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: notification, + + + action: prepare, + + + createdAt: <timestamp>, + + + state: { + + + status: 'error', + + + code: <errorInformation.errorCode> + + + description: <errorInformation.errorDescription> + + + } + + + } + + + } + + + } + + + + + 34 + + + Publish Notification (failure) event for Payer + + diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.2.b.plantuml b/docs/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.2.b.plantuml new file mode 100644 index 000000000..9e9bc1ff9 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.2.b.plantuml @@ -0,0 +1,148 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Miguel de Barros + -------------- + ******'/ + +@startuml +' declate title +title 1.1.2.b. Position Handler Consume (batch messages) + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +collections "topic-transfer-position" as TOPIC_TRANSFER_POSITION +control "Position Event Handler" as POS_HANDLER +collections "Transfer-Topic" as TOPIC_TRANSFERS +entity "Position DAO" as POS_DAO +entity "Event-Topic" as TOPIC_EVENTS +collections "Notification-Topic" as TOPIC_NOTIFICATIONS +entity "Transfer DAO" as TRANS_DAO +database "Central Store" as DB + +box "Central Service" #LightYellow + participant TOPIC_TRANSFER_POSITION + participant POS_HANDLER + participant TOPIC_TRANSFERS + participant TOPIC_EVENTS + participant TOPIC_NOTIFICATIONS + participant POS_DAO + participant TRANS_DAO + participant DB +end box + +' start flow +activate POS_HANDLER +group Position Handler Consume + note over TOPIC_TRANSFER_POSITION #LightSalmon + This flow has not been implemented + end note + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume Position event batch of messages for Payer + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + + group Persist Event Information + ||| + POS_HANDLER -> TOPIC_EVENTS: Publish event information + ref over POS_HANDLER, TOPIC_EVENTS : Event Handler Consume\n + ||| + end + + loop for each message in batch + group Calculate position and persist change + POS_HANDLER -> POS_DAO: Request latest position from DB for Payer + activate POS_DAO + POS_DAO -> DB: Retrieve latest position from DB for Payer + hnote over DB #lightyellow + transferPosition + end note + activate DB + deactivate DB + POS_DAO --> POS_HANDLER: Return latest position + deactivate POS_DAO + + POS_HANDLER <-> POS_HANDLER: Calculate latest position (lpos) by incrementing transfer for prepare + POS_HANDLER <-> POS_HANDLER: Validate Calculated latest position against the net-debit cap (netcap) - Rule: lpos < netcap + + POS_HANDLER -> POS_DAO: Request to persist latest position for Payer + activate POS_DAO + POS_DAO -> DB: Persist latest position to DB for Payer + hnote over DB #lightyellow + transferPosition + end note + activate DB + deactivate DB + POS_DAO --> POS_HANDLER: Return success + deactivate POS_DAO + end + group Persist Transfer State (with transferState='RESERVED' on position check pass) + POS_HANDLER -> TRANS_DAO: Request to persist batch transfer + activate TRANS_DAO + TRANS_DAO -> DB: Persist batch transfer + hnote over DB #lightyellow + transferStateChange + end note + activate DB + deactivate DB + TRANS_DAO --> POS_HANDLER: Return success + deactivate TRANS_DAO + end + note right of POS_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: application/json + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: transfer, + action: prepare, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + POS_HANDLER -> TOPIC_TRANSFERS: Publish Transfer event + activate TOPIC_TRANSFERS + deactivate TOPIC_TRANSFERS + end +end +deactivate POS_HANDLER +@enduml diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.2.b.svg b/docs/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.2.b.svg new file mode 100644 index 000000000..3b1dd63b4 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.2.b.svg @@ -0,0 +1,342 @@ + + + + + + + + + + + 1.1.2.b. Position Handler Consume (batch messages) + + + + Central Service + + + + + + + + + + topic-transfer-position + + + + + topic-transfer-position + + + Position Event Handler + + + + + Position Event Handler + + + + + + + Transfer-Topic + + + + + Transfer-Topic + + + Event-Topic + + + + + Event-Topic + + + + + + + Notification-Topic + + + + + Notification-Topic + + + Position DAO + + + + + Position DAO + + + + + Transfer DAO + + + + + Transfer DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Position Handler Consume + + + + + This flow has not been implemented + + + + + 1 + + + Consume Position event batch of messages for Payer + + + + + Persist Event Information + + + + + 2 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + loop + + + [for each message in batch] + + + + + Calculate position and persist change + + + + + 3 + + + Request latest position from DB for Payer + + + + + 4 + + + Retrieve latest position from DB for Payer + + + + transferPosition + + + + + 5 + + + Return latest position + + + + + 6 + + + Calculate latest position (lpos) by incrementing transfer for prepare + + + + + 7 + + + Validate Calculated latest position against the net-debit cap (netcap) - Rule: lpos < netcap + + + + + 8 + + + Request to persist latest position for Payer + + + + + 9 + + + Persist latest position to DB for Payer + + + + transferPosition + + + + + 10 + + + Return success + + + + + Persist Transfer State (with transferState='RESERVED' on position check pass) + + + + + 11 + + + Request to persist batch transfer + + + + + 12 + + + Persist batch transfer + + + + transferStateChange + + + + + 13 + + + Return success + + + + + Message: + + + { + + + id: <transferMessage.transferId> + + + from: <transferMessage.payerFsp>, + + + to: <transferMessage.payeeFsp>, + + + type: application/json + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: transfer, + + + action: prepare, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 14 + + + Publish Transfer event + + diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.a-v1.1.plantuml b/docs/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.a-v1.1.plantuml new file mode 100644 index 000000000..fc35e5b8b --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.a-v1.1.plantuml @@ -0,0 +1,123 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Miguel de Barros + * Shashikant Hirugade + * Valentin Genev + -------------- + ******'/ + +@startuml +' declate title +title 1.1.4.a. Send notification to Participant (Payer/Payee) (single message) v1.1 + +autonumber + +' Actor Keys: +' actor - Payer DFSP, Payee DFSP +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +actor "Payer DFSP\nParticipant" as PAYER_DFSP +actor "Payee DFSP\nParticipant" as PAYEE_DFSP +control "ML API Notification Event Handler" as NOTIFY_HANDLER +boundary "Central Service API" as CSAPI +collections "Notification-Topic" as TOPIC_NOTIFICATIONS +collections "Event-Topic" as TOPIC_EVENTS +entity "Participant DAO" as PARTICIPANT_DAO +database "Central Store" as DB + +box "Financial Service Provider (Payer)" #lightGray + participant PAYER_DFSP +end box + +box "ML API Adapter Service" #LightBlue + participant NOTIFY_HANDLER +end box + +box "Central Service" #LightYellow + participant TOPIC_NOTIFICATIONS + participant CSAPI + participant TOPIC_EVENTS + participant PARTICIPANT_DAO + participant DB +end box + +box "Financial Service Provider (Payee)" #lightGray + participant PAYEE_DFSP +end box + +' start flow +activate NOTIFY_HANDLER +group Send notification to Participants + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume Notification event + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + + group Persist Event Information + NOTIFY_HANDLER -> CSAPI: Request to persist event information - POST - /events + activate CSAPI + CSAPI -> TOPIC_EVENTS: Publish event information + activate TOPIC_EVENTS + ||| + ref over TOPIC_EVENTS : Event Handler Consume\n + ||| + TOPIC_EVENTS --> CSAPI: Return success + deactivate TOPIC_EVENTS + CSAPI --> NOTIFY_HANDLER: Return success + deactivate CSAPI + end + note right of NOTIFY_HANDLER #lightgray + The endpoint details are cached, when the cache + expires, the details are fetched again + end note + NOTIFY_HANDLER -> CSAPI: Request Endpoint details for Participant - GET - /participants/{{fsp}}/endpoints\nError code: 2003 + + activate CSAPI + CSAPI -> PARTICIPANT_DAO: Fetch Endpoint details for Participant\nError code: 2003 + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Fetch Endpoint details for Participant + activate DB + hnote over DB #lightyellow + participantEndpoint + end note + DB -> PARTICIPANT_DAO: Retrieved Endpoint details for Participant + deactivate DB + PARTICIPANT_DAO --> CSAPI: Return Endpoint details for Participant + deactivate PARTICIPANT_DAO + CSAPI --> NOTIFY_HANDLER: Return Endpoint details for Participant\nError codes: 3202, 3203 + deactivate CSAPI + NOTIFY_HANDLER -> PAYER_DFSP: Notification with Prepare/fulfil result/error to \nPayer DFSP to specified Endpoint - PUT \nError code: 1001 + NOTIFY_HANDLER <-- PAYER_DFSP: HTTP 200 OK + alt event.action === 'reserve' + alt event.status === 'success' + NOTIFY_HANDLER -> PAYEE_DFSP: Notification to with succesful fulfil result (committed) to Payee DFSP to specified Endpoint - PATCH \nError code: 1001 + ||| + NOTIFY_HANDLER <-- PAYEE_DFSP: HTTP 200 OK + end + end +end +deactivate NOTIFY_HANDLER +@enduml diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.a-v1.1.svg b/docs/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.a-v1.1.svg new file mode 100644 index 000000000..7461e0ab9 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.a-v1.1.svg @@ -0,0 +1,326 @@ + + + + + + + + + + + 1.1.4.a. Send notification to Participant (Payer/Payee) (single message) v1.1 + + + + Financial Service Provider (Payer) + + + + ML API Adapter Service + + + + Central Service + + + + Financial Service Provider (Payee) + + + + + + + + Payer DFSP + + + Participant + + + + + Payer DFSP + + + Participant + + + + + ML API Notification Event Handler + + + + + ML API Notification Event Handler + + + + + + + Notification-Topic + + + + + Notification-Topic + + + Central Service API + + + + + Central Service API + + + + + + + Event-Topic + + + + + Event-Topic + + + Participant DAO + + + + + Participant DAO + + + + + Central Store + + + + + Central Store + + + + + Payee DFSP + + + Participant + + + + + Payee DFSP + + + Participant + + + + + + + + Send notification to Participants + + + + + 1 + + + Consume Notification event + + + + + Persist Event Information + + + + + 2 + + + Request to persist event information - POST - /events + + + + + 3 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + 4 + + + Return success + + + + + 5 + + + Return success + + + + + The endpoint details are cached, when the cache + + + expires, the details are fetched again + + + + + 6 + + + Request Endpoint details for Participant - GET - /participants/{{fsp}}/endpoints + + + Error code: + + + 2003 + + + + + 7 + + + Fetch Endpoint details for Participant + + + Error code: + + + 2003 + + + + + 8 + + + Fetch Endpoint details for Participant + + + + participantEndpoint + + + + + 9 + + + Retrieved Endpoint details for Participant + + + + + 10 + + + Return Endpoint details for Participant + + + + + 11 + + + Return Endpoint details for Participant + + + Error codes: + + + 3202, 3203 + + + + + 12 + + + Notification with Prepare/fulfil result/error to + + + Payer DFSP to specified Endpoint - PUT + + + Error code: + + + 1001 + + + + + 13 + + + HTTP 200 OK + + + + + alt + + + [event.action === 'reserve'] + + + + + alt + + + [event.status === 'success'] + + + + + 14 + + + Notification to with succesful fulfil result (committed) to Payee DFSP to specified Endpoint - PATCH + + + Error code: + + + 1001 + + + + + 15 + + + HTTP 200 OK + + diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.a.plantuml b/docs/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.a.plantuml new file mode 100644 index 000000000..b96130bf1 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.a.plantuml @@ -0,0 +1,120 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Miguel de Barros + * Shashikant Hirugade + -------------- + ******'/ + +@startuml +' declate title +title 1.1.4.a. Send notification to Participant (Payer/Payee) (single message) + +autonumber + +' Actor Keys: +' actor - Payer DFSP, Payee DFSP +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +actor "Payer DFSP\nParticipant" as PAYER_DFSP +actor "Payee DFSP\nParticipant" as PAYEE_DFSP +control "ML API Notification Event Handler" as NOTIFY_HANDLER +boundary "Central Service API" as CSAPI +collections "Notification-Topic" as TOPIC_NOTIFICATIONS +collections "Event-Topic" as TOPIC_EVENTS +entity "Participant DAO" as PARTICIPANT_DAO +database "Central Store" as DB + +box "Financial Service Provider (Payer)" #lightGray + participant PAYER_DFSP +end box + +box "ML API Adapter Service" #LightBlue + participant NOTIFY_HANDLER +end box + +box "Central Service" #LightYellow + participant TOPIC_NOTIFICATIONS + participant CSAPI + participant TOPIC_EVENTS + participant PARTICIPANT_DAO + participant DB +end box + +box "Financial Service Provider (Payee)" #lightGray + participant PAYEE_DFSP +end box + +' start flow +activate NOTIFY_HANDLER +group Send notification to Participants + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume Notification event + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + + group Persist Event Information + NOTIFY_HANDLER -> CSAPI: Request to persist event information - POST - /events + activate CSAPI + CSAPI -> TOPIC_EVENTS: Publish event information + activate TOPIC_EVENTS + ||| + ref over TOPIC_EVENTS : Event Handler Consume\n + ||| + TOPIC_EVENTS --> CSAPI: Return success + deactivate TOPIC_EVENTS + CSAPI --> NOTIFY_HANDLER: Return success + deactivate CSAPI + end + note right of NOTIFY_HANDLER #lightgray + The endpoint details are cached, when the cache + expires, the details are fetched again + end note + NOTIFY_HANDLER -> CSAPI: Request Endpoint details for Participant - GET - /participants/{{fsp}}/endpoints\nError code: 2003 + + activate CSAPI + CSAPI -> PARTICIPANT_DAO: Fetch Endpoint details for Participant\nError code: 2003 + activate PARTICIPANT_DAO + PARTICIPANT_DAO -> DB: Fetch Endpoint details for Participant + activate DB + hnote over DB #lightyellow + participantEndpoint + end note + DB -> PARTICIPANT_DAO: Retrieved Endpoint details for Participant + deactivate DB + PARTICIPANT_DAO --> CSAPI: Return Endpoint details for Participant + deactivate PARTICIPANT_DAO + CSAPI --> NOTIFY_HANDLER: Return Endpoint details for Participant\nError codes: 3202, 3203 + deactivate CSAPI + NOTIFY_HANDLER -> PAYER_DFSP: Notification with Prepare/fulfil result/error to \nPayer DFSP to specified Endpoint - PUT \nError code: 1001 + NOTIFY_HANDLER <-- PAYER_DFSP: HTTP 200 OK + alt Config.SEND_TRANSFER_CONFIRMATION_TO_PAYEE === true + NOTIFY_HANDLER -> PAYEE_DFSP: Notification to with fulfil result (committed/aborted/rejected) to Payee DFSP to specified Endpoint - PUT \nError code: 1001 + ||| + NOTIFY_HANDLER <-- PAYEE_DFSP: HTTP 200 OK + end +end +deactivate NOTIFY_HANDLER +@enduml diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.a.svg b/docs/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.a.svg new file mode 100644 index 000000000..de654e47e --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.a.svg @@ -0,0 +1,317 @@ + + + + + + + + + + + 1.1.4.a. Send notification to Participant (Payer/Payee) (single message) + + + + Financial Service Provider (Payer) + + + + ML API Adapter Service + + + + Central Service + + + + Financial Service Provider (Payee) + + + + + + + Payer DFSP + + + Participant + + + + + Payer DFSP + + + Participant + + + + + ML API Notification Event Handler + + + + + ML API Notification Event Handler + + + + + + + Notification-Topic + + + + + Notification-Topic + + + Central Service API + + + + + Central Service API + + + + + + + Event-Topic + + + + + Event-Topic + + + Participant DAO + + + + + Participant DAO + + + + + Central Store + + + + + Central Store + + + + + Payee DFSP + + + Participant + + + + + Payee DFSP + + + Participant + + + + + + + + Send notification to Participants + + + + + 1 + + + Consume Notification event + + + + + Persist Event Information + + + + + 2 + + + Request to persist event information - POST - /events + + + + + 3 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + 4 + + + Return success + + + + + 5 + + + Return success + + + + + The endpoint details are cached, when the cache + + + expires, the details are fetched again + + + + + 6 + + + Request Endpoint details for Participant - GET - /participants/{{fsp}}/endpoints + + + Error code: + + + 2003 + + + + + 7 + + + Fetch Endpoint details for Participant + + + Error code: + + + 2003 + + + + + 8 + + + Fetch Endpoint details for Participant + + + + participantEndpoint + + + + + 9 + + + Retrieved Endpoint details for Participant + + + + + 10 + + + Return Endpoint details for Participant + + + + + 11 + + + Return Endpoint details for Participant + + + Error codes: + + + 3202, 3203 + + + + + 12 + + + Notification with Prepare/fulfil result/error to + + + Payer DFSP to specified Endpoint - PUT + + + Error code: + + + 1001 + + + + + 13 + + + HTTP 200 OK + + + + + alt + + + [Config.SEND_TRANSFER_CONFIRMATION_TO_PAYEE === true] + + + + + 14 + + + Notification to with fulfil result (committed/aborted/rejected) to Payee DFSP to specified Endpoint - PUT + + + Error code: + + + 1001 + + + + + 15 + + + HTTP 200 OK + + diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.b.plantuml b/docs/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.b.plantuml new file mode 100644 index 000000000..0c5c5fb5d --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.b.plantuml @@ -0,0 +1,108 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + * Miguel de Barros + -------------- + ******'/ + +@startuml +' declate title +title 1.1.4.b. Send notification to Participant (Payer/Payee) (batch messages) + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +actor "DFSP(n)\nParticipant" as DFSP +control "ML API Notification Event Handler" as NOTIFY_HANDLER +boundary "Central Service API" as CSAPI +collections "Notification-Topic" as TOPIC_NOTIFICATIONS +collections "Event-Topic" as TOPIC_EVENTS +entity "Notification DAO" as NOTIFY_DAO +database "Central Store" as DB + +box "Financial Service Provider" #lightGray + participant DFSP +end box + +box "ML API Adapter Service" #LightBlue + participant NOTIFY_HANDLER +end box + +box "Central Service" #LightYellow +participant TOPIC_NOTIFICATIONS + participant CSAPI + participant TOPIC_EVENTS + participant EVENT_DAO + participant NOTIFY_DAO + participant DB +end box + +' start flow +activate NOTIFY_HANDLER +group Send notification to Participant + note over DFSP #LightSalmon + This flow has not been implemented + end note + + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: **Consume Notifications event batch of messages for Participant** + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + loop for each message in batch + group Persist Event Information + NOTIFY_HANDLER -> CSAPI: Request to persist event information - POST - /events + activate CSAPI + CSAPI -> TOPIC_EVENTS: Publish event information + activate TOPIC_EVENTS + ||| + ref over TOPIC_EVENTS : Event Handler Consume\n + ||| + TOPIC_EVENTS --> CSAPI: Return success + deactivate TOPIC_EVENTS + CSAPI --> NOTIFY_HANDLER: Return success + deactivate CSAPI + end + NOTIFY_HANDLER -> CSAPI: Request Notifications details for Participant - GET - /notifications/DFPS(n) + activate CSAPI + CSAPI -> NOTIFY_DAO: Fetch Notifications details for Participant + activate NOTIFY_DAO + NOTIFY_DAO -> DB: Fetch Notifications details for Participant + activate DB + hnote over DB #lightyellow + transferPosition + end note + DB --> NOTIFY_DAO: Retrieved Notification details for Participant + 'deactivate DB + NOTIFY_DAO --> CSAPI: Return Notifications details for Participant + deactivate NOTIFY_DAO + CSAPI --> NOTIFY_HANDLER: Return Notifications details for Participant + deactivate CSAPI + NOTIFY_HANDLER --> DFSP: Callback with Prepare result to Participant to specified URL - PUT - />/transfers + end +end +deactivate NOTIFY_HANDLER +@enduml diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.b.svg b/docs/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.b.svg new file mode 100644 index 000000000..6e972084c --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-prepare-1.1.4.b.svg @@ -0,0 +1,246 @@ + + + + + + + + + + + 1.1.4.b. Send notification to Participant (Payer/Payee) (batch messages) + + + + Financial Service Provider + + + + ML API Adapter Service + + + + Central Service + + + + + + + + DFSP(n) + + + Participant + + + + + DFSP(n) + + + Participant + + + + + ML API Notification Event Handler + + + + + ML API Notification Event Handler + + + + + + + Notification-Topic + + + + + Notification-Topic + + + Central Service API + + + + + Central Service API + + + + + + + Event-Topic + + + + + Event-Topic + + + + EVENT_DAO + + + + EVENT_DAO + + + Notification DAO + + + + + Notification DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Send notification to Participant + + + + + This flow has not been implemented + + + + + 1 + + + Consume Notifications event batch of messages for Participant + + + + + loop + + + [for each message in batch] + + + + + Persist Event Information + + + + + 2 + + + Request to persist event information - POST - /events + + + + + 3 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + 4 + + + Return success + + + + + 5 + + + Return success + + + + + 6 + + + Request Notifications details for Participant - GET - /notifications/DFPS(n) + + + + + 7 + + + Fetch Notifications details for Participant + + + + + 8 + + + Fetch Notifications details for Participant + + + + transferPosition + + + + + 9 + + + Retrieved Notification details for Participant + + + + + 10 + + + Return Notifications details for Participant + + + + + 11 + + + Return Notifications details for Participant + + + + + 12 + + + Callback with Prepare result to Participant to specified URL - PUT - /<dfsp-host>>/transfers + + diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0-v1.1.plantuml b/docs/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0-v1.1.plantuml new file mode 100644 index 000000000..45f7fd524 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0-v1.1.plantuml @@ -0,0 +1,143 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Rajiv Mothilal + * Georgi Georgiev + -------------- + ******'/ + +@startuml +' declate title +title 2.2.0. DFSP2 sends a Fulfil Reject Transfer request + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +actor "DFSP1\nPayer" as DFSP1 +actor "DFSP2\nPayee" as DFSP2 +boundary "ML API Adapter" as MLAPI +control "ML API Notification Event Handler" as NOTIFY_HANDLER +boundary "Central Service API" as CSAPI +collections "Fulfil-Topic" as TOPIC_FULFIL +control "Fulfil Event Handler" as FULF_HANDLER + +' collections "topic-transfer-position" as TOPIC_TRANSFER_POSITION +' control "Position Event Handler" as POS_HANDLER +' collections "Event-Topic" as TOPIC_EVENTS +' collections "Notification-Topic" as TOPIC_NOTIFICATIONS + +box "Financial Service Providers" #lightGray + participant DFSP1 + participant DFSP2 +end box + +box "ML API Adapter Service" #LightBlue + participant MLAPI + participant NOTIFY_HANDLER +end box + +box "Central Service" #LightYellow + participant CSAPI + participant TOPIC_FULFIL + participant FULF_HANDLER +end box + +' start flow +activate NOTIFY_HANDLER +activate FULF_HANDLER +group DFSP2 sends an error callback to reject a transfer with an errorCode and description + note right of DFSP2 #yellow + Headers - transferHeaders: { + Content-Length: , + Content-Type: , + Date: , + X-Forwarded-For: , + FSPIOP-Source: , + FSPIOP-Destination: , + FSPIOP-Encryption: , + FSPIOP-Signature: , + FSPIOP-URI: , + FSPIOP-HTTP-Method: + } + + Payload - transferMessage: + { + "errorInformation": { + "errorCode": , + "errorDescription": , + "extensionList": { + "extension": [ + { + "key": , + "value": + } + ] + } + } + } + end note + DFSP2 ->> MLAPI: **PUT - /transfers//error** + + activate MLAPI + MLAPI -> MLAPI: Validate incoming token and originator matching Payee + note right of MLAPI #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + type: fulfil, + action: reject, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + MLAPI -> TOPIC_FULFIL: Route & Publish Fulfil event for Payee + activate TOPIC_FULFIL + TOPIC_FULFIL <-> TOPIC_FULFIL: Ensure event is replicated as configured (ACKS=all) + TOPIC_FULFIL --> MLAPI: Respond replication acknowledgements have been received + deactivate TOPIC_FULFIL + MLAPI -->> DFSP2: Respond HTTP - 200 (OK) + deactivate MLAPI + TOPIC_FULFIL <- FULF_HANDLER: Consume message + FULF_HANDLER -> FULF_HANDLER: Log error message + note right of FULF_HANDLER: (corresponding to a Fulfil message with transferState='ABORTED')\naction REJECT is not allowed into fulfil handler +end +@enduml diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0-v1.1.svg b/docs/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0-v1.1.svg new file mode 100644 index 000000000..d00bef23e --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0-v1.1.svg @@ -0,0 +1,341 @@ + + + + + + + + + + + 2.2.0. DFSP2 sends a Fulfil Reject Transfer request + + + + Financial Service Providers + + + + ML API Adapter Service + + + + Central Service + + + + + + DFSP1 + + + Payer + + + + + DFSP1 + + + Payer + + + + + DFSP2 + + + Payee + + + + + DFSP2 + + + Payee + + + + + ML API Adapter + + + + + ML API Adapter + + + + + ML API Notification Event Handler + + + + + ML API Notification Event Handler + + + + + Central Service API + + + + + Central Service API + + + + + + + Fulfil-Topic + + + + + Fulfil-Topic + + + Fulfil Event Handler + + + + + Fulfil Event Handler + + + + + + + + DFSP2 sends an error callback to reject a transfer with an errorCode and description + + + + + Headers - transferHeaders: { + + + Content-Length: <Content-Length>, + + + Content-Type: <Content-Type>, + + + Date: <Date>, + + + X-Forwarded-For: <X-Forwarded-For>, + + + FSPIOP-Source: <FSPIOP-Source>, + + + FSPIOP-Destination: <FSPIOP-Destination>, + + + FSPIOP-Encryption: <FSPIOP-Encryption>, + + + FSPIOP-Signature: <FSPIOP-Signature>, + + + FSPIOP-URI: <FSPIOP-URI>, + + + FSPIOP-HTTP-Method: <FSPIOP-HTTP-Method> + + + } + + + Payload - transferMessage: + + + { + + + "errorInformation": { + + + "errorCode": <errorCode>, + + + "errorDescription": <errorDescription>, + + + "extensionList": { + + + "extension": [ + + + { + + + "key": <string>, + + + "value": <string> + + + } + + + ] + + + } + + + } + + + } + + + + 1 + + + PUT - /transfers/<ID>/error + + + + + 2 + + + Validate incoming token and originator matching Payee + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + type: fulfil, + + + action: reject, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 3 + + + Route & Publish Fulfil event for Payee + + + + + 4 + + + Ensure event is replicated as configured (ACKS=all) + + + + + 5 + + + Respond replication acknowledgements have been received + + + + + 6 + + + Respond HTTP - 200 (OK) + + + + + 7 + + + Consume message + + + + + 8 + + + Log error message + + + + + (corresponding to a Fulfil message with transferState='ABORTED') + + + action REJECT is not allowed into fulfil handler + + diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.a-v1.1.plantuml b/docs/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.a-v1.1.plantuml new file mode 100644 index 000000000..ec02b5318 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.a-v1.1.plantuml @@ -0,0 +1,166 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Sam Kummary + -------------- +******'/ + +@startuml +' declate title +title 2.2.0.a. DFSP2 sends a PUT call on /error end-point for a Transfer request + +autonumber +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +actor "DFSP1\nPayer" as DFSP1 +actor "DFSP2\nPayee" as DFSP2 +boundary "ML API Adapter" as MLAPI +control "ML API Notification Event Handler" as NOTIFY_HANDLER +boundary "Central Service API" as CSAPI +collections "Fulfil-Topic" as TOPIC_FULFIL +control "Fulfil Event Handler" as FULF_HANDLER +collections "topic-transfer-position" as TOPIC_TRANSFER_POSITION +control "Position Event Handler" as POS_HANDLER +collections "Notification-Topic" as TOPIC_NOTIFICATIONS + +box "Financial Service Providers" #lightGray + participant DFSP1 + participant DFSP2 +end box + +box "ML API Adapter Service" #LightBlue + participant MLAPI + participant NOTIFY_HANDLER +end box + +box "Central Service" #LightYellow + participant CSAPI + participant TOPIC_FULFIL + participant FULF_HANDLER + participant TOPIC_TRANSFER_POSITION + participant POS_HANDLER + participant TOPIC_NOTIFICATIONS +end box + +' start flow +activate NOTIFY_HANDLER +activate FULF_HANDLER +activate POS_HANDLER +group DFSP2 sends a Fulfil Success Transfer request + DFSP2 <-> DFSP2: During processing of an incoming\nPOST /transfers request, some processing\nerror occurred and an Error callback is made + note right of DFSP2 #yellow + Headers - transferHeaders: { + Content-Length: , + Content-Type: , + Date: , + X-Forwarded-For: , + FSPIOP-Source: , + FSPIOP-Destination: , + FSPIOP-Encryption: , + FSPIOP-Signature: , + FSPIOP-URI: , + FSPIOP-HTTP-Method: + } + + Payload - errorMessage: + { + errorInformation + { + "errorCode": , + "errorDescription": + "extensionList": { + "extension": [ + { + "key": , + "value": + } + ] + } + } + } + end note + DFSP2 ->> MLAPI: PUT - /transfers//error + activate MLAPI + MLAPI -> MLAPI: Validate incoming originator matching Payee\nError codes: 3000-3002, 3100-3107 + note right of MLAPI #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + type: fulfil, + action: abort, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + MLAPI -> TOPIC_FULFIL: Route & Publish Abort event for Payee\nError code: 2003 + activate TOPIC_FULFIL + TOPIC_FULFIL <-> TOPIC_FULFIL: Ensure event is replicated as configured (ACKS=all)\nError code: 2003 + TOPIC_FULFIL --> MLAPI: Respond replication acknowledgements have been received + deactivate TOPIC_FULFIL + MLAPI -->> DFSP2: Respond HTTP - 200 (OK) + deactivate MLAPI + TOPIC_FULFIL <- FULF_HANDLER: Consume message + ref over TOPIC_FULFIL, TOPIC_TRANSFER_POSITION: Fulfil Handler Consume (Abort)\n + FULF_HANDLER -> TOPIC_TRANSFER_POSITION: Produce message + ||| + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume message + ref over TOPIC_TRANSFER_POSITION, TOPIC_NOTIFICATIONS: Position Handler Consume (Abort)\n + POS_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + ||| + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message + opt action == 'abort' + ||| + ref over DFSP1, TOPIC_NOTIFICATIONS: Send notification to Participant (Payer)\n + NOTIFY_HANDLER -> DFSP1: Send callback notification + end + ||| + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message + opt action == 'abort' + ||| + ref over DFSP2, TOPIC_NOTIFICATIONS: Send notification to Participant (Payee)\n + NOTIFY_HANDLER -> DFSP2: Send callback notification + end + ||| +end +deactivate POS_HANDLER +deactivate FULF_HANDLER +deactivate NOTIFY_HANDLER +@enduml \ No newline at end of file diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.a-v1.1.svg b/docs/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.a-v1.1.svg new file mode 100644 index 000000000..dd1fc3063 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.a-v1.1.svg @@ -0,0 +1,495 @@ + + + + + + + + + + + 2.2.0.a. DFSP2 sends a PUT call on /error end-point for a Transfer request + + + + Financial Service Providers + + + + ML API Adapter Service + + + + Central Service + + + + + + + DFSP1 + + + Payer + + + + + DFSP1 + + + Payer + + + + + DFSP2 + + + Payee + + + + + DFSP2 + + + Payee + + + + + ML API Adapter + + + + + ML API Adapter + + + + + ML API Notification Event Handler + + + + + ML API Notification Event Handler + + + + + Central Service API + + + + + Central Service API + + + + + + + Fulfil-Topic + + + + + Fulfil-Topic + + + Fulfil Event Handler + + + + + Fulfil Event Handler + + + + + + + topic-transfer-position + + + + + topic-transfer-position + + + Position Event Handler + + + + + Position Event Handler + + + + + + + Notification-Topic + + + + + Notification-Topic + + + + + + DFSP2 sends a Fulfil Success Transfer request + + + + + 1 + + + During processing of an incoming + + + POST /transfers request, some processing + + + error occurred and an Error callback is made + + + + + Headers - transferHeaders: { + + + Content-Length: <Content-Length>, + + + Content-Type: <Content-Type>, + + + Date: <Date>, + + + X-Forwarded-For: <X-Forwarded-For>, + + + FSPIOP-Source: <FSPIOP-Source>, + + + FSPIOP-Destination: <FSPIOP-Destination>, + + + FSPIOP-Encryption: <FSPIOP-Encryption>, + + + FSPIOP-Signature: <FSPIOP-Signature>, + + + FSPIOP-URI: <FSPIOP-URI>, + + + FSPIOP-HTTP-Method: <FSPIOP-HTTP-Method> + + + } + + + Payload - errorMessage: + + + { + + + errorInformation + + + { + + + "errorCode": <errorCode>, + + + "errorDescription": <errorDescription> + + + "extensionList": { + + + "extension": [ + + + { + + + "key": <string>, + + + "value": <string> + + + } + + + ] + + + } + + + } + + + } + + + + 2 + + + PUT - /transfers/<ID>/error + + + + + 3 + + + Validate incoming originator matching Payee + + + Error codes: + + + 3000-3002, 3100-3107 + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <errorMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + type: fulfil, + + + action: abort, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 4 + + + Route & Publish Abort event for Payee + + + Error code: + + + 2003 + + + + + 5 + + + Ensure event is replicated as configured (ACKS=all) + + + Error code: + + + 2003 + + + + + 6 + + + Respond replication acknowledgements have been received + + + + + 7 + + + Respond HTTP - 200 (OK) + + + + + 8 + + + Consume message + + + + + ref + + + Fulfil Handler Consume (Abort) + + + + + 9 + + + Produce message + + + + + 10 + + + Consume message + + + + + ref + + + Position Handler Consume (Abort) + + + + + 11 + + + Produce message + + + + + 12 + + + Consume message + + + + + opt + + + [action == 'abort'] + + + + + ref + + + Send notification to Participant (Payer) + + + + + 13 + + + Send callback notification + + + + + 14 + + + Consume message + + + + + opt + + + [action == 'abort'] + + + + + ref + + + Send notification to Participant (Payee) + + + + + 15 + + + Send callback notification + + diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.a.plantuml b/docs/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.a.plantuml new file mode 100644 index 000000000..f7c9c3c06 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.a.plantuml @@ -0,0 +1,166 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Sam Kummary + -------------- +******'/ + +@startuml +' declate title +title 2.2.0.a. DFSP2 sends a PUT call on /error end-point for a Transfer request + +autonumber +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +actor "DFSP1\nPayer" as DFSP1 +actor "DFSP2\nPayee" as DFSP2 +boundary "ML API Adapter" as MLAPI +control "ML API Notification Event Handler" as NOTIFY_HANDLER +boundary "Central Service API" as CSAPI +collections "Fulfil-Topic" as TOPIC_FULFIL +control "Fulfil Event Handler" as FULF_HANDLER +collections "topic-transfer-position" as TOPIC_TRANSFER_POSITION +control "Position Event Handler" as POS_HANDLER +collections "Notification-Topic" as TOPIC_NOTIFICATIONS + +box "Financial Service Providers" #lightGray + participant DFSP1 + participant DFSP2 +end box + +box "ML API Adapter Service" #LightBlue + participant MLAPI + participant NOTIFY_HANDLER +end box + +box "Central Service" #LightYellow + participant CSAPI + participant TOPIC_FULFIL + participant FULF_HANDLER + participant TOPIC_TRANSFER_POSITION + participant POS_HANDLER + participant TOPIC_NOTIFICATIONS +end box + +' start flow +activate NOTIFY_HANDLER +activate FULF_HANDLER +activate POS_HANDLER +group DFSP2 sends a Fulfil Success Transfer request + DFSP2 <-> DFSP2: During processing of an incoming\nPOST /transfers request, some processing\nerror occurred and an Error callback is made + note right of DFSP2 #yellow + Headers - transferHeaders: { + Content-Length: , + Content-Type: , + Date: , + X-Forwarded-For: , + FSPIOP-Source: , + FSPIOP-Destination: , + FSPIOP-Encryption: , + FSPIOP-Signature: , + FSPIOP-URI: , + FSPIOP-HTTP-Method: + } + + Payload - errorMessage: + { + errorInformation + { + "errorCode": , + "errorDescription": + "extensionList": { + "extension": [ + { + "key": , + "value": + } + ] + } + } + } + end note + DFSP2 ->> MLAPI: PUT - /transfers//error + activate MLAPI + MLAPI -> MLAPI: Validate incoming originator matching Payee\nError codes: 3000-3002, 3100-3107 + note right of MLAPI #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + type: fulfil, + action: abort, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + MLAPI -> TOPIC_FULFIL: Route & Publish Abort/Reject event for Payee\nError code: 2003 + activate TOPIC_FULFIL + TOPIC_FULFIL <-> TOPIC_FULFIL: Ensure event is replicated as configured (ACKS=all)\nError code: 2003 + TOPIC_FULFIL --> MLAPI: Respond replication acknowledgements have been received + deactivate TOPIC_FULFIL + MLAPI -->> DFSP2: Respond HTTP - 200 (OK) + deactivate MLAPI + TOPIC_FULFIL <- FULF_HANDLER: Consume message + ref over TOPIC_FULFIL, TOPIC_TRANSFER_POSITION: Fulfil Handler Consume (Reject/Abort)\n + FULF_HANDLER -> TOPIC_TRANSFER_POSITION: Produce message + ||| + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume message + ref over TOPIC_TRANSFER_POSITION, TOPIC_NOTIFICATIONS: Position Handler Consume (Abort)\n + POS_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + ||| + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message + opt action == 'abort' + ||| + ref over DFSP1, TOPIC_NOTIFICATIONS: Send notification to Participant (Payer)\n + NOTIFY_HANDLER -> DFSP1: Send callback notification + end + ||| + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message + opt action == 'abort' + ||| + ref over DFSP2, TOPIC_NOTIFICATIONS: Send notification to Participant (Payee)\n + NOTIFY_HANDLER -> DFSP2: Send callback notification + end + ||| +end +deactivate POS_HANDLER +deactivate FULF_HANDLER +deactivate NOTIFY_HANDLER +@enduml \ No newline at end of file diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.a.svg b/docs/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.a.svg new file mode 100644 index 000000000..7ac9606f1 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.a.svg @@ -0,0 +1,495 @@ + + + + + + + + + + + 2.2.0.a. DFSP2 sends a PUT call on /error end-point for a Transfer request + + + + Financial Service Providers + + + + ML API Adapter Service + + + + Central Service + + + + + + + DFSP1 + + + Payer + + + + + DFSP1 + + + Payer + + + + + DFSP2 + + + Payee + + + + + DFSP2 + + + Payee + + + + + ML API Adapter + + + + + ML API Adapter + + + + + ML API Notification Event Handler + + + + + ML API Notification Event Handler + + + + + Central Service API + + + + + Central Service API + + + + + + + Fulfil-Topic + + + + + Fulfil-Topic + + + Fulfil Event Handler + + + + + Fulfil Event Handler + + + + + + + topic-transfer-position + + + + + topic-transfer-position + + + Position Event Handler + + + + + Position Event Handler + + + + + + + Notification-Topic + + + + + Notification-Topic + + + + + + DFSP2 sends a Fulfil Success Transfer request + + + + + 1 + + + During processing of an incoming + + + POST /transfers request, some processing + + + error occurred and an Error callback is made + + + + + Headers - transferHeaders: { + + + Content-Length: <Content-Length>, + + + Content-Type: <Content-Type>, + + + Date: <Date>, + + + X-Forwarded-For: <X-Forwarded-For>, + + + FSPIOP-Source: <FSPIOP-Source>, + + + FSPIOP-Destination: <FSPIOP-Destination>, + + + FSPIOP-Encryption: <FSPIOP-Encryption>, + + + FSPIOP-Signature: <FSPIOP-Signature>, + + + FSPIOP-URI: <FSPIOP-URI>, + + + FSPIOP-HTTP-Method: <FSPIOP-HTTP-Method> + + + } + + + Payload - errorMessage: + + + { + + + errorInformation + + + { + + + "errorCode": <errorCode>, + + + "errorDescription": <errorDescription> + + + "extensionList": { + + + "extension": [ + + + { + + + "key": <string>, + + + "value": <string> + + + } + + + ] + + + } + + + } + + + } + + + + 2 + + + PUT - /transfers/<ID>/error + + + + + 3 + + + Validate incoming originator matching Payee + + + Error codes: + + + 3000-3002, 3100-3107 + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <errorMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + type: fulfil, + + + action: abort, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 4 + + + Route & Publish Abort/Reject event for Payee + + + Error code: + + + 2003 + + + + + 5 + + + Ensure event is replicated as configured (ACKS=all) + + + Error code: + + + 2003 + + + + + 6 + + + Respond replication acknowledgements have been received + + + + + 7 + + + Respond HTTP - 200 (OK) + + + + + 8 + + + Consume message + + + + + ref + + + Fulfil Handler Consume (Reject/Abort) + + + + + 9 + + + Produce message + + + + + 10 + + + Consume message + + + + + ref + + + Position Handler Consume (Abort) + + + + + 11 + + + Produce message + + + + + 12 + + + Consume message + + + + + opt + + + [action == 'abort'] + + + + + ref + + + Send notification to Participant (Payer) + + + + + 13 + + + Send callback notification + + + + + 14 + + + Consume message + + + + + opt + + + [action == 'abort'] + + + + + ref + + + Send notification to Participant (Payee) + + + + + 15 + + + Send callback notification + + diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.plantuml b/docs/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.plantuml new file mode 100644 index 000000000..9c88eb8cb --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.plantuml @@ -0,0 +1,170 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Rajiv Mothilal + * Georgi Georgiev + -------------- + ******'/ + +@startuml +' declate title +title 2.2.0. DFSP2 sends a Fulfil Reject Transfer request + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +actor "DFSP1\nPayer" as DFSP1 +actor "DFSP2\nPayee" as DFSP2 +boundary "ML API Adapter" as MLAPI +control "ML API Notification Event Handler" as NOTIFY_HANDLER +boundary "Central Service API" as CSAPI +collections "Fulfil-Topic" as TOPIC_FULFIL +control "Fulfil Event Handler" as FULF_HANDLER +collections "topic-transfer-position" as TOPIC_TRANSFER_POSITION +control "Position Event Handler" as POS_HANDLER +collections "Event-Topic" as TOPIC_EVENTS +collections "Notification-Topic" as TOPIC_NOTIFICATIONS + +box "Financial Service Providers" #lightGray + participant DFSP1 + participant DFSP2 +end box + +box "ML API Adapter Service" #LightBlue + participant MLAPI + participant NOTIFY_HANDLER +end box + +box "Central Service" #LightYellow + participant CSAPI + participant TOPIC_FULFIL + participant FULF_HANDLER + participant TOPIC_TRANSFER_POSITION + participant TOPIC_EVENTS + participant POS_HANDLER + participant TOPIC_NOTIFICATIONS +end box + +' start flow +activate NOTIFY_HANDLER +activate FULF_HANDLER +activate POS_HANDLER +group DFSP2 sends a Fulfil Reject Transfer request + DFSP2 <-> DFSP2: Retrieve fulfilment string generated during\nthe quoting process or regenerate it using\n**Local secret** and **ILP Packet** as inputs + note right of DFSP2 #lightblue + **Note**: In the payload for PUT /transfers/ + only the **transferState** field is **required** + end note + note right of DFSP2 #yellow + Headers - transferHeaders: { + Content-Length: , + Content-Type: , + Date: , + X-Forwarded-For: , + FSPIOP-Source: , + FSPIOP-Destination: , + FSPIOP-Encryption: , + FSPIOP-Signature: , + FSPIOP-URI: , + FSPIOP-HTTP-Method: + } + + Payload - transferMessage: + { + "fulfilment": , + "completedTimestamp": , + "transferState": "ABORTED", + "extensionList": { + "extension": [ + { + "key": , + "value": + } + ] + } + } + end note + note right of DFSP2 #lightgray + **Note**: Payee rejection reason should be captured + in the extensionList within the payload. + end note + DFSP2 ->> MLAPI: **PUT - /transfers/** + + activate MLAPI + MLAPI -> MLAPI: Validate incoming token and originator matching Payee + note right of MLAPI #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + type: fulfil, + action: reject, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + MLAPI -> TOPIC_FULFIL: Route & Publish Fulfil event for Payee + activate TOPIC_FULFIL + TOPIC_FULFIL <-> TOPIC_FULFIL: Ensure event is replicated as configured (ACKS=all) + TOPIC_FULFIL --> MLAPI: Respond replication acknowledgements have been received + deactivate TOPIC_FULFIL + MLAPI -->> DFSP2: Respond HTTP - 200 (OK) + deactivate MLAPI + TOPIC_FULFIL <- FULF_HANDLER: Consume message + ref over TOPIC_FULFIL, TOPIC_EVENTS: Fulfil Handler Consume (Reject/Abort)\n + FULF_HANDLER -> TOPIC_TRANSFER_POSITION: Produce message + ||| + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume message + ref over TOPIC_TRANSFER_POSITION, TOPIC_NOTIFICATIONS: Position Handler Consume (Reject)\n + POS_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + ||| + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message + opt action == 'reject' + ||| + ref over DFSP1, TOPIC_NOTIFICATIONS: Send notification to Participant (Payer)\n + NOTIFY_HANDLER -> DFSP1: Send callback notification + end + ||| +end +activate POS_HANDLER +activate FULF_HANDLER +activate NOTIFY_HANDLER +@enduml diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.svg b/docs/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.svg new file mode 100644 index 000000000..a2cbf7626 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.0.svg @@ -0,0 +1,489 @@ + + + + + + + + + + + 2.2.0. DFSP2 sends a Fulfil Reject Transfer request + + + + Financial Service Providers + + + + ML API Adapter Service + + + + Central Service + + + + + + + DFSP1 + + + Payer + + + + + DFSP1 + + + Payer + + + + + DFSP2 + + + Payee + + + + + DFSP2 + + + Payee + + + + + ML API Adapter + + + + + ML API Adapter + + + + + ML API Notification Event Handler + + + + + ML API Notification Event Handler + + + + + Central Service API + + + + + Central Service API + + + + + + + Fulfil-Topic + + + + + Fulfil-Topic + + + Fulfil Event Handler + + + + + Fulfil Event Handler + + + + + + + topic-transfer-position + + + + + topic-transfer-position + + + + + Event-Topic + + + + + Event-Topic + + + Position Event Handler + + + + + Position Event Handler + + + + + + + Notification-Topic + + + + + Notification-Topic + + + + + + DFSP2 sends a Fulfil Reject Transfer request + + + + + 1 + + + Retrieve fulfilment string generated during + + + the quoting process or regenerate it using + + + Local secret + + + and + + + ILP Packet + + + as inputs + + + + + Note + + + : In the payload for PUT /transfers/<ID> + + + only the + + + transferState + + + field is + + + required + + + + + Headers - transferHeaders: { + + + Content-Length: <Content-Length>, + + + Content-Type: <Content-Type>, + + + Date: <Date>, + + + X-Forwarded-For: <X-Forwarded-For>, + + + FSPIOP-Source: <FSPIOP-Source>, + + + FSPIOP-Destination: <FSPIOP-Destination>, + + + FSPIOP-Encryption: <FSPIOP-Encryption>, + + + FSPIOP-Signature: <FSPIOP-Signature>, + + + FSPIOP-URI: <FSPIOP-URI>, + + + FSPIOP-HTTP-Method: <FSPIOP-HTTP-Method> + + + } + + + Payload - transferMessage: + + + { + + + "fulfilment": <IlpFulfilment>, + + + "completedTimestamp": <DateTime>, + + + "transferState": "ABORTED", + + + "extensionList": { + + + "extension": [ + + + { + + + "key": <string>, + + + "value": <string> + + + } + + + ] + + + } + + + } + + + + + Note + + + : Payee rejection reason should be captured + + + in the extensionList within the payload. + + + + 2 + + + PUT - /transfers/<ID> + + + + + 3 + + + Validate incoming token and originator matching Payee + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + type: fulfil, + + + action: reject, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 4 + + + Route & Publish Fulfil event for Payee + + + + + 5 + + + Ensure event is replicated as configured (ACKS=all) + + + + + 6 + + + Respond replication acknowledgements have been received + + + + + 7 + + + Respond HTTP - 200 (OK) + + + + + 8 + + + Consume message + + + + + ref + + + Fulfil Handler Consume (Reject/Abort) + + + + + 9 + + + Produce message + + + + + 10 + + + Consume message + + + + + ref + + + Position Handler Consume (Reject) + + + + + 11 + + + Produce message + + + + + 12 + + + Consume message + + + + + opt + + + [action == 'reject'] + + + + + ref + + + Send notification to Participant (Payer) + + + + + 13 + + + Send callback notification + + diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.1-v1.1.plantuml b/docs/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.1-v1.1.plantuml new file mode 100644 index 000000000..3c390db71 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.1-v1.1.plantuml @@ -0,0 +1,225 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Rajiv Mothilal + * Georgi Georgiev + * Sam Kummary + -------------- + ******'/ + +@startuml +' declate title +title 2.2.1. Fulfil Handler Consume (Abort/Reject) +autonumber +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store +' declare actors +collections "Fulfil-Topic" as TOPIC_FULFIL +control "Fulfil Event Handler" as FULF_HANDLER +collections "Event-Topic" as TOPIC_EVENT +collections "topic-transfer-position" as TOPIC_TRANSFER_POSITION +collections "Notification-Topic" as TOPIC_NOTIFICATIONS +'entity "Transfer Duplicate Facade" as DUP_FACADE +entity "Transfer DAO" as TRANS_DAO +database "Central Store" as DB +box "Central Service" #LightYellow + participant TOPIC_FULFIL + participant FULF_HANDLER + participant TOPIC_TRANSFER_POSITION + participant TOPIC_EVENT + participant TOPIC_NOTIFICATIONS + participant TRANS_DAO + participant DB +end box +' start flow +activate FULF_HANDLER +group Fulfil Handler Consume (Failure) + alt Consume Single Message + TOPIC_FULFIL <- FULF_HANDLER: Consume Fulfil event message for Payer + activate TOPIC_FULFIL + deactivate TOPIC_FULFIL + break + group Validate Event + FULF_HANDLER <-> FULF_HANDLER: Validate event - Rule: type == 'fulfil' && ( action IN ['reject','abort'] )\nError codes: 2001 + end + end + group Persist Event Information + FULF_HANDLER -> TOPIC_EVENT: Publish event information + ref over FULF_HANDLER, TOPIC_EVENT: Event Handler Consume + end + group Validate FSPIOP-Signature + ||| + ref over FULF_HANDLER, TOPIC_NOTIFICATIONS: Validate message.content.headers.**FSPIOP-Signature**\nError codes: 2001 + end + group Validate Transfer Fulfil Duplicate Check + FULF_HANDLER -> FULF_HANDLER: Generate transferFulfilmentId uuid + FULF_HANDLER -> TRANS_DAO: Request to retrieve transfer fulfilment hashes by transferId\nError code: 2003 + activate TRANS_DAO + TRANS_DAO -> DB: Request Transfer fulfilment duplicate message hashes + hnote over DB #lightyellow + SELET transferId, hash + FROM **transferFulfilmentDuplicateCheck** + WHERE transferId = request.params.id + end note + activate DB + TRANS_DAO <-- DB: Return existing hashes + deactivate DB + TRANS_DAO --> FULF_HANDLER: Return (list of) transfer fulfil messages hash(es) + deactivate TRANS_DAO + FULF_HANDLER -> FULF_HANDLER: Loop the list of returned hashes and compare each entry with the calculated message hash + alt Hash matched + ' Need to check what respond with same results if finalised then resend, else ignore and wait for response + FULF_HANDLER -> TRANS_DAO: Request to retrieve Transfer Fulfilment and Transfer state\nError code: 2003 + activate TRANS_DAO + TRANS_DAO -> DB: Request to retrieve Transfer Fulfilment and Transfer state + hnote over DB #lightyellow + transferFulfilment + transferStateChange + end note + activate DB + TRANS_DAO <-- DB: Return Transfer Fulfilment and Transfer state + deactivate DB + TRANS_DAO --> FULF_HANDLER: Return Transfer Fulfilment and Transfer state + deactivate TRANS_DAO + alt transferFulfilment.isValid == 0 + break + FULF_HANDLER <-> FULF_HANDLER: Error handling: 3105 + end + else transferState IN ['COMMITTED', 'ABORTED'] + break + ref over FULF_HANDLER, TOPIC_NOTIFICATIONS: Send notification to Participant (Payee)\n + end + else transferState NOT 'RESERVED' + break + FULF_HANDLER <-> FULF_HANDLER: Error code: 2001 + end + else + break + FULF_HANDLER <-> FULF_HANDLER: Allow previous request to complete + end + end + else Hash not matched + FULF_HANDLER -> TRANS_DAO: Request to persist transfer hash\nError codes: 2003 + activate TRANS_DAO + TRANS_DAO -> DB: Persist hash + hnote over DB #lightyellow + transferFulfilmentDuplicateCheck + end note + activate DB + deactivate DB + TRANS_DAO --> FULF_HANDLER: Return success + deactivate TRANS_DAO + end + end + alt action=='reject' call made on PUT /transfers/{ID} + FULF_HANDLER -> FULF_HANDLER: Log error message + note right of FULF_HANDLER: action REJECT is not allowed into fulfil handler + else action=='abort' Error callback + alt Validation successful + group Persist Transfer State (with transferState='RECEIVED_ERROR') + FULF_HANDLER -> TRANS_DAO: Request to persist transfer state and Error\nError code: 2003 + activate TRANS_DAO + TRANS_DAO -> DB: Persist transfer state and error information + activate DB + hnote over DB #lightyellow + transferStateChange + transferError + transferExtension + end note + deactivate DB + TRANS_DAO --> FULF_HANDLER: Return success + end + + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: position, + action: abort, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + + FULF_HANDLER -> TOPIC_TRANSFER_POSITION: Route & Publish Position event for Payer + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + else Validate Transfer Error Message not successful + break + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: position, + action: abort, + createdAt: , + state: { + status: "error", + code: 1 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_NOTIFICATIONS: Route & Publish Notification event for Payee + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + end + end + end + else Consume Batch Messages + note left of FULF_HANDLER #lightblue + To be delivered by future story + end note + end +end +deactivate FULF_HANDLER +@enduml diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.1-v1.1.svg b/docs/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.1-v1.1.svg new file mode 100644 index 000000000..7b61b6711 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.1-v1.1.svg @@ -0,0 +1,697 @@ + + + + + + + + + + + 2.2.1. Fulfil Handler Consume (Abort/Reject) + + + + Central Service + + + + + + + + + + + + + + + + + + + + + + + + + + + + Fulfil-Topic + + + + + Fulfil-Topic + + + Fulfil Event Handler + + + + + Fulfil Event Handler + + + + + + + topic-transfer-position + + + + + topic-transfer-position + + + + + Event-Topic + + + + + Event-Topic + + + + + Notification-Topic + + + + + Notification-Topic + + + Transfer DAO + + + + + Transfer DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Fulfil Handler Consume (Failure) + + + + + alt + + + [Consume Single Message] + + + + + 1 + + + Consume Fulfil event message for Payer + + + + + break + + + + + Validate Event + + + + + 2 + + + Validate event - Rule: type == 'fulfil' && ( action IN ['reject','abort'] ) + + + Error codes: + + + 2001 + + + + + Persist Event Information + + + + + 3 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + Validate FSPIOP-Signature + + + + + ref + + + Validate message.content.headers. + + + FSPIOP-Signature + + + Error codes: + + + 2001 + + + + + Validate Transfer Fulfil Duplicate Check + + + + + 4 + + + Generate transferFulfilmentId uuid + + + + + 5 + + + Request to retrieve transfer fulfilment hashes by transferId + + + Error code: + + + 2003 + + + + + 6 + + + Request Transfer fulfilment duplicate message hashes + + + + SELET transferId, hash + + + FROM + + + transferFulfilmentDuplicateCheck + + + WHERE transferId = request.params.id + + + + + 7 + + + Return existing hashes + + + + + 8 + + + Return (list of) transfer fulfil messages hash(es) + + + + + 9 + + + Loop the list of returned hashes and compare each entry with the calculated message hash + + + + + alt + + + [Hash matched] + + + + + 10 + + + Request to retrieve Transfer Fulfilment and Transfer state + + + Error code: + + + 2003 + + + + + 11 + + + Request to retrieve Transfer Fulfilment and Transfer state + + + + transferFulfilment + + + transferStateChange + + + + + 12 + + + Return Transfer Fulfilment and Transfer state + + + + + 13 + + + Return Transfer Fulfilment and Transfer state + + + + + alt + + + [transferFulfilment.isValid == 0] + + + + + break + + + + + 14 + + + Error handling: + + + 3105 + + + + [transferState IN ['COMMITTED', 'ABORTED']] + + + + + break + + + + + ref + + + Send notification to Participant (Payee) + + + + [transferState NOT 'RESERVED'] + + + + + break + + + + + 15 + + + Error code: + + + 2001 + + + + + + break + + + + + 16 + + + Allow previous request to complete + + + + [Hash not matched] + + + + + 17 + + + Request to persist transfer hash + + + Error codes: + + + 2003 + + + + + 18 + + + Persist hash + + + + transferFulfilmentDuplicateCheck + + + + + 19 + + + Return success + + + + + alt + + + [action=='reject' call made on PUT /transfers/{ID}] + + + + + 20 + + + Log error message + + + + + action REJECT is not allowed into fulfil handler + + + + [action=='abort' Error callback] + + + + + alt + + + [Validation successful] + + + + + Persist Transfer State (with transferState='RECEIVED_ERROR') + + + + + 21 + + + Request to persist transfer state and Error + + + Error code: + + + 2003 + + + + + 22 + + + Persist transfer state and error information + + + + transferStateChange + + + transferError + + + transferExtension + + + + + 23 + + + Return success + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: position, + + + action: abort, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 24 + + + Route & Publish Position event for Payer + + + + [Validate Transfer Error Message not successful] + + + + + break + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: position, + + + action: abort, + + + createdAt: <timestamp>, + + + state: { + + + status: "error", + + + code: 1 + + + } + + + } + + + } + + + } + + + + + 25 + + + Route & Publish Notification event for Payee + + + + [Consume Batch Messages] + + + + + To be delivered by future story + + diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.1.plantuml b/docs/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.1.plantuml new file mode 100644 index 000000000..1cd1e4b68 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.1.plantuml @@ -0,0 +1,343 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Rajiv Mothilal + * Georgi Georgiev + * Sam Kummary + -------------- + ******'/ + +@startuml +' declate title +title 2.2.1. Fulfil Handler Consume (Reject/Abort) +autonumber +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store +' declare actors +collections "Fulfil-Topic" as TOPIC_FULFIL +control "Fulfil Event Handler" as FULF_HANDLER +collections "Event-Topic" as TOPIC_EVENT +collections "topic-transfer-position" as TOPIC_TRANSFER_POSITION +collections "Notification-Topic" as TOPIC_NOTIFICATIONS +'entity "Transfer Duplicate Facade" as DUP_FACADE +entity "Transfer DAO" as TRANS_DAO +database "Central Store" as DB +box "Central Service" #LightYellow + participant TOPIC_FULFIL + participant FULF_HANDLER + participant TOPIC_TRANSFER_POSITION + participant TOPIC_EVENT + participant TOPIC_NOTIFICATIONS + participant TRANS_DAO + participant DB +end box +' start flow +activate FULF_HANDLER +group Fulfil Handler Consume (Failure) + alt Consume Single Message + TOPIC_FULFIL <- FULF_HANDLER: Consume Fulfil event message for Payer + activate TOPIC_FULFIL + deactivate TOPIC_FULFIL + break + group Validate Event + FULF_HANDLER <-> FULF_HANDLER: Validate event - Rule: type == 'fulfil' && ( action IN ['reject','abort'] )\nError codes: 2001 + end + end + group Persist Event Information + FULF_HANDLER -> TOPIC_EVENT: Publish event information + ref over FULF_HANDLER, TOPIC_EVENT: Event Handler Consume + end + group Validate FSPIOP-Signature + ||| + ref over FULF_HANDLER, TOPIC_NOTIFICATIONS: Validate message.content.headers.**FSPIOP-Signature**\nError codes: 2001 + end + group Validate Transfer Fulfil Duplicate Check + FULF_HANDLER -> FULF_HANDLER: Generate transferFulfilmentId uuid + FULF_HANDLER -> TRANS_DAO: Request to retrieve transfer fulfilment hashes by transferId\nError code: 2003 + activate TRANS_DAO + TRANS_DAO -> DB: Request Transfer fulfilment duplicate message hashes + hnote over DB #lightyellow + SELET transferId, hash + FROM **transferFulfilmentDuplicateCheck** + WHERE transferId = request.params.id + end note + activate DB + TRANS_DAO <-- DB: Return existing hashes + deactivate DB + TRANS_DAO --> FULF_HANDLER: Return (list of) transfer fulfil messages hash(es) + deactivate TRANS_DAO + FULF_HANDLER -> FULF_HANDLER: Loop the list of returned hashes and compare each entry with the calculated message hash + alt Hash matched + ' Need to check what respond with same results if finalised then resend, else ignore and wait for response + FULF_HANDLER -> TRANS_DAO: Request to retrieve Transfer Fulfilment and Transfer state\nError code: 2003 + activate TRANS_DAO + TRANS_DAO -> DB: Request to retrieve Transfer Fulfilment and Transfer state + hnote over DB #lightyellow + transferFulfilment + transferStateChange + end note + activate DB + TRANS_DAO <-- DB: Return Transfer Fulfilment and Transfer state + deactivate DB + TRANS_DAO --> FULF_HANDLER: Return Transfer Fulfilment and Transfer state + deactivate TRANS_DAO + alt transferFulfilment.isValid == 0 + break + FULF_HANDLER <-> FULF_HANDLER: Error handling: 3105 + end + else transferState IN ['COMMITTED', 'ABORTED'] + break + ref over FULF_HANDLER, TOPIC_NOTIFICATIONS: Send notification to Participant (Payee)\n + end + else transferState NOT 'RESERVED' + break + FULF_HANDLER <-> FULF_HANDLER: Error code: 2001 + end + else + break + FULF_HANDLER <-> FULF_HANDLER: Allow previous request to complete + end + end + else Hash not matched + FULF_HANDLER -> TRANS_DAO: Request to persist transfer hash\nError codes: 2003 + activate TRANS_DAO + TRANS_DAO -> DB: Persist hash + hnote over DB #lightyellow + transferFulfilmentDuplicateCheck + end note + activate DB + deactivate DB + TRANS_DAO --> FULF_HANDLER: Return success + deactivate TRANS_DAO + end + end + alt action=='reject' call made on PUT /transfers/{ID} + FULF_HANDLER -> TRANS_DAO: Request information for the validate checks\nError code: 2003 + activate TRANS_DAO + TRANS_DAO -> DB: Fetch from database + activate DB + hnote over DB #lightyellow + transfer + end note + DB --> TRANS_DAO + deactivate DB + FULF_HANDLER <-- TRANS_DAO: Return transfer + deactivate TRANS_DAO + + alt Fulfilment present in the PUT /transfers/{ID} message + FULF_HANDLER ->FULF_HANDLER: Validate that Transfer.ilpCondition = SHA-256 (content.payload.fulfilment)\nError code: 2001 + + group Persist fulfilment + FULF_HANDLER -> TRANS_DAO: Persist fulfilment with the result of the above check (transferFulfilment.isValid)\nError code: 2003 + activate TRANS_DAO + TRANS_DAO -> DB: Persist to database + activate DB + deactivate DB + hnote over DB #lightyellow + transferFulfilment + transferExtension + end note + FULF_HANDLER <-- TRANS_DAO: Return success + deactivate TRANS_DAO + end + else Fulfilment NOT present in the PUT /transfers/{ID} message + FULF_HANDLER ->FULF_HANDLER: Validate that transfer fulfilment message to Abort is valid\nError code: 2001 + group Persist extensions + FULF_HANDLER -> TRANS_DAO: Persist extensionList elements\nError code: 2003 + activate TRANS_DAO + TRANS_DAO -> DB: Persist to database + activate DB + deactivate DB + hnote over DB #lightyellow + transferExtension + end note + FULF_HANDLER <-- TRANS_DAO: Return success + deactivate TRANS_DAO + end + end + + alt Transfer.ilpCondition validate successful OR generic validation successful + group Persist Transfer State (with transferState='RECEIVED_REJECT') + FULF_HANDLER -> TRANS_DAO: Request to persist transfer state\nError code: 2003 + activate TRANS_DAO + TRANS_DAO -> DB: Persist transfer state + activate DB + hnote over DB #lightyellow + transferStateChange + end note + deactivate DB + TRANS_DAO --> FULF_HANDLER: Return success + end + + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: position, + action: reject, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + + FULF_HANDLER -> TOPIC_TRANSFER_POSITION: Route & Publish Position event for Payer + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + else Validate Fulfil Transfer not successful or Generic validation failed + break + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: position, + action: reject, + createdAt: , + state: { + status: "error", + code: 1 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_NOTIFICATIONS: Route & Publish Notification event for Payee + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + end + end + else action=='abort' Error callback + alt Validation successful + group Persist Transfer State (with transferState='RECEIVED_ERROR') + FULF_HANDLER -> TRANS_DAO: Request to persist transfer state and Error\nError code: 2003 + activate TRANS_DAO + TRANS_DAO -> DB: Persist transfer state and error information + activate DB + hnote over DB #lightyellow + transferStateChange + transferError + transferExtension + end note + deactivate DB + TRANS_DAO --> FULF_HANDLER: Return success + end + + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: position, + action: abort, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + + FULF_HANDLER -> TOPIC_TRANSFER_POSITION: Route & Publish Position event for Payer + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + else Validate Transfer Error Message not successful + break + note right of FULF_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: , + payload: + }, + metadata: { + event: { + id: , + responseTo: , + type: position, + action: abort, + createdAt: , + state: { + status: "error", + code: 1 + } + } + } + } + end note + FULF_HANDLER -> TOPIC_NOTIFICATIONS: Route & Publish Notification event for Payee + activate TOPIC_NOTIFICATIONS + deactivate TOPIC_NOTIFICATIONS + end + end + end + else Consume Batch Messages + note left of FULF_HANDLER #lightblue + To be delivered by future story + end note + end +end +deactivate FULF_HANDLER +@enduml diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.1.svg b/docs/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.1.svg new file mode 100644 index 000000000..ad8d40a03 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-reject-2.2.1.svg @@ -0,0 +1,1073 @@ + + + + + + + + + + + 2.2.1. Fulfil Handler Consume (Reject/Abort) + + + + Central Service + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Fulfil-Topic + + + + + Fulfil-Topic + + + Fulfil Event Handler + + + + + Fulfil Event Handler + + + + + + + topic-transfer-position + + + + + topic-transfer-position + + + + + Event-Topic + + + + + Event-Topic + + + + + Notification-Topic + + + + + Notification-Topic + + + Transfer DAO + + + + + Transfer DAO + + + + + Central Store + + + + + Central Store + + + + + + + + + Fulfil Handler Consume (Failure) + + + + + alt + + + [Consume Single Message] + + + + + 1 + + + Consume Fulfil event message for Payer + + + + + break + + + + + Validate Event + + + + + 2 + + + Validate event - Rule: type == 'fulfil' && ( action IN ['reject','abort'] ) + + + Error codes: + + + 2001 + + + + + Persist Event Information + + + + + 3 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + Validate FSPIOP-Signature + + + + + ref + + + Validate message.content.headers. + + + FSPIOP-Signature + + + Error codes: + + + 2001 + + + + + Validate Transfer Fulfil Duplicate Check + + + + + 4 + + + Generate transferFulfilmentId uuid + + + + + 5 + + + Request to retrieve transfer fulfilment hashes by transferId + + + Error code: + + + 2003 + + + + + 6 + + + Request Transfer fulfilment duplicate message hashes + + + + SELET transferId, hash + + + FROM + + + transferFulfilmentDuplicateCheck + + + WHERE transferId = request.params.id + + + + + 7 + + + Return existing hashes + + + + + 8 + + + Return (list of) transfer fulfil messages hash(es) + + + + + 9 + + + Loop the list of returned hashes and compare each entry with the calculated message hash + + + + + alt + + + [Hash matched] + + + + + 10 + + + Request to retrieve Transfer Fulfilment and Transfer state + + + Error code: + + + 2003 + + + + + 11 + + + Request to retrieve Transfer Fulfilment and Transfer state + + + + transferFulfilment + + + transferStateChange + + + + + 12 + + + Return Transfer Fulfilment and Transfer state + + + + + 13 + + + Return Transfer Fulfilment and Transfer state + + + + + alt + + + [transferFulfilment.isValid == 0] + + + + + break + + + + + 14 + + + Error handling: + + + 3105 + + + + [transferState IN ['COMMITTED', 'ABORTED']] + + + + + break + + + + + ref + + + Send notification to Participant (Payee) + + + + [transferState NOT 'RESERVED'] + + + + + break + + + + + 15 + + + Error code: + + + 2001 + + + + + + break + + + + + 16 + + + Allow previous request to complete + + + + [Hash not matched] + + + + + 17 + + + Request to persist transfer hash + + + Error codes: + + + 2003 + + + + + 18 + + + Persist hash + + + + transferFulfilmentDuplicateCheck + + + + + 19 + + + Return success + + + + + alt + + + [action=='reject' call made on PUT /transfers/{ID}] + + + + + 20 + + + Request information for the validate checks + + + Error code: + + + 2003 + + + + + 21 + + + Fetch from database + + + + transfer + + + + + 22 + + + + + 23 + + + Return transfer + + + + + alt + + + [Fulfilment present in the PUT /transfers/{ID} message] + + + + + 24 + + + Validate that Transfer.ilpCondition = SHA-256 (content.payload.fulfilment) + + + Error code: + + + 2001 + + + + + Persist fulfilment + + + + + 25 + + + Persist fulfilment with the result of the above check (transferFulfilment.isValid) + + + Error code: + + + 2003 + + + + + 26 + + + Persist to database + + + + transferFulfilment + + + transferExtension + + + + + 27 + + + Return success + + + + [Fulfilment NOT present in the PUT /transfers/{ID} message] + + + + + 28 + + + Validate that transfer fulfilment message to Abort is valid + + + Error code: + + + 2001 + + + + + Persist extensions + + + + + 29 + + + Persist extensionList elements + + + Error code: + + + 2003 + + + + + 30 + + + Persist to database + + + + transferExtension + + + + + 31 + + + Return success + + + + + alt + + + [Transfer.ilpCondition validate successful OR generic validation successful] + + + + + Persist Transfer State (with transferState='RECEIVED_REJECT') + + + + + 32 + + + Request to persist transfer state + + + Error code: + + + 2003 + + + + + 33 + + + Persist transfer state + + + + transferStateChange + + + + + 34 + + + Return success + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: position, + + + action: reject, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 35 + + + Route & Publish Position event for Payer + + + + [Validate Fulfil Transfer not successful or Generic validation failed] + + + + + break + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: position, + + + action: reject, + + + createdAt: <timestamp>, + + + state: { + + + status: "error", + + + code: 1 + + + } + + + } + + + } + + + } + + + + + 36 + + + Route & Publish Notification event for Payee + + + + [action=='abort' Error callback] + + + + + alt + + + [Validation successful] + + + + + Persist Transfer State (with transferState='RECEIVED_ERROR') + + + + + 37 + + + Request to persist transfer state and Error + + + Error code: + + + 2003 + + + + + 38 + + + Persist transfer state and error information + + + + transferStateChange + + + transferError + + + transferExtension + + + + + 39 + + + Return success + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: position, + + + action: abort, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 40 + + + Route & Publish Position event for Payer + + + + [Validate Transfer Error Message not successful] + + + + + break + + + + + Message: + + + { + + + id: <ID>, + + + from: <transferHeaders.FSPIOP-Source>, + + + to: <transferHeaders.FSPIOP-Destination>, + + + type: application/json, + + + content: { + + + headers: <transferHeaders>, + + + payload: <transferMessage> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: <previous.uuid>, + + + type: position, + + + action: abort, + + + createdAt: <timestamp>, + + + state: { + + + status: "error", + + + code: 1 + + + } + + + } + + + } + + + } + + + + + 41 + + + Route & Publish Notification event for Payee + + + + [Consume Batch Messages] + + + + + To be delivered by future story + + diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-request-dup-check-9.1.1.plantuml b/docs/technical/central-ledger/assets/diagrams/sequence/seq-request-dup-check-9.1.1.plantuml new file mode 100644 index 000000000..99fd990f9 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-request-dup-check-9.1.1.plantuml @@ -0,0 +1,114 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * Georgi Georgiev + -------------- + ******'/ + +@startuml +' declate title +title 9.1.1. Request Duplicate Check (incl. Transfers, Quotes, Bulk Transfers, Bulk Quotes) + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +collections "topic-source" as TOPIC_SOURCE +control "Processing\nHandler" as HANDLER +collections "topic-event" as TOPIC_EVENTS +collections "topic-notifcation" as TOPIC_NOTIFICATION +entity "Request DAO" as DAO +database "Central Store" as DB + +box "Central Service" #LightYellow + participant TOPIC_SOURCE + participant HANDLER + participant TOPIC_EVENTS + participant TOPIC_NOTIFICATION + participant DAO + participant DB +end box + +' start flow +activate HANDLER + +group Request Duplicate Check + TOPIC_SOURCE <- HANDLER: Consume message + activate TOPIC_SOURCE + deactivate TOPIC_SOURCE + + HANDLER -> HANDLER: Generate hash: **generatedHash** + group UUID Check (compareById) + HANDLER -> DAO: Query hash using getDuplicateDataFuncOverride(id)\nError code: 2003 + activate DAO + note right of DAO #lightgrey + //request// keyword to be replaced by + **transfer**, **transferFulfilment**, + **bulkTransfer** or other depending + on the override + end note + DAO -> DB: getDuplicateDataFuncOverride + hnote over DB #lightyellow + //request//DuplicateCheck + end note + activate DB + DB --> DAO: Return **duplicateHashRecord** + deactivate DB + DAO --> HANDLER: Return **hasDuplicateId** + deactivate DAO + end + + alt hasDuplicateId == TRUE + group Hash Check (compareByHash) + note right of HANDLER #lightgrey + generatedHash == duplicateHashRecord.hash + end note + HANDLER -> HANDLER: Return **hasDuplicateHash** + end + else hasDuplicateId == FALSE + group Store Message Hash + HANDLER -> DAO: Persist hash using saveHashFuncOverride(id, generatedHash)\nError code: 2003 + activate DAO + DAO -> DB: Persist **generatedHash** + activate DB + deactivate DB + hnote over DB #lightyellow + //request//DuplicateCheck + end note + DAO --> HANDLER: Return success + deactivate DAO + end + end + + note right of HANDLER #yellow + return { + hasDuplicateId: Boolean, + hasDuplicateHash: Boolean + } + end note +end + +@enduml diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-request-dup-check-9.1.1.svg b/docs/technical/central-ledger/assets/diagrams/sequence/seq-request-dup-check-9.1.1.svg new file mode 100644 index 000000000..988ffd39a --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-request-dup-check-9.1.1.svg @@ -0,0 +1,292 @@ + + + + + + + + + + + 9.1.1. Request Duplicate Check (incl. Transfers, Quotes, Bulk Transfers, Bulk Quotes) + + + + Central Service + + + + + + + + + + + + topic-source + + + + + topic-source + + + Processing + + + Handler + + + + + Processing + + + Handler + + + + + + + topic-event + + + + + topic-event + + + + + topic-notifcation + + + + + topic-notifcation + + + Request DAO + + + + + Request DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Request Duplicate Check + + + + + 1 + + + Consume message + + + + + 2 + + + Generate hash: + + + generatedHash + + + + + UUID Check (compareById) + + + + + 3 + + + Query hash using getDuplicateDataFuncOverride(id) + + + Error code: + + + 2003 + + + + + request + + + keyword to be replaced by + + + transfer + + + , + + + transferFulfilment + + + , + + + bulkTransfer + + + or other depending + + + on the override + + + + + 4 + + + getDuplicateDataFuncOverride + + + + request + + + DuplicateCheck + + + + + 5 + + + Return + + + duplicateHashRecord + + + + + 6 + + + Return + + + hasDuplicateId + + + + + alt + + + [hasDuplicateId == TRUE] + + + + + Hash Check (compareByHash) + + + + + generatedHash == duplicateHashRecord.hash + + + + + 7 + + + Return + + + hasDuplicateHash + + + + [hasDuplicateId == FALSE] + + + + + Store Message Hash + + + + + 8 + + + Persist hash using saveHashFuncOverride(id, generatedHash) + + + Error code: + + + 2003 + + + + + 9 + + + Persist + + + generatedHash + + + + request + + + DuplicateCheck + + + + + 10 + + + Return success + + + + + return { + + + hasDuplicateId: Boolean, + + + hasDuplicateHash: Boolean + + + } + + diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-setmodel-2.1.2.plantuml b/docs/technical/central-ledger/assets/diagrams/sequence/seq-setmodel-2.1.2.plantuml new file mode 100644 index 000000000..3d8209299 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-setmodel-2.1.2.plantuml @@ -0,0 +1,122 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * ModusBox + - Georgi Georgiev + -------------- + ******'/ + +@startuml +' declate title +title 2.1.2. Settlement Model Handler Consume +autonumber +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store +' declare actors +collections "topic-\nsettlement-model" as TOPIC_SETMODEL +control "Settlement Model\nHandler" as SETMODEL_HANDLER +collections "topic-event" as TOPIC_EVENT +entity "Settlement DAO" as SET_DAO +database "Central Store" as DB + +box "Central Service" #LightYellow + participant TOPIC_SETMODEL + participant SETMODEL_HANDLER + participant TOPIC_EVENT + participant SET_DAO + participant DB +end box + +' start flow +activate SETMODEL_HANDLER +group Settlement Model Handler Consume + alt Consume Single Message + TOPIC_SETMODEL <- SETMODEL_HANDLER: Consume settlement model\nevent message + activate TOPIC_SETMODEL + deactivate TOPIC_SETMODEL + break + group Validate Event + SETMODEL_HANDLER <-> SETMODEL_HANDLER: Validate event - Rule: type == 'setmodel' && action == 'commit'\nError codes: 2001 + end + end + group Persist Event Information + ||| + SETMODEL_HANDLER -> TOPIC_EVENT: Publish event information + ref over SETMODEL_HANDLER, TOPIC_EVENT: Event Handler Consume\n + ||| + end + + SETMODEL_HANDLER -> SET_DAO: Assign transferParicipant state(s)\nError code: 2003 + activate SET_DAO + group DB TRANSACTION + SET_DAO -> DB: Fetch transfer participant entries + activate DB + hnote over DB #lightyellow + transferParticipant + end note + DB --> SET_DAO: Return **transferParticipantRecords** + deactivate DB + + loop for each transferParticipant + note right of SET_DAO #lightgrey + Settlement models caching to be considered + end note + SET_DAO -> DB: Get settlement model by currency and ledger entry + activate DB + hnote over DB #lightyellow + settlementModel + end note + DB --> SET_DAO: Return **settlementModel** + deactivate DB + + opt settlementModel.delay == 'IMMEDIATE' && settlementModel.granularity == 'GROSS' + SET_DAO -> DB: Set states: CLOSED->PENDING_SETTLEMENT->SETTLED + activate DB + hnote over DB #lightyellow + transferParticipantStateChange + transferParticipant + end note + deactivate DB + else + SET_DAO -> DB: Set state: OPEN + activate DB + hnote over DB #lightyellow + transferParticipantStateChange + transferParticipant + end note + deactivate DB + end + + end + end + SETMODEL_HANDLER <-- SET_DAO: Return success + deactivate SET_DAO + else Consume Batch Messages + note left of SETMODEL_HANDLER #lightblue + To be delivered by future story + end note + end +end +deactivate SETMODEL_HANDLER +@enduml diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-setmodel-2.1.2.svg b/docs/technical/central-ledger/assets/diagrams/sequence/seq-setmodel-2.1.2.svg new file mode 100644 index 000000000..50323963f --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-setmodel-2.1.2.svg @@ -0,0 +1,292 @@ + + + + + + + + + + + 2.1.2. Settlement Model Handler Consume + + + + Central Service + + + + + + + + + + + + + + topic- + + + settlement-model + + + + + topic- + + + settlement-model + + + Settlement Model + + + Handler + + + + + Settlement Model + + + Handler + + + + + + + topic-event + + + + + topic-event + + + Settlement DAO + + + + + Settlement DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Settlement Model Handler Consume + + + + + alt + + + [Consume Single Message] + + + + + 1 + + + Consume settlement model + + + event message + + + + + break + + + + + Validate Event + + + + + 2 + + + Validate event - Rule: type == 'setmodel' && action == 'commit' + + + Error codes: + + + 2001 + + + + + Persist Event Information + + + + + 3 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + 4 + + + Assign transferParicipant state(s) + + + Error code: + + + 2003 + + + + + DB TRANSACTION + + + + + 5 + + + Fetch transfer participant entries + + + + transferParticipant + + + + + 6 + + + Return + + + transferParticipantRecords + + + + + loop + + + [for each transferParticipant] + + + + + Settlement models caching to be considered + + + + + 7 + + + Get settlement model by currency and ledger entry + + + + settlementModel + + + + + 8 + + + Return + + + settlementModel + + + + + opt + + + [settlementModel.delay == 'IMMEDIATE' && settlementModel.granularity == 'GROSS'] + + + + + 9 + + + Set states: CLOSED->PENDING_SETTLEMENT->SETTLED + + + + transferParticipantStateChange + + + transferParticipant + + + + + + 10 + + + Set state: OPEN + + + + transferParticipantStateChange + + + transferParticipant + + + + + 11 + + + Return success + + + + [Consume Batch Messages] + + + + + To be delivered by future story + + diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.0.plantuml b/docs/technical/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.0.plantuml new file mode 100644 index 000000000..a1ee95a55 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.0.plantuml @@ -0,0 +1,107 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * ModusBox + - Georgi Georgiev + -------------- + ******'/ + +@startuml +' declate title +title 2.3.0. Transfer Timeout + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +actor "DFSP1\nPayer" as DFSP1 +actor "DFSP2\nPayee" as DFSP2 +boundary "ML API\nAdapter" as MLAPI +control "Notification\nHandler" as NOTIFY_HANDLER +control "Timeout Prepare\nHandler" as TIMEOUT_PREP_HANDLER +collections "topic-\ntransfer-timeout" as TOPIC_TRANSFER_TIMEOUT +control "Timeout\nHandler" as TIMEOUT_HANDLER +collections "topic-\ntransfer-position" as TOPIC_TRANSFER_POSITION +control "Position\nHandler" as POS_HANDLER +collections "topic-notification" as TOPIC_NOTIFICATIONS + +box "Financial Service Providers" #lightgray + participant DFSP1 + participant DFSP2 +end box + +box "ML API Adapter Service" #lightblue + participant MLAPI + participant NOTIFY_HANDLER +end box + +box "Central Service" #lightyellow + participant TIMEOUT_PREP_HANDLER + participant TOPIC_TRANSFER_TIMEOUT + participant TIMEOUT_HANDLER + participant TOPIC_TRANSFER_POSITION + participant POS_HANDLER + participant TOPIC_NOTIFICATIONS +end box + +' start flow +activate TIMEOUT_PREP_HANDLER +activate NOTIFY_HANDLER +activate TIMEOUT_HANDLER +activate POS_HANDLER +group Transfer Expiry + ||| + ref over TIMEOUT_PREP_HANDLER, TOPIC_TRANSFER_TIMEOUT: Timeout Processing Handler Consume\n + TIMEOUT_PREP_HANDLER -> TOPIC_TRANSFER_TIMEOUT: Produce message + ||| + TOPIC_TRANSFER_TIMEOUT <- TIMEOUT_HANDLER: Consume message + ref over TOPIC_TRANSFER_TIMEOUT, TIMEOUT_HANDLER: Timeout Processing Handler Consume\n + alt transferStateId == 'RECEIVED_PREPARE' + TIMEOUT_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + else transferStateId == 'RESERVED' + TIMEOUT_HANDLER -> TOPIC_TRANSFER_POSITION: Produce message + TOPIC_TRANSFER_POSITION <- POS_HANDLER: Consume message + ref over TOPIC_TRANSFER_POSITION, TOPIC_NOTIFICATIONS: Position Hander Consume (Timeout)\n + POS_HANDLER -> TOPIC_NOTIFICATIONS: Produce message + end + opt action IN ['timeout-received', 'timeout-reserved'] + ||| + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message + ref over DFSP1, TOPIC_NOTIFICATIONS : Send notification to Participant (Payer)\n + NOTIFY_HANDLER -> DFSP1: Send callback notification + end + ||| + TOPIC_NOTIFICATIONS <- NOTIFY_HANDLER: Consume message + opt action == 'timeout-reserved' + ||| + ref over DFSP2, TOPIC_NOTIFICATIONS : Send notification to Participant (Payee)\n + NOTIFY_HANDLER -> DFSP2: Send callback notification + end +end +deactivate POS_HANDLER +deactivate TIMEOUT_HANDLER +deactivate NOTIFY_HANDLER +@enduml diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.0.svg b/docs/technical/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.0.svg new file mode 100644 index 000000000..b35a96686 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.0.svg @@ -0,0 +1,339 @@ + + + + + + + + + + + 2.3.0. Transfer Timeout + + + + Financial Service Providers + + + + ML API Adapter Service + + + + Central Service + + + + + + + + + DFSP1 + + + Payer + + + + + DFSP1 + + + Payer + + + + + DFSP2 + + + Payee + + + + + DFSP2 + + + Payee + + + + + ML API + + + Adapter + + + + + ML API + + + Adapter + + + + + Notification + + + Handler + + + + + Notification + + + Handler + + + + + Timeout Prepare + + + Handler + + + + + Timeout Prepare + + + Handler + + + + + + + topic- + + + transfer-timeout + + + + + topic- + + + transfer-timeout + + + Timeout + + + Handler + + + + + Timeout + + + Handler + + + + + + + topic- + + + transfer-position + + + + + topic- + + + transfer-position + + + Position + + + Handler + + + + + Position + + + Handler + + + + + + + topic-notification + + + + + topic-notification + + + + + + Transfer Expiry + + + + + ref + + + Timeout Processing Handler Consume + + + + + 1 + + + Produce message + + + + + 2 + + + Consume message + + + + + ref + + + Timeout Processing Handler Consume + + + + + alt + + + [transferStateId == 'RECEIVED_PREPARE'] + + + + + 3 + + + Produce message + + + + [transferStateId == 'RESERVED'] + + + + + 4 + + + Produce message + + + + + 5 + + + Consume message + + + + + ref + + + Position Hander Consume (Timeout) + + + + + 6 + + + Produce message + + + + + opt + + + [action IN ['timeout-received', 'timeout-reserved']] + + + + + 7 + + + Consume message + + + + + ref + + + Send notification to Participant (Payer) + + + + + 8 + + + Send callback notification + + + + + 9 + + + Consume message + + + + + opt + + + [action == 'timeout-reserved'] + + + + + ref + + + Send notification to Participant (Payee) + + + + + 10 + + + Send callback notification + + diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.1.plantuml b/docs/technical/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.1.plantuml new file mode 100644 index 000000000..c51976758 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.1.plantuml @@ -0,0 +1,132 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * ModusBox + - Georgi Georgiev + -------------- + ******'/ + +@startuml +' declare title +title 2.3.1. Timeout Prepare Handler + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +control "Timeout Prepare\nHandler" as TIMEOUT_PREP_HANDLER +collections "topic-\ntransfer-timeout" as TOPIC_TRANSFER_TIMEOUT +collections "topic-event" as EVENT_TOPIC +entity "Timeout DAO" as TIMEOUT_DAO +database "Central Store" as DB + +box "Central Service" #lightyellow + participant TIMEOUT_PREP_HANDLER + participant TOPIC_TRANSFER_TIMEOUT + participant EVENT_TOPIC + participant TIMEOUT_DAO + participant DB +end box + +' start flow + +group Timeout Prepare Handler + activate TIMEOUT_PREP_HANDLER + group Persist Event Information + TIMEOUT_PREP_HANDLER -> EVENT_TOPIC: Publish event information + ref over TIMEOUT_PREP_HANDLER, EVENT_TOPIC : Event Handler Consume\n + end + + group Cleanup + TIMEOUT_PREP_HANDLER -> TIMEOUT_DAO: Cleanup Fulfilled Transfers\nError code: 2003 + activate TIMEOUT_DAO + TIMEOUT_DAO -> DB: Delete fuflfilled transfers records + activate DB + deactivate DB + hnote over DB #lightyellow + DELETE et + FROM **expiringTransfer** et + JOIN **transferFulfilment** tf + ON tf.transferId = et.transferId + end note + TIMEOUT_DAO --> TIMEOUT_PREP_HANDLER: Return success + deactivate TIMEOUT_DAO + end + + group List Expired + TIMEOUT_PREP_HANDLER -> TIMEOUT_DAO: Retrieve Expired Transfers\nError code: 2003 + activate TIMEOUT_DAO + TIMEOUT_DAO -> DB: Select using index + activate DB + hnote over DB #lightyellow + SELECT * + FROM **expiringTransfer** + WHERE expirationDate < currentTimestamp + end note + TIMEOUT_DAO <-- DB: Return expired transfers + deactivate DB + TIMEOUT_DAO --> TIMEOUT_PREP_HANDLER: Return **expiredTransfersList** + deactivate TIMEOUT_DAO + end + + + + loop for each transfer in the list + ||| + note right of TIMEOUT_PREP_HANDLER #yellow + Message: + { + id: + from: , + to: , + type: application/json + content: { + headers: null, + payload: + }, + metadata: { + event: { + id: , + responseTo: null, + type: transfer, + action: timeout, + createdAt: , + state: { + status: "success", + code: 0 + } + } + } + } + end note + TIMEOUT_PREP_HANDLER -> TOPIC_TRANSFER_TIMEOUT: Publish Timeout event\nError code: 2003 + activate TOPIC_TRANSFER_TIMEOUT + deactivate TOPIC_TRANSFER_TIMEOUT + end + + deactivate TIMEOUT_PREP_HANDLER +end +@enduml diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.1.svg b/docs/technical/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.1.svg new file mode 100644 index 000000000..08083d7e3 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.1.svg @@ -0,0 +1,325 @@ + + + + + + + + + + + 2.3.1. Timeout Prepare Handler + + + + Central Service + + + + + + + Timeout Prepare + + + Handler + + + + + Timeout Prepare + + + Handler + + + + + + + topic- + + + transfer-timeout + + + + + topic- + + + transfer-timeout + + + + + topic-event + + + + + topic-event + + + Timeout DAO + + + + + Timeout DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Timeout Prepare Handler + + + + + Persist Event Information + + + + + 1 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + Cleanup + + + + + 2 + + + Cleanup Fulfilled Transfers + + + Error code: + + + 2003 + + + + + 3 + + + Delete fuflfilled transfers records + + + + DELETE et + + + FROM + + + expiringTransfer + + + et + + + JOIN + + + transferFulfilment + + + tf + + + ON tf.transferId = et.transferId + + + + + 4 + + + Return success + + + + + List Expired + + + + + 5 + + + Retrieve Expired Transfers + + + Error code: + + + 2003 + + + + + 6 + + + Select using index + + + + SELECT * + + + FROM + + + expiringTransfer + + + WHERE expirationDate < currentTimestamp + + + + + 7 + + + Return expired transfers + + + + + 8 + + + Return + + + expiredTransfersList + + + + + loop + + + [for each transfer in the list] + + + + + Message: + + + { + + + id: <uuid> + + + from: <switch>, + + + to: <payerFsp>, + + + type: application/json + + + content: { + + + headers: null, + + + payload: <transfer> + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + responseTo: null, + + + type: transfer, + + + action: timeout, + + + createdAt: <timestamp>, + + + state: { + + + status: "success", + + + code: 0 + + + } + + + } + + + } + + + } + + + + + 9 + + + Publish Timeout event + + + Error code: + + + 2003 + + diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.2.plantuml b/docs/technical/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.2.plantuml new file mode 100644 index 000000000..42132c116 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.2.plantuml @@ -0,0 +1,227 @@ +/'***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + * Gates Foundation + - Name Surname + + * ModusBox + - Georgi Georgiev + - Rajiv Mothilal + -------------- + ******'/ + +@startuml +' declare title +title 2.3.2. Timeout Handler + +autonumber + +' Actor Keys: +' boundary - APIs/Interfaces, etc +' collections - Kafka Topics +' control - Kafka Consumers +' entity - Database Access Objects +' database - Database Persistance Store + +' declare actors +control "Transfer Timeout Handler" as TIMEOUT_HANDLER +collections "topic-\ntransfer-timeout" as TOPIC_TRANSFER_TIMEOUT +collections "topic-\ntransfer-position" as TOPIC_TRANSFER_POSITION +collections "topic-\nnotification" as NOTIFICATIONS_TOPIC +collections "topic-event" as EVENT_TOPIC +entity "Timeout DAO" as TIMEOUT_DAO +database "Central Store" as DB + +box "Central Service" #lightyellow + participant TOPIC_TRANSFER_TIMEOUT + participant TIMEOUT_HANDLER + participant TOPIC_TRANSFER_POSITION + participant NOTIFICATIONS_TOPIC + participant EVENT_TOPIC + participant TIMEOUT_DAO + participant DB +end box + +' start flow + +group Timeout Handler Consume + activate TIMEOUT_HANDLER + TOPIC_TRANSFER_TIMEOUT <- TIMEOUT_HANDLER: Consume message + activate TOPIC_TRANSFER_TIMEOUT + deactivate TOPIC_TRANSFER_TIMEOUT + + group Persist Event Information + TIMEOUT_HANDLER -> EVENT_TOPIC: Publish event information + ref over TIMEOUT_HANDLER, EVENT_TOPIC: Event Handler Consume\n + end + + group Get transfer info + TIMEOUT_HANDLER -> TIMEOUT_DAO: Acquire transfer information\nError code: 2003 + activate TIMEOUT_DAO + TIMEOUT_DAO -> DB: Get transfer data and state + activate DB + hnote over DB #lightyellow + transfer + transferParticipant + participantCurrency + participant + transferStateChange + end note + TIMEOUT_DAO <-- DB: Return **transferInfo** + deactivate DB + TIMEOUT_HANDLER <-- TIMEOUT_DAO: Return **transferInfo** + deactivate TIMEOUT_DAO + end + + alt transferInfo.transferStateId == 'RECEIVED_PREPARE' + TIMEOUT_HANDLER -> TIMEOUT_DAO: Set EXPIRED_PREPARED state\nError code: 2003 + activate TIMEOUT_DAO + TIMEOUT_DAO -> DB: Insert state change + activate DB + deactivate DB + hnote over DB #lightyellow + transferStateChange + end note + TIMEOUT_HANDLER <-- TIMEOUT_DAO: Return success + deactivate TIMEOUT_DAO + + note right of TIMEOUT_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: { + Content-Length: , + Content-Type: , + Date: , + X-Forwarded-For: , + FSPIOP-Source: , + FSPIOP-Destination: , + FSPIOP-Encryption: , + FSPIOP-Signature: , + FSPIOP-URI: , + FSPIOP-HTTP-Method: + }, + payload: { + "errorInformation": { + "errorCode": 3303, + "errorDescription": "Transfer expired", + "extensionList": + } + } + }, + metadata: { + event: { + id: , + type: notification, + action: timeout-received, + createdAt: , + state: { + status: 'error', + code: + description: + } + } + } + } + end note + TIMEOUT_HANDLER -> NOTIFICATIONS_TOPIC: Publish Notification event + activate NOTIFICATIONS_TOPIC + deactivate NOTIFICATIONS_TOPIC + else transferInfo.transferStateId == 'RESERVED' + TIMEOUT_HANDLER -> TIMEOUT_DAO: Set RESERVED_TIMEOUT state\nError code: 2003 + activate TIMEOUT_DAO + TIMEOUT_DAO -> DB: Insert state change + activate DB + deactivate DB + hnote over DB #lightyellow + transferStateChange + end note + TIMEOUT_HANDLER <-- TIMEOUT_DAO: Return success + deactivate TIMEOUT_DAO + + note right of TIMEOUT_HANDLER #yellow + Message: + { + id: , + from: , + to: , + type: application/json, + content: { + headers: { + Content-Length: , + Content-Type: , + Date: , + X-Forwarded-For: , + FSPIOP-Source: , + FSPIOP-Destination: , + FSPIOP-Encryption: , + FSPIOP-Signature: , + FSPIOP-URI: , + FSPIOP-HTTP-Method: + }, + payload: { + "errorInformation": { + "errorCode": 3303, + "errorDescription": "Transfer expired", + "extensionList": + } + } + }, + metadata: { + event: { + id: , + type: position, + action: timeout-reserved, + createdAt: , + state: { + status: 'error', + code: + description: + } + } + } + } + end note + TIMEOUT_HANDLER -> TOPIC_TRANSFER_POSITION: Route & Publish Position event\nError code: 2003 + activate TOPIC_TRANSFER_POSITION + deactivate TOPIC_TRANSFER_POSITION + else + note right of TIMEOUT_HANDLER #lightgrey + Any other state is ignored + end note + end + + group Cleanup + TIMEOUT_HANDLER -> TIMEOUT_DAO: Cleanup handled expiring transfer\nError code: 2003 + activate TIMEOUT_DAO + TIMEOUT_DAO -> DB: Delete record + activate DB + deactivate DB + hnote over DB #lightyellow + expiringTransfer + end note + TIMEOUT_HANDLER <-- TIMEOUT_DAO: Return success + deactivate TIMEOUT_DAO + end + + deactivate TIMEOUT_HANDLER +end +@enduml diff --git a/docs/technical/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.2.svg b/docs/technical/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.2.svg new file mode 100644 index 000000000..0103f7ba9 --- /dev/null +++ b/docs/technical/central-ledger/assets/diagrams/sequence/seq-timeout-2.3.2.svg @@ -0,0 +1,614 @@ + + + + + + + + + + + 2.3.2. Timeout Handler + + + + Central Service + + + + + + + + + + + topic- + + + transfer-timeout + + + + + topic- + + + transfer-timeout + + + Transfer Timeout Handler + + + + + Transfer Timeout Handler + + + + + + + topic- + + + transfer-position + + + + + topic- + + + transfer-position + + + + + topic- + + + notification + + + + + topic- + + + notification + + + + + topic-event + + + + + topic-event + + + Timeout DAO + + + + + Timeout DAO + + + + + Central Store + + + + + Central Store + + + + + + + + Timeout Handler Consume + + + + + 1 + + + Consume message + + + + + Persist Event Information + + + + + 2 + + + Publish event information + + + + + ref + + + Event Handler Consume + + + + + Get transfer info + + + + + 3 + + + Acquire transfer information + + + Error code: + + + 2003 + + + + + 4 + + + Get transfer data and state + + + + transfer + + + transferParticipant + + + participantCurrency + + + participant + + + transferStateChange + + + + + 5 + + + Return + + + transferInfo + + + + + 6 + + + Return + + + transferInfo + + + + + alt + + + [transferInfo.transferStateId == 'RECEIVED_PREPARE'] + + + + + 7 + + + Set EXPIRED_PREPARED state + + + Error code: + + + 2003 + + + + + 8 + + + Insert state change + + + + transferStateChange + + + + + 9 + + + Return success + + + + + Message: + + + { + + + id: <transferId>, + + + from: <payerParticipantId>, + + + to: <payeeParticipantId>, + + + type: application/json, + + + content: { + + + headers: + + + { + + + Content-Length: <Content-Length>, + + + Content-Type: <Content-Type>, + + + Date: <Date>, + + + X-Forwarded-For: <X-Forwarded-For>, + + + FSPIOP-Source: <FSPIOP-Source>, + + + FSPIOP-Destination: <FSPIOP-Destination>, + + + FSPIOP-Encryption: <FSPIOP-Encryption>, + + + FSPIOP-Signature: <FSPIOP-Signature>, + + + FSPIOP-URI: <FSPIOP-URI>, + + + FSPIOP-HTTP-Method: <FSPIOP-HTTP-Method> + + + }, + + + payload: { + + + "errorInformation": { + + + "errorCode": 3303, + + + "errorDescription": "Transfer expired", + + + "extensionList": <transferMessage.extensionList> + + + } + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + type: notification, + + + action: timeout-received, + + + createdAt: <timestamp>, + + + state: { + + + status: 'error', + + + code: <errorInformation.errorCode> + + + description: <errorInformation.errorDescription> + + + } + + + } + + + } + + + } + + + + + 10 + + + Publish Notification event + + + + [transferInfo.transferStateId == 'RESERVED'] + + + + + 11 + + + Set RESERVED_TIMEOUT state + + + Error code: + + + 2003 + + + + + 12 + + + Insert state change + + + + transferStateChange + + + + + 13 + + + Return success + + + + + Message: + + + { + + + id: <transferId>, + + + from: <payerParticipantId>, + + + to: <payeeParticipantId>, + + + type: application/json, + + + content: { + + + headers: + + + { + + + Content-Length: <Content-Length>, + + + Content-Type: <Content-Type>, + + + Date: <Date>, + + + X-Forwarded-For: <X-Forwarded-For>, + + + FSPIOP-Source: <FSPIOP-Source>, + + + FSPIOP-Destination: <FSPIOP-Destination>, + + + FSPIOP-Encryption: <FSPIOP-Encryption>, + + + FSPIOP-Signature: <FSPIOP-Signature>, + + + FSPIOP-URI: <FSPIOP-URI>, + + + FSPIOP-HTTP-Method: <FSPIOP-HTTP-Method> + + + }, + + + payload: { + + + "errorInformation": { + + + "errorCode": 3303, + + + "errorDescription": "Transfer expired", + + + "extensionList": <transferMessage.extensionList> + + + } + + + } + + + }, + + + metadata: { + + + event: { + + + id: <uuid>, + + + type: position, + + + action: timeout-reserved, + + + createdAt: <timestamp>, + + + state: { + + + status: 'error', + + + code: <errorInformation.errorCode> + + + description: <errorInformation.errorDescription> + + + } + + + } + + + } + + + } + + + + + 14 + + + Route & Publish Position event + + + Error code: + + + 2003 + + + + + + Any other state is ignored + + + + + Cleanup + + + + + 15 + + + Cleanup handled expiring transfer + + + Error code: + + + 2003 + + + + + 16 + + + Delete record + + + + expiringTransfer + + + + + 17 + + + Return success + + diff --git a/docs/technical/central-ledger/transfers/1.1.0-prepare-transfer-request.md b/docs/technical/central-ledger/transfers/1.1.0-prepare-transfer-request.md new file mode 100644 index 000000000..e98c606e8 --- /dev/null +++ b/docs/technical/central-ledger/transfers/1.1.0-prepare-transfer-request.md @@ -0,0 +1,16 @@ +# Prepare Transfer Request + +Sequence design diagram for Prepare Transfer Request process. + +## References within Sequence Diagram + +* [Prepare Handler Consume (1.1.1.a)](1.1.1.a-prepare-handler-consume.md) +* **Not Implemented** [Prepare Handler Consume (1.1.1.b)](1.1.1.b-prepare-handler-consume.md) +* [Position Handler Consume (1.1.2.a)](1.1.2.a-position-handler-consume.md) +* **Not Implemented** [Position Handler Consume (1.1.2.b)](1.1.2.b-position-handler-consume.md) +* [Send notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant.md) +* **Not Implemented** [Send notification to Participant (1.1.4.b)](1.1.4.b-send-notification-to-participant.md) + +## Sequence Diagram + +![seq-prepare-1.1.0.svg](../assets/diagrams/sequence/seq-prepare-1.1.0.svg) diff --git a/docs/technical/central-ledger/transfers/1.1.1.a-prepare-handler-consume.md b/docs/technical/central-ledger/transfers/1.1.1.a-prepare-handler-consume.md new file mode 100644 index 000000000..b0a401b5f --- /dev/null +++ b/docs/technical/central-ledger/transfers/1.1.1.a-prepare-handler-consume.md @@ -0,0 +1,11 @@ +# Prepare handler consume + +Sequence design diagram for Prepare Handler Consume process. + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) + +## Sequence Diagram + +![seq-prepare-1.1.1.a.svg](../assets/diagrams/sequence/seq-prepare-1.1.1.a.svg) diff --git a/docs/technical/central-ledger/transfers/1.1.1.b-prepare-handler-consume.md b/docs/technical/central-ledger/transfers/1.1.1.b-prepare-handler-consume.md new file mode 100644 index 000000000..72e6784d5 --- /dev/null +++ b/docs/technical/central-ledger/transfers/1.1.1.b-prepare-handler-consume.md @@ -0,0 +1,11 @@ +# Prepare handler consume + +Sequence design diagram for Prepare Handler Consume process. + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) + +## Sequence Diagram + +![seq-prepare-1.1.1.b.svg](../assets/diagrams/sequence/seq-prepare-1.1.1.b.svg) diff --git a/docs/technical/central-ledger/transfers/1.1.2.a-position-handler-consume.md b/docs/technical/central-ledger/transfers/1.1.2.a-position-handler-consume.md new file mode 100644 index 000000000..8904fe97f --- /dev/null +++ b/docs/technical/central-ledger/transfers/1.1.2.a-position-handler-consume.md @@ -0,0 +1,11 @@ +# Position handler consume + +Sequence design diagram for Position Handler Consume process. + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) + +## Sequence Diagram + +![seq-prepare-1.1.2.a.svg](../assets/diagrams/sequence/seq-prepare-1.1.2.a.svg) diff --git a/docs/technical/central-ledger/transfers/1.1.2.b-position-handler-consume.md b/docs/technical/central-ledger/transfers/1.1.2.b-position-handler-consume.md new file mode 100644 index 000000000..161bea8d9 --- /dev/null +++ b/docs/technical/central-ledger/transfers/1.1.2.b-position-handler-consume.md @@ -0,0 +1,11 @@ +# Position handler consume + +Sequence design diagram for Position Handler Consume process. + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) + +## Sequence Diagram + +![seq-prepare-1.1.2.b.svg](../assets/diagrams/sequence/seq-prepare-1.1.2.b.svg) diff --git a/docs/technical/central-ledger/transfers/1.1.4.a-send-notification-to-participant-v1.1.md b/docs/technical/central-ledger/transfers/1.1.4.a-send-notification-to-participant-v1.1.md new file mode 100644 index 000000000..9fd4fb1c5 --- /dev/null +++ b/docs/technical/central-ledger/transfers/1.1.4.a-send-notification-to-participant-v1.1.md @@ -0,0 +1,11 @@ +# Send Notification to Participant v1.1 + +Sequence design diagram for the Send Notification to Participant request. + +## References within Sequence Diagram + +* [9.1.0-event-handler-consume](../../central-event-processor/9.1.0-event-handler-placeholder.md) + +## Sequence Diagram + +![seq-prepare-1.1.4.a-v1.1.svg](../assets/diagrams/sequence/seq-prepare-1.1.4.a-v1.1.svg) diff --git a/docs/technical/central-ledger/transfers/1.1.4.a-send-notification-to-participant.md b/docs/technical/central-ledger/transfers/1.1.4.a-send-notification-to-participant.md new file mode 100644 index 000000000..12b1972d6 --- /dev/null +++ b/docs/technical/central-ledger/transfers/1.1.4.a-send-notification-to-participant.md @@ -0,0 +1,11 @@ +# Send Notification to Participant + +Sequence design diagram for the Send Notification to Participant request. + +## References within Sequence Diagram + +* [9.1.0-event-handler-consume](../../central-event-processor/9.1.0-event-handler-placeholder.md) + +## Sequence Diagram + +![seq-prepare-1.1.4.a.svg](../assets/diagrams/sequence/seq-prepare-1.1.4.a.svg) diff --git a/docs/technical/central-ledger/transfers/1.1.4.b-send-notification-to-participant.md b/docs/technical/central-ledger/transfers/1.1.4.b-send-notification-to-participant.md new file mode 100644 index 000000000..c22b6c94f --- /dev/null +++ b/docs/technical/central-ledger/transfers/1.1.4.b-send-notification-to-participant.md @@ -0,0 +1,11 @@ +# Send Notification to Participant + +Sequence design diagram for the Send Notification to Participant request. + +## References within Sequence Diagram + +* [9.1.0-event-handler-consume](../../central-event-processor/9.1.0-event-handler-placeholder.md) + +## Sequence Diagram + +![seq-prepare-1.1.4.b.svg](../assets/diagrams/sequence/seq-prepare-1.1.4.b.svg) diff --git a/docs/technical/central-ledger/transfers/1.3.0-position-handler-consume-v1.1.md b/docs/technical/central-ledger/transfers/1.3.0-position-handler-consume-v1.1.md new file mode 100644 index 000000000..3f12ab0b1 --- /dev/null +++ b/docs/technical/central-ledger/transfers/1.3.0-position-handler-consume-v1.1.md @@ -0,0 +1,14 @@ +# Position Handler Consume v1.1 + +Sequence design diagram for Position Handler Consume process. + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) +* [Prepare Position Handler Consume (1.3.1)](1.3.1-prepare-position-handler-consume.md) +* [Fufil Position Handler Consume (1.3.2)](1.3.2-fulfil-position-handler-consume-v1.1.md) +* [Abort Position Handler Consume (1.3.3)](1.3.3-abort-position-handler-consume.md) + +## Sequence Diagram + +![seq-position-1.3.0-v1.1.svg](../assets/diagrams/sequence/seq-position-1.3.0-v1.1.svg) diff --git a/docs/technical/central-ledger/transfers/1.3.0-position-handler-consume.md b/docs/technical/central-ledger/transfers/1.3.0-position-handler-consume.md new file mode 100644 index 000000000..a3942172f --- /dev/null +++ b/docs/technical/central-ledger/transfers/1.3.0-position-handler-consume.md @@ -0,0 +1,14 @@ +# Position Handler Consume + +Sequence design diagram for Position Handler Consume process. + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) +* [Prepare Position Handler Consume (1.3.1)](1.3.1-prepare-position-handler-consume.md) +* [Fufil Position Handler Consume (1.3.2)](1.3.2-fulfil-position-handler-consume.md) +* [Abort Position Handler Consume (1.3.3)](1.3.3-abort-position-handler-consume.md) + +## Sequence Diagram + +![seq-position-1.3.0.svg](../assets/diagrams/sequence/seq-position-1.3.0.svg) diff --git a/docs/technical/central-ledger/transfers/1.3.1-prepare-position-handler-consume.md b/docs/technical/central-ledger/transfers/1.3.1-prepare-position-handler-consume.md new file mode 100644 index 000000000..2ab39456e --- /dev/null +++ b/docs/technical/central-ledger/transfers/1.3.1-prepare-position-handler-consume.md @@ -0,0 +1,7 @@ +# Prepare Position Handler Consume + +Sequence design diagram for Prepare Position Handler Consume process. + +## Sequence Diagram + +![seq-position-1.3.1-prepare.svg](../assets/diagrams/sequence/seq-position-1.3.1-prepare.svg) diff --git a/docs/technical/central-ledger/transfers/1.3.2-fulfil-position-handler-consume-v1.1.md b/docs/technical/central-ledger/transfers/1.3.2-fulfil-position-handler-consume-v1.1.md new file mode 100644 index 000000000..71799b0ea --- /dev/null +++ b/docs/technical/central-ledger/transfers/1.3.2-fulfil-position-handler-consume-v1.1.md @@ -0,0 +1,7 @@ +# Fulfil Position Handler Consume v1.1 + +Sequence design diagram for Fulfil Position Handler Consume process. + +## Sequence Diagram + +![seq-position-1.3.2-fulfil-v1.1.svg](../assets/diagrams/sequence/seq-position-1.3.2-fulfil-v1.1.svg) diff --git a/docs/technical/central-ledger/transfers/1.3.2-fulfil-position-handler-consume.md b/docs/technical/central-ledger/transfers/1.3.2-fulfil-position-handler-consume.md new file mode 100644 index 000000000..25e5b2774 --- /dev/null +++ b/docs/technical/central-ledger/transfers/1.3.2-fulfil-position-handler-consume.md @@ -0,0 +1,7 @@ +# Fulfil Position Handler Consume + +Sequence design diagram for Fulfil Position Handler Consume process. + +## Sequence Diagram + +![seq-position-1.3.2-fulfil.svg](../assets/diagrams/sequence/seq-position-1.3.2-fulfil.svg) diff --git a/docs/technical/central-ledger/transfers/1.3.3-abort-position-handler-consume.md b/docs/technical/central-ledger/transfers/1.3.3-abort-position-handler-consume.md new file mode 100644 index 000000000..9ab80dc75 --- /dev/null +++ b/docs/technical/central-ledger/transfers/1.3.3-abort-position-handler-consume.md @@ -0,0 +1,7 @@ +# Abort Position Handler Consume + +Sequence design diagram for Abort Position Handler Consume process. + +## Sequence Diagram + +![seq-position-1.3.3-abort.svg](../assets/diagrams/sequence/seq-position-1.3.3-abort.svg) diff --git a/docs/technical/central-ledger/transfers/2.1.0-fulfil-transfer-request-v1.1.md b/docs/technical/central-ledger/transfers/2.1.0-fulfil-transfer-request-v1.1.md new file mode 100644 index 000000000..d7a71954f --- /dev/null +++ b/docs/technical/central-ledger/transfers/2.1.0-fulfil-transfer-request-v1.1.md @@ -0,0 +1,13 @@ +# Fulfil Transfer Request success v1.1 + +Sequence design diagram for the Fulfil Success Transfer request. + +## References within Sequence Diagram + +* [Fulfil Handler Consume (Success) (2.1.1)](2.1.1-fulfil-handler-consume-v1.1.md) +* [Position Handler Consume (Success) (1.3.2)](1.3.2-fulfil-position-handler-consume-v1.1.md) +* [Send Notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant-v1.1-v1.1.md) + +## Sequence Diagram + +![seq-fulfil-2.1.0-v1.1.svg](../assets/diagrams/sequence/seq-fulfil-2.1.0-v1.1.svg) diff --git a/docs/technical/central-ledger/transfers/2.1.0-fulfil-transfer-request.md b/docs/technical/central-ledger/transfers/2.1.0-fulfil-transfer-request.md new file mode 100644 index 000000000..c552a057a --- /dev/null +++ b/docs/technical/central-ledger/transfers/2.1.0-fulfil-transfer-request.md @@ -0,0 +1,13 @@ +# Fulfil Transfer Request success + +Sequence design diagram for the Fulfil Success Transfer request. + +## References within Sequence Diagram + +* [Fulfil Handler Consume (Success) (2.1.1)](2.1.1-fulfil-handler-consume.md) +* [Position Handler Consume (Success) (1.3.2)](1.3.2-fulfil-position-handler-consume.md) +* [Send Notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant.md) + +## Sequence Diagram + +![seq-fulfil-2.1.0.svg](../assets/diagrams/sequence/seq-fulfil-2.1.0.svg) diff --git a/docs/technical/central-ledger/transfers/2.1.1-fulfil-handler-consume-v1.1.md b/docs/technical/central-ledger/transfers/2.1.1-fulfil-handler-consume-v1.1.md new file mode 100644 index 000000000..69f2afa87 --- /dev/null +++ b/docs/technical/central-ledger/transfers/2.1.1-fulfil-handler-consume-v1.1.md @@ -0,0 +1,13 @@ +# Fulfil Handler Consume (Success) v1.1 + +Sequence design diagram for the Fulfil Handler Consume process. + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) +* [seq-signature-validation](../../central-event-processor/signature-validation.md) +* [Send Notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant-v1.1.md) + +## Sequence Diagram + +![seq-fulfil-2.1.1-v1.1.svg](../assets/diagrams/sequence/seq-fulfil-2.1.1-v1.1.svg) diff --git a/docs/technical/central-ledger/transfers/2.1.1-fulfil-handler-consume.md b/docs/technical/central-ledger/transfers/2.1.1-fulfil-handler-consume.md new file mode 100644 index 000000000..05f7e38f0 --- /dev/null +++ b/docs/technical/central-ledger/transfers/2.1.1-fulfil-handler-consume.md @@ -0,0 +1,13 @@ +# Fulfil Handler Consume (Success) + +Sequence design diagram for the Fulfil Handler Consume process. + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) +* [seq-signature-validation](../../central-event-processor/signature-validation.md) +* [Send Notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant.md) + +## Sequence Diagram + +![seq-fulfil-2.1.1.svg](../assets/diagrams/sequence/seq-fulfil-2.1.1.svg) diff --git a/docs/technical/central-ledger/transfers/2.2.0-fulfil-reject-transfer-v1.1.md b/docs/technical/central-ledger/transfers/2.2.0-fulfil-reject-transfer-v1.1.md new file mode 100644 index 000000000..ede9acee1 --- /dev/null +++ b/docs/technical/central-ledger/transfers/2.2.0-fulfil-reject-transfer-v1.1.md @@ -0,0 +1,7 @@ +# Payee sends a Fulfil Abort Transfer request v1.1 + +Sequence design diagram for the Fulfil Reject Transfer process for version 1.1. of the API. + +## Sequence Diagram + +![seq-reject-2.2.0-v1.1.svg](../assets/diagrams/sequence/seq-reject-2.2.0-v1.1.svg) diff --git a/docs/technical/central-ledger/transfers/2.2.0-fulfil-reject-transfer.md b/docs/technical/central-ledger/transfers/2.2.0-fulfil-reject-transfer.md new file mode 100644 index 000000000..fc193a59d --- /dev/null +++ b/docs/technical/central-ledger/transfers/2.2.0-fulfil-reject-transfer.md @@ -0,0 +1,13 @@ +# [Outdated] Payee sends a Fulfil Reject Transfer request + +Sequence design diagram for the Fulfil Reject Transfer process. + +## References within Sequence Diagram + +* [Fulfil Handler Consume (Reject/Abort)(2.2.1)](2.2.1-fulfil-reject-handler.md) +* [Position Handler Consume (Reject)(1.3.3)](1.3.3-abort-position-handler-consume.md) +* [Send Notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant-v1.1.md) + +## Sequence Diagram + +![seq-reject-2.2.0.svg](../assets/diagrams/sequence/seq-reject-2.2.0.svg) diff --git a/docs/technical/central-ledger/transfers/2.2.0.a-fulfil-abort-transfer-v1.1.md b/docs/technical/central-ledger/transfers/2.2.0.a-fulfil-abort-transfer-v1.1.md new file mode 100644 index 000000000..c50c356a0 --- /dev/null +++ b/docs/technical/central-ledger/transfers/2.2.0.a-fulfil-abort-transfer-v1.1.md @@ -0,0 +1,13 @@ +# Payee sends a PUT call on /error end-point for a Transfer request v1.1 + +Sequence design diagram for the Fulfil Reject Transfer process for version 1.1. of the API. + +## References within Sequence Diagram + +* [Fulfil Handler Consume (Abort)(2.2.1)](2.2.1-fulfil-reject-handler-v1.1.md) +* [Position Handler Consume (Reject)(1.3.3)](1.3.3-abort-position-handler-consume.md) +* [Send Notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant-v1.1.md) + +## Sequence Diagram + +![seq-reject-2.2.0.a-v1.1.svg](../assets/diagrams/sequence/seq-reject-2.2.0.a-v1.1.svg) diff --git a/docs/technical/central-ledger/transfers/2.2.0.a-fulfil-abort-transfer.md b/docs/technical/central-ledger/transfers/2.2.0.a-fulfil-abort-transfer.md new file mode 100644 index 000000000..0a1639855 --- /dev/null +++ b/docs/technical/central-ledger/transfers/2.2.0.a-fulfil-abort-transfer.md @@ -0,0 +1,13 @@ +# Payee sends a PUT call on /error end-point for a Transfer request + +Sequence design diagram for the Fulfil Reject Transfer process. + +## References within Sequence Diagram + +* [Fulfil Handler Consume (Reject/Abort)(2.2.1)](2.2.1-fulfil-reject-handler.md) +* [Position Handler Consume (Reject)(1.3.3)](1.3.3-abort-position-handler-consume.md) +* [Send Notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant.md) + +## Sequence Diagram + +![seq-reject-2.2.0.a.svg](../assets/diagrams/sequence/seq-reject-2.2.0.a.svg) diff --git a/docs/technical/central-ledger/transfers/2.2.1-fulfil-reject-handler-v1.1.md b/docs/technical/central-ledger/transfers/2.2.1-fulfil-reject-handler-v1.1.md new file mode 100644 index 000000000..1098c1c2f --- /dev/null +++ b/docs/technical/central-ledger/transfers/2.2.1-fulfil-reject-handler-v1.1.md @@ -0,0 +1,7 @@ +# Fulfil Handler Consume (Reject/Abort) + +Sequence design diagram for the Fulfil Handler Consume Reject/Abort process for version 1.1. of the API. + +## Sequence Diagram + +![seq-reject-2.2.1-v1.1.svg](../assets/diagrams/sequence/seq-reject-2.2.1-v1.1.svg) diff --git a/docs/technical/central-ledger/transfers/2.2.1-fulfil-reject-handler.md b/docs/technical/central-ledger/transfers/2.2.1-fulfil-reject-handler.md new file mode 100644 index 000000000..b4512e034 --- /dev/null +++ b/docs/technical/central-ledger/transfers/2.2.1-fulfil-reject-handler.md @@ -0,0 +1,13 @@ +# Fulfil Handler Consume (Reject/Abort) + +Sequence design diagram for the Fulfil Handler Consume Reject/Abort process. + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) +* [seq-signature-validation](../../central-event-processor/signature-validation.md) +* [Send Notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant.md) + +## Sequence Diagram + +![seq-reject-2.2.1.svg](../assets/diagrams/sequence/seq-reject-2.2.1.svg) diff --git a/docs/technical/central-ledger/transfers/2.3.0-transfer-timeout.md b/docs/technical/central-ledger/transfers/2.3.0-transfer-timeout.md new file mode 100644 index 000000000..03d9f36c1 --- /dev/null +++ b/docs/technical/central-ledger/transfers/2.3.0-transfer-timeout.md @@ -0,0 +1,13 @@ +# Transfer Timeout + +Sequence design diagram for the Transfer Timeout process. + +## References within Sequence Diagram + +* [Timeout Handler Consume (2.3.1)](2.3.1-timeout-handler-consume.md) +* [Position Handler Consume (Timeout)(1.3.3)](1.3.3-abort-position-handler-consume.md) +* [Send Notification to Participant (1.1.4.a)](1.1.4.a-send-notification-to-participant.md) + +## Sequence Diagram + +![seq-timeout-2.3.0.svg](../assets/diagrams/sequence/seq-timeout-2.3.0.svg) diff --git a/docs/technical/central-ledger/transfers/2.3.1-timeout-handler-consume.md b/docs/technical/central-ledger/transfers/2.3.1-timeout-handler-consume.md new file mode 100644 index 000000000..dd1415f1f --- /dev/null +++ b/docs/technical/central-ledger/transfers/2.3.1-timeout-handler-consume.md @@ -0,0 +1,11 @@ +# Timeout Handler Consume + +Sequence design diagram for the Timeout Handler Consume process. + +## References within Sequence Diagram + +* [Event Handler Consume (9.1.0)](../../central-event-processor/9.1.0-event-handler-placeholder.md) + +## Sequence Diagram + +![seq-timeout-2.3.1.svg](../assets/diagrams/sequence/seq-timeout-2.3.1.svg) diff --git a/docs/technical/central-ledger/transfers/README.md b/docs/technical/central-ledger/transfers/README.md new file mode 100644 index 000000000..ba8fc02cf --- /dev/null +++ b/docs/technical/central-ledger/transfers/README.md @@ -0,0 +1,8 @@ +# Mojaloop Transfer operations + +Operational processes that is the core of the transfer operational process; + +- Prepare process +- Fulfil process +- Notifications process +- Reject/Abort process