@mojaloop/central-ledger 9.2.2 → 15.1.3-snapshot.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (256) hide show
  1. package/.circleci/config.yml +625 -204
  2. package/.env +3 -2
  3. package/.ncurc.yaml +9 -0
  4. package/.nvmrc +1 -1
  5. package/.versionrc +15 -0
  6. package/CHANGELOG.md +353 -0
  7. package/CODEOWNERS +31 -0
  8. package/Dockerfile +20 -14
  9. package/LICENSE.md +4 -4
  10. package/Onboarding.md +0 -7
  11. package/README.md +99 -22
  12. package/audit-resolve.json +136 -1
  13. package/config/default.json +82 -27
  14. package/docker/central-ledger/default.json +68 -21
  15. package/docker/ml-api-adapter/default.json +10 -1
  16. package/docker/wait-for/wait-for-objstore.sh +1 -6
  17. package/docker/wait-for/wait-for.env +1 -1
  18. package/docker-compose.integration.yml +8 -5
  19. package/docker-compose.yml +73 -16
  20. package/migrations/310203_transferParticipant-indexes.js +38 -0
  21. package/migrations/310503_participantLimit-indexes-composite.js +38 -0
  22. package/migrations/{400401_settlementWindowStateChange-indexes.js → 400401_settlmentWindowStateChange-indexes.js} +0 -0
  23. package/migrations/401301_settlementModel-indexes.js +2 -0
  24. package/migrations/500401_quote-hotfix-2719.js +58 -0
  25. package/migrations/500501_feature-fixSubIdRef.js +53 -0
  26. package/migrations/500601_party-2480.js +63 -0
  27. package/migrations/501001_quoteExtension-quote-service-174.js +46 -0
  28. package/migrations/501002_quoteExtension-2522.js +61 -0
  29. package/migrations/800101_feature-fixSubIdRef.js +90 -0
  30. package/migrations/910102_hotfix954.js +4 -1
  31. package/migrations/940100_quotePartyIdInfoExtension.js +52 -0
  32. package/migrations/940101_quotePartyIdInfoExtension-2522.js +64 -0
  33. package/migrations/950100_settlementContentAggregation-decimal184.js +40 -0
  34. package/migrations/950101_transferParticipantStateChange.js +46 -0
  35. package/migrations/950102_settlementModel-adjustPosition.js +42 -0
  36. package/migrations/950103_dropTransferParticipantStateChange.js +47 -0
  37. package/migrations/950104_settlementModel-settlementAccountTypeId.js +79 -0
  38. package/migrations/950106_unique_settlement_model_ledger_account_currency.js +38 -0
  39. package/migrations/950107_settlementWindowContent_foreign_settlementModel.js +60 -0
  40. package/package.json +99 -81
  41. package/scripts/_wait4_all.js +146 -0
  42. package/seeds/amountType.js +4 -6
  43. package/seeds/balanceOfPayments.js +4 -6
  44. package/seeds/bulkProcessingState.js +4 -6
  45. package/seeds/bulkTransferState.js +4 -6
  46. package/seeds/currency.js +4 -6
  47. package/seeds/endpointType.js +128 -7
  48. package/seeds/ledgerAccountType.js +11 -10
  49. package/seeds/ledgerEntryType.js +5 -7
  50. package/seeds/participant.js +4 -6
  51. package/seeds/participantLimitType.js +4 -6
  52. package/seeds/partyIdentifierType.js +4 -6
  53. package/seeds/partyType.js +4 -6
  54. package/seeds/settlementDelay.js +4 -6
  55. package/seeds/settlementGranularity.js +4 -6
  56. package/seeds/settlementInterchange.js +4 -6
  57. package/seeds/settlementState.js +4 -6
  58. package/seeds/settlementWindow1State.js +4 -6
  59. package/seeds/transactionInitiator.js +4 -6
  60. package/seeds/transactionInitiatorType.js +4 -6
  61. package/seeds/transactionScenario.js +4 -6
  62. package/seeds/transferParticipantRoleType.js +4 -6
  63. package/seeds/transferState.js +9 -6
  64. package/src/api/interface/swagger.json +728 -948
  65. package/src/api/ledgerAccountTypes/handler.js +55 -0
  66. package/src/api/ledgerAccountTypes/routes.js +63 -0
  67. package/src/api/metrics/handler.js +2 -2
  68. package/src/api/metrics/routes.js +1 -1
  69. package/src/api/participants/handler.js +43 -35
  70. package/src/api/participants/routes.js +13 -13
  71. package/src/api/root/routes.js +2 -2
  72. package/src/api/settlementModels/handler.js +9 -26
  73. package/src/api/settlementModels/routes.js +4 -4
  74. package/src/api/transactions/handler.js +46 -0
  75. package/src/api/transactions/routes.js +45 -0
  76. package/src/domain/bulkTransfer/index.js +6 -5
  77. package/src/domain/ledgerAccountTypes/index.js +58 -0
  78. package/src/domain/participant/index.js +55 -4
  79. package/src/domain/position/index.js +18 -2
  80. package/src/domain/settlement/index.js +39 -6
  81. package/src/domain/transactions/index.js +61 -0
  82. package/src/domain/transfer/index.js +22 -2
  83. package/src/domain/transfer/transform.js +3 -3
  84. package/src/handlers/admin/handler.js +24 -32
  85. package/src/handlers/bulk/fulfil/handler.js +89 -56
  86. package/src/handlers/bulk/get/handler.js +203 -0
  87. package/src/handlers/bulk/index.js +4 -1
  88. package/src/handlers/bulk/prepare/handler.js +30 -29
  89. package/src/handlers/bulk/processing/handler.js +61 -32
  90. package/src/handlers/bulk/shared/validator.js +13 -1
  91. package/src/handlers/index.js +18 -9
  92. package/src/handlers/positions/handler.js +67 -46
  93. package/src/handlers/register.js +7 -7
  94. package/src/handlers/timeouts/handler.js +9 -4
  95. package/src/handlers/transfers/handler.js +408 -182
  96. package/src/handlers/transfers/validator.js +41 -11
  97. package/src/lib/cache.js +8 -34
  98. package/src/lib/config.js +5 -7
  99. package/src/lib/enum.js +22 -22
  100. package/src/lib/enumCached.js +76 -0
  101. package/src/lib/healthCheck/subServiceHealth.js +2 -2
  102. package/src/lib/requestLogger.js +9 -9
  103. package/src/lib/urlParser.js +1 -1
  104. package/src/models/bulkTransfer/bulkTransfer.js +6 -6
  105. package/src/models/bulkTransfer/bulkTransferAssociation.js +3 -3
  106. package/src/models/bulkTransfer/bulkTransferDuplicateCheck.js +4 -4
  107. package/src/models/bulkTransfer/bulkTransferExtension.js +2 -2
  108. package/src/models/bulkTransfer/bulkTransferFulfilmentDuplicateCheck.js +4 -4
  109. package/src/models/bulkTransfer/bulkTransferStateChange.js +7 -7
  110. package/src/models/bulkTransfer/facade.js +54 -3
  111. package/src/models/bulkTransfer/individualTransfer.js +2 -2
  112. package/src/models/ilpPackets/ilpPacket.js +36 -0
  113. package/src/models/ledgerAccountType/ledgerAccountType.js +139 -3
  114. package/src/models/misc/migrationLock.js +1 -1
  115. package/src/models/misc/segment.js +1 -1
  116. package/src/models/participant/facade.js +226 -76
  117. package/src/models/participant/participant.js +6 -5
  118. package/src/models/participant/participantCached.js +8 -0
  119. package/src/models/participant/participantCurrency.js +7 -7
  120. package/src/models/participant/participantCurrencyCached.js +11 -1
  121. package/src/models/participant/participantLimit.js +13 -13
  122. package/src/models/participant/participantLimitCached.js +124 -0
  123. package/src/models/participant/participantPosition.js +34 -5
  124. package/src/models/participant/participantPositionChange.js +10 -2
  125. package/src/models/position/facade.js +112 -18
  126. package/src/models/position/participantPosition.js +6 -6
  127. package/src/models/settlement/settlementModel.js +92 -17
  128. package/src/models/settlement/settlementModelCached.js +139 -0
  129. package/src/models/transfer/facade.js +97 -32
  130. package/src/models/transfer/ilpPacket.js +4 -4
  131. package/src/models/transfer/transfer.js +7 -7
  132. package/src/models/transfer/transferDuplicateCheck.js +21 -5
  133. package/src/models/transfer/transferError.js +5 -5
  134. package/src/models/transfer/transferErrorDuplicateCheck.js +4 -4
  135. package/src/models/transfer/transferExtension.js +4 -4
  136. package/src/models/transfer/transferFulfilment.js +5 -5
  137. package/src/models/transfer/transferFulfilmentDuplicateCheck.js +4 -4
  138. package/src/models/transfer/transferParticipant.js +3 -3
  139. package/src/models/transfer/transferStateChange.js +11 -11
  140. package/src/models/transfer/transferTimeout.js +5 -5
  141. package/src/schema/bulkTransfer.js +4 -4
  142. package/src/shared/plugins.js +10 -9
  143. package/src/shared/setup.js +69 -46
  144. package/test/integration/domain/participant/index.test.js +2 -0
  145. package/test/integration/handlers/handlers.test.js +605 -166
  146. package/test/integration/handlers/root.test.js +1 -1
  147. package/test/integration/helpers/hubAccounts.js +62 -0
  148. package/test/integration/helpers/ilpPacket.js +1 -1
  149. package/test/integration/helpers/participantFundsInOut.js +80 -0
  150. package/test/integration/helpers/participantLimit.js +6 -1
  151. package/test/integration/helpers/settlementModels.js +88 -0
  152. package/test/integration/helpers/testConsumer.js +163 -0
  153. package/test/integration/helpers/testProducer.js +0 -1
  154. package/test/integration/helpers/transferDuplicateCheck.js +1 -1
  155. package/test/integration/helpers/transferStateChange.js +1 -1
  156. package/test/integration/helpers/transferTestHelper.js +3 -5
  157. package/test/integration/models/transfer/transferStateChange.test.js +6 -0
  158. package/test/unit/api/ledgerAccountTypes/handler.test.js +126 -0
  159. package/test/unit/api/ledgerAccountTypes/routes.test.js +52 -0
  160. package/test/unit/api/participants/handler.test.js +75 -33
  161. package/test/unit/api/root/handler.test.js +1 -1
  162. package/test/unit/api/root/routes.test.js +2 -2
  163. package/test/unit/api/settlementModels/handler.test.js +21 -57
  164. package/test/unit/api/transactions/handler.test.js +108 -0
  165. package/test/unit/api/transactions/routes.test.js +38 -0
  166. package/test/unit/domain/ledgerAccountTypes/index.test.js +197 -0
  167. package/test/unit/domain/participant/index.test.js +115 -2
  168. package/test/unit/domain/settlement/index.test.js +199 -29
  169. package/test/unit/domain/transactions/index.test.js +128 -0
  170. package/test/unit/domain/transfer/index.test.js +1 -0
  171. package/test/unit/domain/transfer/transform.test.js +2 -0
  172. package/test/unit/handlers/admin/handler.test.js +5 -5
  173. package/test/unit/handlers/bulk/get/handler.test.js +401 -0
  174. package/test/unit/handlers/index.test.js +6 -0
  175. package/test/unit/handlers/positions/handler.test.js +26 -0
  176. package/test/unit/handlers/register.test.js +2 -0
  177. package/test/unit/handlers/transfers/handler.test.js +491 -36
  178. package/test/unit/handlers/transfers/validator.test.js +31 -31
  179. package/test/unit/lib/cache.test.js +0 -64
  180. package/test/unit/lib/cachingOfEnums.test.js +121 -0
  181. package/test/unit/lib/config.test.js +34 -0
  182. package/test/unit/lib/enum.test.js +6 -1
  183. package/test/unit/lib/enumCached.test.js +82 -0
  184. package/test/unit/lib/healthCheck/subServiceHealth.test.js +2 -0
  185. package/test/unit/lib/requestLogger.test.js +14 -12
  186. package/test/unit/models/ilpPackets/ilpPacket.test.js +89 -0
  187. package/test/unit/models/ledgerAccountType/ledgerAccountType.test.js +255 -6
  188. package/test/unit/models/misc/migrationLock.test.js +4 -0
  189. package/test/unit/models/misc/segment.test.js +5 -0
  190. package/test/unit/models/participant/facade.test.js +493 -54
  191. package/test/unit/models/participant/participant.test.js +4 -0
  192. package/test/unit/models/participant/participantCurrency.test.js +22 -9
  193. package/test/unit/models/participant/participantCurrencyCached.test.js +1 -1
  194. package/test/unit/models/participant/participantLimit.test.js +97 -0
  195. package/test/unit/models/participant/participantLimitCached.test.js +232 -0
  196. package/test/unit/models/participant/participantPosition.test.js +217 -0
  197. package/test/unit/models/participant/participantPositionChange.test.js +3 -0
  198. package/test/unit/models/position/facade.test.js +318 -29
  199. package/test/unit/models/position/participantPosition.test.js +22 -7
  200. package/test/unit/models/settlement/settlementModel.test.js +18 -37
  201. package/test/unit/models/settlement/settlementModelCached.test.js +171 -0
  202. package/test/unit/models/transfer/facade.test.js +115 -0
  203. package/test/unit/models/transfer/ilpPacket.test.js +28 -11
  204. package/test/unit/models/transfer/transfer.test.js +13 -4
  205. package/test/unit/models/transfer/transferDuplicateCheck.test.js +4 -0
  206. package/test/unit/models/transfer/transferError.test.js +5 -1
  207. package/test/unit/models/transfer/transferErrorDuplicateCheck.test.js +4 -0
  208. package/test/unit/models/transfer/transferExtension.test.js +26 -9
  209. package/test/unit/models/transfer/transferFulfilment.test.js +14 -5
  210. package/test/unit/models/transfer/transferFulfilmentDuplicateCheck.test.js +4 -0
  211. package/test/unit/models/transfer/transferParticipant.test.js +14 -5
  212. package/test/unit/models/transfer/transferStateChange.test.js +3 -0
  213. package/test/unit/models/transfer/transferTimeout.test.js +6 -0
  214. package/test/unit/seeds/amountType.test.js +6 -22
  215. package/test/unit/seeds/balanceOfPayments.test.js +6 -22
  216. package/test/unit/seeds/bulkProcessingState.test.js +84 -0
  217. package/test/unit/{lib/sidecar/nullClient.test.js → seeds/bulkTransferState.test.js} +36 -39
  218. package/test/unit/seeds/currency.test.js +6 -22
  219. package/test/unit/seeds/endpointType.test.js +6 -22
  220. package/test/unit/seeds/ledgerAccountType.test.js +5 -22
  221. package/test/unit/seeds/ledgerEntryType.test.js +6 -22
  222. package/test/unit/seeds/participant.test.js +5 -22
  223. package/test/unit/seeds/participantLimitType.test.js +6 -22
  224. package/test/unit/seeds/partyIdentifierType.test.js +6 -22
  225. package/test/unit/seeds/partyType.test.js +6 -22
  226. package/test/unit/seeds/settlementState.test.js +5 -22
  227. package/test/unit/seeds/settlementWindow1State.test.js +5 -22
  228. package/test/unit/seeds/transactionInitiator.test.js +6 -22
  229. package/test/unit/seeds/transactionInitiatorType.test.js +6 -22
  230. package/test/unit/seeds/transactionScenario.test.js +6 -22
  231. package/test/unit/seeds/transferParticipantRoleType.test.js +6 -22
  232. package/test/unit/seeds/transferState.test.js +6 -22
  233. package/test/unit/shared/plugins.test.js +31 -1
  234. package/test/unit/shared/setup.test.js +25 -36
  235. package/test/util/helpers.js +37 -2
  236. package/test/util/randomTransfers.js +1 -1
  237. package/test/util/scripts/env.sh +6 -5
  238. package/test/util/scripts/populateTestData.sh +204 -181
  239. package/test/util/scripts/populateTestDataForLegacySimulator.sh +261 -0
  240. package/test/util/scripts/restartObjStore.sh +1 -1
  241. package/test-integration.Dockerfile +15 -15
  242. package/test.Dockerfile +12 -12
  243. package/.circleci/_set_up_deploy_envs.sh +0 -47
  244. package/.dockerignore +0 -17
  245. package/.ncurc.json +0 -3
  246. package/server.sh +0 -4
  247. package/sonar-project.properties +0 -17
  248. package/src/lib/sidecar/index.js +0 -47
  249. package/src/lib/sidecar/nullClient.js +0 -18
  250. package/test/.env +0 -8
  251. package/test/integration-config.json +0 -367
  252. package/test/integration-runner.env +0 -31
  253. package/test/integration-runner.sh +0 -264
  254. package/test/spec-runner.sh +0 -132
  255. package/test/unit/lib/sidecar/index.test.js +0 -148
  256. package/test/unit/models/position/participantLimit.test.js +0 -135
@@ -0,0 +1,55 @@
1
+ /*****
2
+ License
3
+ --------------
4
+ Copyright © 2017 Bill & Melinda Gates Foundation
5
+ 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
6
+ http://www.apache.org/licenses/LICENSE-2.0
7
+ 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.
8
+ Contributors
9
+ --------------
10
+ This is the official list of the Mojaloop project contributors for this file.
11
+ Names of the original copyright holders (individuals or organizations)
12
+ should be listed with a '*' in the first column. People who have
13
+ contributed from an organization can be listed under the organization
14
+ that actually holds the copyright for their contributions (see the
15
+ Gates Foundation organization for an example). Those individuals should have
16
+ their names indented and be marked with a '-'. Email address can be added
17
+ optionally within square brackets <email>.
18
+ * Gates Foundation
19
+ - Name Surname <name.surname@gatesfoundation.com>
20
+
21
+ * ModusBox
22
+ - Claudio Viola <claudio.viola@modusbox.com>
23
+ --------------
24
+ ******/
25
+ 'use strict'
26
+
27
+ const LedgerAccountTypesService = require('../../domain/ledgerAccountTypes')
28
+ const ErrorHandler = require('@mojaloop/central-services-error-handling')
29
+ const Logger = require('@mojaloop/central-services-logger')
30
+
31
+ const getAll = async function () {
32
+ return LedgerAccountTypesService.getAll()
33
+ }
34
+ async function create (request, h) {
35
+ try {
36
+ const ledgerAccountTypeExist = await LedgerAccountTypesService.getByName(request.payload.name)
37
+ if (ledgerAccountTypeExist) {
38
+ throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.CLIENT_ERROR, 'This Ledger Account Type already exists')
39
+ } else {
40
+ const body = request.payload
41
+ await LedgerAccountTypesService.create(body.name, body.description, body.isActive, body.isSettleable)
42
+ return h.response().code(201)
43
+ }
44
+ } catch (err) {
45
+ Logger.isErrorEnabled && Logger.error(err)
46
+ throw ErrorHandler.Factory.reformatFSPIOPError(err)
47
+ }
48
+ }
49
+
50
+ module.exports = {
51
+ create,
52
+ // getByName,
53
+ getAll
54
+ // update
55
+ }
@@ -0,0 +1,63 @@
1
+ /*****
2
+ License
3
+ --------------
4
+ Copyright © 2017 Bill & Melinda Gates Foundation
5
+ 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
6
+ http://www.apache.org/licenses/LICENSE-2.0
7
+ 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.
8
+ Contributors
9
+ --------------
10
+ This is the official list of the Mojaloop project contributors for this file.
11
+ Names of the original copyright holders (individuals or organizations)
12
+ should be listed with a '*' in the first column. People who have
13
+ contributed from an organization can be listed under the organization
14
+ that actually holds the copyright for their contributions (see the
15
+ Gates Foundation organization for an example). Those individuals should have
16
+ their names indented and be marked with a '-'. Email address can be added
17
+ optionally within square brackets <email>.
18
+ * Gates Foundation
19
+ - Name Surname <name.surname@gatesfoundation.com>
20
+
21
+ * ModusBox
22
+ - Claudio Viola <claudio.viola@modusbox.com>
23
+ --------------
24
+ ******/
25
+ 'use strict'
26
+
27
+ const Handler = require('./handler')
28
+ const Joi = require('@hapi/joi')
29
+ const tags = ['api', 'ledgerAccountTypes']
30
+
31
+ module.exports = [
32
+ {
33
+ method: 'GET',
34
+ path: '/ledgerAccountTypes',
35
+ handler: Handler.getAll,
36
+ options: {
37
+ tags,
38
+ description: 'Get all ledger Account types'
39
+
40
+ }
41
+ },
42
+ {
43
+ method: 'POST',
44
+ path: '/ledgerAccountTypes',
45
+ handler: Handler.create,
46
+ options: {
47
+ tags,
48
+ description: 'Create a new ledger account type',
49
+ payload: {
50
+ allow: ['application/json'],
51
+ failAction: 'error'
52
+ },
53
+ validate: {
54
+ payload: Joi.object({
55
+ name: Joi.string().min(2).max(30).pattern(/^\w+$/).required().description('Name of the ledger account type'),
56
+ description: Joi.string().required().description('The description of the ledger account type'),
57
+ isActive: Joi.boolean().required().description('Determines whether this ledger account type is active or not'),
58
+ isSettleable: Joi.boolean().required().description('Determines whether this ledger account type is settleable or not')
59
+ })
60
+ }
61
+ }
62
+ }
63
+ ]
@@ -27,6 +27,6 @@
27
27
 
28
28
  const Metrics = require('@mojaloop/central-services-metrics')
29
29
 
30
- exports.metrics = function (request, h) {
31
- return h.response(Metrics.getMetricsForPrometheus()).code(200)
30
+ exports.metrics = async (request, h) => {
31
+ return h.response(await Metrics.getMetricsForPrometheus()).code(200)
32
32
  }
@@ -35,7 +35,7 @@ module.exports = [
35
35
  path: '/metrics',
36
36
  handler: Handler.metrics,
37
37
  config: {
38
- tags: tags,
38
+ tags,
39
39
  description: 'Prometheus metrics endpoint',
40
40
  id: 'metrics'
41
41
  }
@@ -28,10 +28,10 @@ const ParticipantService = require('../../domain/participant')
28
28
  const UrlParser = require('../../lib/urlParser')
29
29
  const Config = require('../../lib/config')
30
30
  const Util = require('@mojaloop/central-services-shared').Util
31
- const Sidecar = require('../../lib/sidecar')
32
31
  const Logger = require('@mojaloop/central-services-logger')
33
32
  const ErrorHandler = require('@mojaloop/central-services-error-handling')
34
- const Cache = require('../../lib/cache')
33
+ const Enums = require('../../lib/enumCached')
34
+ const SettlementService = require('../../domain/settlement')
35
35
 
36
36
  const LocalEnum = {
37
37
  activated: 'activated',
@@ -70,17 +70,9 @@ const handleMissingRecord = (entity) => {
70
70
  }
71
71
 
72
72
  const create = async function (request, h) {
73
- Sidecar.logRequest(request)
74
73
  try {
75
- const ledgerAccountTypes = await Cache.getEnums('ledgerAccountType')
76
- const hubReconciliationAccountExists = await ParticipantService.hubAccountExists(request.payload.currency, ledgerAccountTypes.HUB_RECONCILIATION)
77
- if (!hubReconciliationAccountExists) {
78
- throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ADD_PARTY_INFO_ERROR, 'Hub reconciliation account for the specified currency does not exist')
79
- }
80
- const hubMlnsAccountExists = await ParticipantService.hubAccountExists(request.payload.currency, ledgerAccountTypes.HUB_MULTILATERAL_SETTLEMENT)
81
- if (!hubMlnsAccountExists) {
82
- throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ADD_PARTY_INFO_ERROR, 'Hub multilateral net settlement account for the specified currency does not exist')
83
- }
74
+ const ledgerAccountTypes = await Enums.getEnums('ledgerAccountType')
75
+ await ParticipantService.validateHubAccounts(request.payload.currency)
84
76
  let participant = await ParticipantService.getByName(request.payload.name)
85
77
  if (participant) {
86
78
  const currencyExists = participant.currencyList.find(currency => {
@@ -94,17 +86,32 @@ const create = async function (request, h) {
94
86
  participant = await ParticipantService.getById(participantId)
95
87
  }
96
88
  const ledgerAccountIds = Util.transpose(ledgerAccountTypes)
97
- const participantCurrencyId1 = await ParticipantService.createParticipantCurrency(participant.participantId, request.payload.currency, ledgerAccountTypes.POSITION, false)
98
- const participantCurrencyId2 = await ParticipantService.createParticipantCurrency(participant.participantId, request.payload.currency, ledgerAccountTypes.SETTLEMENT, false)
99
- participant.currencyList = [await ParticipantService.getParticipantCurrencyById(participantCurrencyId1), await ParticipantService.getParticipantCurrencyById(participantCurrencyId2)]
89
+ const allSettlementModels = await SettlementService.getAll()
90
+ let settlementModels = allSettlementModels.filter(model => model.currencyId === request.payload.currency)
91
+ if (settlementModels.length === 0) {
92
+ settlementModels = allSettlementModels.filter(model => model.currencyId === null) // Default settlement model
93
+ if (settlementModels.length === 0) {
94
+ throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.GENERIC_SETTLEMENT_ERROR, 'Unable to find a matching or default, Settlement Model')
95
+ }
96
+ }
97
+ for (const settlementModel of settlementModels) {
98
+ const [participantCurrencyId1, participantCurrencyId2] = await Promise.all([
99
+ ParticipantService.createParticipantCurrency(participant.participantId, request.payload.currency, settlementModel.ledgerAccountTypeId, false),
100
+ ParticipantService.createParticipantCurrency(participant.participantId, request.payload.currency, settlementModel.settlementAccountTypeId, false)])
101
+ if (Array.isArray(participant.currencyList)) {
102
+ participant.currencyList = participant.currencyList.concat([await ParticipantService.getParticipantCurrencyById(participantCurrencyId1), await ParticipantService.getParticipantCurrencyById(participantCurrencyId2)])
103
+ } else {
104
+ participant.currencyList = await Promise.all([ParticipantService.getParticipantCurrencyById(participantCurrencyId1), ParticipantService.getParticipantCurrencyById(participantCurrencyId2)])
105
+ }
106
+ }
100
107
  return h.response(entityItem(participant, ledgerAccountIds)).code(201)
101
108
  } catch (err) {
109
+ Logger.isErrorEnabled && Logger.error(err)
102
110
  throw ErrorHandler.Factory.reformatFSPIOPError(err)
103
111
  }
104
112
  }
105
113
 
106
114
  const createHubAccount = async function (request, h) {
107
- Sidecar.logRequest(request)
108
115
  try {
109
116
  // start - To Do move to domain
110
117
  const participant = await ParticipantService.getByName(request.params.name)
@@ -140,17 +147,18 @@ const createHubAccount = async function (request, h) {
140
147
  throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ADD_PARTY_INFO_ERROR, 'Participant was not found.')
141
148
  }
142
149
  // end here : move to domain
143
- const ledgerAccountTypes = await Cache.getEnums('ledgerAccountType')
150
+ const ledgerAccountTypes = await Enums.getEnums('ledgerAccountType')
144
151
  const ledgerAccountIds = Util.transpose(ledgerAccountTypes)
145
152
  return h.response(entityItem(participant, ledgerAccountIds)).code(201)
146
153
  } catch (err) {
154
+ Logger.isErrorEnabled && Logger.error(err)
147
155
  throw ErrorHandler.Factory.reformatFSPIOPError(err)
148
156
  }
149
157
  }
150
158
 
151
159
  const getAll = async function (request) {
152
160
  const results = await ParticipantService.getAll()
153
- const ledgerAccountTypes = await Cache.getEnums('ledgerAccountType')
161
+ const ledgerAccountTypes = await Enums.getEnums('ledgerAccountType')
154
162
  const ledgerAccountIds = Util.transpose(ledgerAccountTypes)
155
163
  return results.map(record => entityItem(record, ledgerAccountIds))
156
164
  }
@@ -158,40 +166,39 @@ const getAll = async function (request) {
158
166
  const getByName = async function (request) {
159
167
  const entity = await ParticipantService.getByName(request.params.name)
160
168
  handleMissingRecord(entity)
161
- const ledgerAccountTypes = await Cache.getEnums('ledgerAccountType')
169
+ const ledgerAccountTypes = await Enums.getEnums('ledgerAccountType')
162
170
  const ledgerAccountIds = Util.transpose(ledgerAccountTypes)
163
171
  return entityItem(entity, ledgerAccountIds)
164
172
  }
165
173
 
166
174
  const update = async function (request) {
167
- Sidecar.logRequest(request)
168
175
  try {
169
176
  const updatedEntity = await ParticipantService.update(request.params.name, request.payload)
170
177
  if (request.payload.isActive !== undefined) {
171
178
  const isActiveText = request.payload.isActive ? LocalEnum.activated : LocalEnum.disabled
172
179
  const changeLog = JSON.stringify(Object.assign({}, request.params, { isActive: request.payload.isActive }))
173
- Logger.info(`Participant has been ${isActiveText} :: ${changeLog}`)
180
+ Logger.isInfoEnabled && Logger.info(`Participant has been ${isActiveText} :: ${changeLog}`)
174
181
  }
175
- const ledgerAccountTypes = await Cache.getEnums('ledgerAccountType')
182
+ const ledgerAccountTypes = await Enums.getEnums('ledgerAccountType')
176
183
  const ledgerAccountIds = Util.transpose(ledgerAccountTypes)
177
184
  return entityItem(updatedEntity, ledgerAccountIds)
178
185
  } catch (err) {
186
+ Logger.isErrorEnabled && Logger.error(err)
179
187
  throw ErrorHandler.Factory.reformatFSPIOPError(err)
180
188
  }
181
189
  }
182
190
 
183
191
  const addEndpoint = async function (request, h) {
184
- Sidecar.logRequest(request)
185
192
  try {
186
193
  await ParticipantService.addEndpoint(request.params.name, request.payload)
187
194
  return h.response().code(201)
188
195
  } catch (err) {
196
+ Logger.isErrorEnabled && Logger.error(err)
189
197
  throw ErrorHandler.Factory.reformatFSPIOPError(err)
190
198
  }
191
199
  }
192
200
 
193
201
  const getEndpoint = async function (request) {
194
- Sidecar.logRequest(request)
195
202
  try {
196
203
  if (request.query.type) {
197
204
  const result = await ParticipantService.getEndpoint(request.params.name, request.query.type)
@@ -217,22 +224,22 @@ const getEndpoint = async function (request) {
217
224
  return endpoints
218
225
  }
219
226
  } catch (err) {
227
+ Logger.isErrorEnabled && Logger.error(err)
220
228
  throw ErrorHandler.Factory.reformatFSPIOPError(err)
221
229
  }
222
230
  }
223
231
 
224
232
  const addLimitAndInitialPosition = async function (request, h) {
225
- Sidecar.logRequest(request)
226
233
  try {
227
234
  await ParticipantService.addLimitAndInitialPosition(request.params.name, request.payload)
228
235
  return h.response().code(201)
229
236
  } catch (err) {
237
+ Logger.isErrorEnabled && Logger.error(err)
230
238
  throw ErrorHandler.Factory.reformatFSPIOPError(err)
231
239
  }
232
240
  }
233
241
 
234
242
  const getLimits = async function (request) {
235
- Sidecar.logRequest(request)
236
243
  try {
237
244
  const result = await ParticipantService.getLimits(request.params.name, request.query)
238
245
  const limits = []
@@ -250,12 +257,12 @@ const getLimits = async function (request) {
250
257
  }
251
258
  return limits
252
259
  } catch (err) {
260
+ Logger.isErrorEnabled && Logger.error(err)
253
261
  throw ErrorHandler.Factory.reformatFSPIOPError(err)
254
262
  }
255
263
  }
256
264
 
257
265
  const getLimitsForAllParticipants = async function (request) {
258
- Sidecar.logRequest(request)
259
266
  try {
260
267
  const result = await ParticipantService.getLimitsForAllParticipants(request.query)
261
268
  const limits = []
@@ -274,12 +281,12 @@ const getLimitsForAllParticipants = async function (request) {
274
281
  }
275
282
  return limits
276
283
  } catch (err) {
284
+ Logger.isErrorEnabled && Logger.error(err)
277
285
  throw ErrorHandler.Factory.reformatFSPIOPError(err)
278
286
  }
279
287
  }
280
288
 
281
289
  const adjustLimits = async function (request, h) {
282
- Sidecar.logRequest(request)
283
290
  try {
284
291
  const result = await ParticipantService.adjustLimits(request.params.name, request.payload)
285
292
  const { participantLimit } = result
@@ -294,53 +301,54 @@ const adjustLimits = async function (request, h) {
294
301
  }
295
302
  return h.response(updatedLimit).code(200)
296
303
  } catch (err) {
304
+ Logger.isErrorEnabled && Logger.error(err)
297
305
  throw ErrorHandler.Factory.reformatFSPIOPError(err)
298
306
  }
299
307
  }
300
308
 
301
309
  const getPositions = async function (request) {
302
- Sidecar.logRequest(request)
303
310
  try {
304
311
  return await ParticipantService.getPositions(request.params.name, request.query)
305
312
  } catch (err) {
313
+ Logger.isErrorEnabled && Logger.error(err)
306
314
  throw ErrorHandler.Factory.reformatFSPIOPError(err)
307
315
  }
308
316
  }
309
317
 
310
318
  const getAccounts = async function (request) {
311
- Sidecar.logRequest(request)
312
319
  try {
313
320
  return await ParticipantService.getAccounts(request.params.name, request.query)
314
321
  } catch (err) {
322
+ Logger.isErrorEnabled && Logger.error(err)
315
323
  throw ErrorHandler.Factory.reformatFSPIOPError(err)
316
324
  }
317
325
  }
318
326
 
319
327
  const updateAccount = async function (request, h) {
320
- Sidecar.logRequest(request)
321
328
  try {
322
329
  const enums = {
323
- ledgerAccountType: await Cache.getEnums('ledgerAccountType')
330
+ ledgerAccountType: await Enums.getEnums('ledgerAccountType')
324
331
  }
325
332
  await ParticipantService.updateAccount(request.payload, request.params, enums)
326
333
  if (request.payload.isActive !== undefined) {
327
334
  const isActiveText = request.payload.isActive ? LocalEnum.activated : LocalEnum.disabled
328
335
  const changeLog = JSON.stringify(Object.assign({}, request.params, { isActive: request.payload.isActive }))
329
- Logger.info(`Participant account has been ${isActiveText} :: ${changeLog}`)
336
+ Logger.isInfoEnabled && Logger.info(`Participant account has been ${isActiveText} :: ${changeLog}`)
330
337
  }
331
338
  return h.response().code(200)
332
339
  } catch (err) {
340
+ Logger.isErrorEnabled && Logger.error(err)
333
341
  throw ErrorHandler.Factory.reformatFSPIOPError(err)
334
342
  }
335
343
  }
336
344
 
337
345
  const recordFunds = async function (request, h) {
338
- Sidecar.logRequest(request)
339
346
  try {
340
- const enums = await Cache.getEnums('all')
347
+ const enums = await Enums.getEnums('all')
341
348
  await ParticipantService.recordFundsInOut(request.payload, request.params, enums)
342
349
  return h.response().code(202)
343
350
  } catch (err) {
351
+ Logger.isErrorEnabled && Logger.error(err)
344
352
  throw ErrorHandler.Factory.reformatFSPIOPError(err)
345
353
  }
346
354
  }
@@ -25,7 +25,7 @@
25
25
  'use strict'
26
26
 
27
27
  const Handler = require('./handler')
28
- const Joi = require('@hapi/joi')
28
+ const Joi = require('joi')
29
29
  const currencyList = require('../../../seeds/currency.js').currencyList
30
30
 
31
31
  const tags = ['api', 'participants']
@@ -100,7 +100,7 @@ module.exports = [
100
100
  handler: Handler.addEndpoint,
101
101
  options: {
102
102
  id: 'participants_endpoints_add',
103
- tags: tags,
103
+ tags,
104
104
  description: 'Add/Update participant endpoints',
105
105
  payload: {
106
106
  allow: ['application/json'],
@@ -123,7 +123,7 @@ module.exports = [
123
123
  handler: Handler.getEndpoint,
124
124
  options: {
125
125
  id: 'participants_endpoints_get',
126
- tags: tags,
126
+ tags,
127
127
  description: 'View participant endpoints',
128
128
  validate: {
129
129
  params: Joi.object({
@@ -138,7 +138,7 @@ module.exports = [
138
138
  handler: Handler.addLimitAndInitialPosition,
139
139
  options: {
140
140
  id: 'participants_limits_pos_add',
141
- tags: tags,
141
+ tags,
142
142
  description: 'Add initial participant limits and position',
143
143
  payload: {
144
144
  allow: ['application/json'],
@@ -165,7 +165,7 @@ module.exports = [
165
165
  handler: Handler.getLimits,
166
166
  options: {
167
167
  id: 'participants_limits_get',
168
- tags: tags,
168
+ tags,
169
169
  description: 'View participant limits',
170
170
  validate: {
171
171
  params: Joi.object({
@@ -184,7 +184,7 @@ module.exports = [
184
184
  handler: Handler.getLimitsForAllParticipants,
185
185
  options: {
186
186
  id: 'participants_limits_get_all',
187
- tags: tags,
187
+ tags,
188
188
  description: 'View limits for all participants',
189
189
  validate: {
190
190
  query: Joi.object({
@@ -200,7 +200,7 @@ module.exports = [
200
200
  handler: Handler.adjustLimits,
201
201
  options: {
202
202
  id: 'participants_limits_adjust',
203
- tags: tags,
203
+ tags,
204
204
  description: 'Adjust participant limits',
205
205
  payload: {
206
206
  allow: ['application/json'],
@@ -227,7 +227,7 @@ module.exports = [
227
227
  handler: Handler.createHubAccount,
228
228
  options: {
229
229
  id: 'hub_accounts_create',
230
- tags: tags,
230
+ tags,
231
231
  description: 'Create hub accounts',
232
232
  payload: {
233
233
  allow: ['application/json'],
@@ -250,7 +250,7 @@ module.exports = [
250
250
  handler: Handler.getPositions,
251
251
  options: {
252
252
  id: 'participants_positions_get',
253
- tags: tags,
253
+ tags,
254
254
  description: 'View participant positions',
255
255
  validate: {
256
256
  params: Joi.object({
@@ -268,7 +268,7 @@ module.exports = [
268
268
  handler: Handler.getAccounts,
269
269
  options: {
270
270
  id: 'participants_accounts_get',
271
- tags: tags,
271
+ tags,
272
272
  description: 'View participant accounts and balances',
273
273
  validate: {
274
274
  params: Joi.object({
@@ -283,7 +283,7 @@ module.exports = [
283
283
  handler: Handler.updateAccount,
284
284
  options: {
285
285
  id: 'participants_accounts_update',
286
- tags: tags,
286
+ tags,
287
287
  description: 'Update participant accounts',
288
288
  validate: {
289
289
  payload: Joi.object({
@@ -302,7 +302,7 @@ module.exports = [
302
302
  handler: Handler.recordFunds,
303
303
  options: {
304
304
  id: 'post_participants_accounts_funds',
305
- tags: tags,
305
+ tags,
306
306
  description: 'Record Funds In or Out of participant account',
307
307
  validate: {
308
308
  payload: Joi.object({
@@ -334,7 +334,7 @@ module.exports = [
334
334
  handler: Handler.recordFunds,
335
335
  options: {
336
336
  id: 'put_participants_accounts_funds',
337
- tags: tags,
337
+ tags,
338
338
  description: 'Record Funds In or Out of participant account',
339
339
  validate: {
340
340
  payload: Joi.object({
@@ -29,7 +29,7 @@
29
29
  ******/
30
30
  'use strict'
31
31
  const Handler = require('./handler')
32
- const Cache = require('../../lib/cache')
32
+ const Enums = require('../../lib/enumCached')
33
33
 
34
34
  const tags = ['api', 'root']
35
35
 
@@ -46,7 +46,7 @@ module.exports = [
46
46
  method: 'GET',
47
47
  path: '/enums',
48
48
  handler: async function (request, h) {
49
- const enums = await Cache.getEnums('all')
49
+ const enums = await Enums.getEnums('all')
50
50
  return h.response(enums).code(200)
51
51
  },
52
52
  options: {
@@ -26,9 +26,8 @@
26
26
  'use strict'
27
27
 
28
28
  const SettlementService = require('../../domain/settlement')
29
- const Sidecar = require('../../lib/sidecar')
30
29
  const ErrorHandler = require('@mojaloop/central-services-error-handling')
31
- const Cache = require('../../lib/cache')
30
+ const Enums = require('../../lib/enumCached')
32
31
  const Util = require('@mojaloop/central-services-shared').Util
33
32
  const Enum = require('@mojaloop/central-services-shared').Enum.Settlements
34
33
  const Logger = require('@mojaloop/central-services-logger')
@@ -58,7 +57,7 @@ const handleMissingRecord = (entity) => {
58
57
  const getByName = async function (request) {
59
58
  const entity = await SettlementService.getByName(request.params.name)
60
59
  handleMissingRecord(entity)
61
- const ledgerAccountTypes = await Cache.getEnums('ledgerAccountType')
60
+ const ledgerAccountTypes = await Enums.getEnums('ledgerAccountType')
62
61
  const ledgerAccountIds = Util.transpose(ledgerAccountTypes)
63
62
  const settlementGranularityIds = Util.transpose(Enum.SettlementGranularity)
64
63
  const settlementInterchangeIds = Util.transpose(Enum.SettlementInterchange)
@@ -68,7 +67,7 @@ const getByName = async function (request) {
68
67
  }
69
68
  const getAll = async function () {
70
69
  const results = await SettlementService.getAll()
71
- const ledgerAccountTypes = await Cache.getEnums('ledgerAccountType')
70
+ const ledgerAccountTypes = await Enums.getEnums('ledgerAccountType')
72
71
  const ledgerAccountIds = Util.transpose(ledgerAccountTypes)
73
72
  const settlementGranularityIds = Util.transpose(Enum.SettlementGranularity)
74
73
  const settlementInterchangeIds = Util.transpose(Enum.SettlementInterchange)
@@ -77,46 +76,30 @@ const getAll = async function () {
77
76
  }
78
77
 
79
78
  const update = async function (request) {
80
- Sidecar.logRequest(request)
81
79
  try {
82
80
  const updatedEntity = await SettlementService.update(request.params.name, request.payload)
83
81
  if (request.payload.isActive !== undefined) {
84
82
  const isActiveText = request.payload.isActive ? Enum.isActiveText.activated : Enum.isActiveText.disabled
85
83
  const changeLog = JSON.stringify(Object.assign({}, request.params, { isActive: request.payload.isActive }))
86
- Logger.info(`Settlement Model has been ${isActiveText} :: ${changeLog}`)
84
+ Logger.isInfoEnabled && Logger.info(`Settlement Model has been ${isActiveText} :: ${changeLog}`)
87
85
  }
88
- const ledgerAccountTypes = await Cache.getEnums('ledgerAccountType')
86
+ const ledgerAccountTypes = await Enums.getEnums('ledgerAccountType')
89
87
  const ledgerAccountIds = Util.transpose(ledgerAccountTypes)
90
88
  const settlementGranularityIds = Util.transpose(Enum.SettlementGranularity)
91
89
  const settlementInterchangeIds = Util.transpose(Enum.SettlementInterchange)
92
90
  const settlementDelayIds = Util.transpose(Enum.SettlementDelay)
93
91
  return entityItem(updatedEntity, ledgerAccountIds, settlementGranularityIds, settlementInterchangeIds, settlementDelayIds)
94
92
  } catch (err) {
93
+ Logger.isErrorEnabled && Logger.error(err)
95
94
  throw ErrorHandler.Factory.reformatFSPIOPError(err)
96
95
  }
97
96
  }
98
97
  const create = async function (request, h) {
99
- Sidecar.logRequest(request)
100
98
  try {
101
- const settlementGranularity = Enum.SettlementGranularity[request.payload.settlementGranularity]
102
- const settlementInterchange = Enum.SettlementInterchange[request.payload.settlementInterchange]
103
- const settlementDelay = Enum.SettlementDelay[request.payload.settlementDelay]
104
- const { isValid, reasons } = Util.Settlement.validateSettlementModel(settlementDelay, settlementGranularity, settlementInterchange)
105
- if (!isValid) {
106
- throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.CLIENT_ERROR, reasons.join('. '))
107
- }
108
- const ledgerAccountType = await SettlementService.getLedgerAccountTypeName(request.payload.ledgerAccountType)
109
- if (!ledgerAccountType) {
110
- throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ADD_PARTY_INFO_ERROR, 'Ledger account type was not found')
111
- }
112
- const settlementModelExist = await SettlementService.getByName(request.payload.name)
113
- if (settlementModelExist) {
114
- throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.CLIENT_ERROR, 'This Settlement Model already exists')
115
- } else {
116
- await SettlementService.createSettlementModel(request.payload.name, true, settlementGranularity, settlementInterchange, settlementDelay, request.payload.currency, request.payload.requireLiquidityCheck, ledgerAccountType.ledgerAccountTypeId, request.payload.autoPositionReset)
117
- return h.response().code(201)
118
- }
99
+ await SettlementService.createSettlementModel(request.payload)
100
+ return h.response().code(201)
119
101
  } catch (err) {
102
+ Logger.isErrorEnabled && Logger.error(err)
120
103
  throw ErrorHandler.Factory.reformatFSPIOPError(err)
121
104
  }
122
105
  }
@@ -26,12 +26,11 @@
26
26
  'use strict'
27
27
 
28
28
  const Handler = require('./handler')
29
- const Joi = require('@hapi/joi')
29
+ const Joi = require('joi')
30
30
  const currencyList = require('../../../seeds/currency.js').currencyList
31
31
  const settlementGranularityList = require('../../../seeds/settlementGranularity.js').settlementGranularityList
32
32
  const settlementInterchangeList = require('../../../seeds/settlementInterchange.js').settlementInterchangeList
33
33
  const settlementDelayList = require('../../../seeds/settlementDelay.js').settlementDelayList
34
- const ledgerAccountList = require('../../../seeds/ledgerAccountType.js').ledgerAccountList
35
34
  const tags = ['api', 'settlement']
36
35
 
37
36
  module.exports = [
@@ -74,8 +73,9 @@ module.exports = [
74
73
  settlementDelay: Joi.string().required().valid(...settlementDelayList).description('Delay type for the settlement model IMMEDIATE or DEFERRED'),
75
74
  currency: Joi.string().valid(...currencyList).description('Currency code'),
76
75
  requireLiquidityCheck: Joi.boolean().required().description('Liquidity Check boolean'),
77
- ledgerAccountType: Joi.string().required().valid(...ledgerAccountList).description('Account type for the settlement model POSITION, SETTLEMENT or INTERCHANGE_FEE'),
78
- autoPositionReset: Joi.boolean().required().description('Automatic position reset setting, which determines whether to execute the settlement transfer or not')
76
+ ledgerAccountType: Joi.string().required().description('Account type for the settlement model'),
77
+ autoPositionReset: Joi.boolean().required().description('Automatic position reset setting, which determines whether to execute the settlement transfer or not'),
78
+ settlementAccountType: Joi.string().valid('SETTLEMENT', 'INTERCHANGE_FEE_SETTLEMENT').required().description('Settlement account linked to the ledger account')
79
79
  })
80
80
  }
81
81
  }