@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
@@ -31,38 +31,84 @@
31
31
  const Db = require('../../lib/db')
32
32
  const Time = require('@mojaloop/central-services-shared').Util.Time
33
33
  const ErrorHandler = require('@mojaloop/central-services-error-handling')
34
+ const Metrics = require('@mojaloop/central-services-metrics')
35
+ const Cache = require('../../lib/cache')
36
+ const ParticipantModelCached = require('../../models/participant/participantCached')
34
37
  const ParticipantCurrencyModelCached = require('../../models/participant/participantCurrencyCached')
38
+ const ParticipantLimitCached = require('../../models/participant/participantLimitCached')
39
+ const Config = require('../../lib/config')
40
+ const SettlementModelModel = require('../settlement/settlementModel')
41
+ const { Enum } = require('@mojaloop/central-services-shared')
35
42
 
36
43
  const getByNameAndCurrency = async (name, currencyId, ledgerAccountTypeId, isCurrencyActive) => {
44
+ const histTimerParticipantGetByNameAndCurrencyEnd = Metrics.getHistogram(
45
+ 'model_participant',
46
+ 'facade_getByNameAndCurrency - Metrics for participant model',
47
+ ['success', 'queryName']
48
+ ).startTimer()
49
+
37
50
  try {
38
- return await Db.participant.query(async (builder) => {
39
- let b = builder
40
- .where({ 'participant.name': name })
41
- .andWhere({ 'pc.currencyId': currencyId })
42
- .andWhere({ 'pc.ledgerAccountTypeId': ledgerAccountTypeId })
43
- .innerJoin('participantCurrency AS pc', 'pc.participantId', 'participant.participantId')
44
- .select(
45
- 'participant.*',
46
- 'pc.participantCurrencyId',
47
- 'pc.currencyId',
48
- 'pc.isActive AS currencyIsActive'
49
- )
50
- .first()
51
+ let participant
52
+ if (Cache.isCacheEnabled()) {
53
+ /* Cached version - fetch data from Models (which we trust are cached) */
54
+ /* find paricipant id by name */
55
+ participant = await ParticipantModelCached.getByName(name)
56
+ if (participant) {
57
+ /* use the paricipant id and incoming params to prepare the filter */
58
+ const searchFilter = {
59
+ participantId: participant.participantId,
60
+ currencyId,
61
+ ledgerAccountTypeId
62
+ }
63
+ if (isCurrencyActive !== undefined) {
64
+ searchFilter.isActive = isCurrencyActive
65
+ }
66
+
67
+ /* find the participantCurrency by prepared filter */
68
+ const participantCurrency = await ParticipantCurrencyModelCached.findOneByParams(searchFilter)
51
69
 
52
- if (isCurrencyActive !== undefined) {
53
- b = b.andWhere({ 'pc.isActive': isCurrencyActive })
70
+ if (participantCurrency) {
71
+ /* mix requested data from participantCurrency */
72
+ participant.participantCurrencyId = participantCurrency.participantCurrencyId
73
+ participant.currencyId = participantCurrency.currencyId
74
+ participant.currencyIsActive = participantCurrency.isActive
75
+ }
54
76
  }
77
+ } else {
78
+ /* Non-cached version - direct call to DB */
79
+ participant = await Db.from('participant').query(async (builder) => {
80
+ let b = builder
81
+ .where({ 'participant.name': name })
82
+ .andWhere({ 'pc.currencyId': currencyId })
83
+ .andWhere({ 'pc.ledgerAccountTypeId': ledgerAccountTypeId })
84
+ .innerJoin('participantCurrency AS pc', 'pc.participantId', 'participant.participantId')
85
+ .select(
86
+ 'participant.*',
87
+ 'pc.participantCurrencyId',
88
+ 'pc.currencyId',
89
+ 'pc.isActive AS currencyIsActive'
90
+ )
91
+ .first()
55
92
 
56
- return b
57
- })
93
+ if (isCurrencyActive !== undefined) {
94
+ b = b.andWhere({ 'pc.isActive': isCurrencyActive })
95
+ }
96
+ return b
97
+ })
98
+ }
99
+
100
+ histTimerParticipantGetByNameAndCurrencyEnd({ success: true, queryName: 'facade_getByNameAndCurrency' })
101
+
102
+ return participant
58
103
  } catch (err) {
104
+ histTimerParticipantGetByNameAndCurrencyEnd({ success: false, queryName: 'facade_getByNameAndCurrency' })
59
105
  throw ErrorHandler.Factory.reformatFSPIOPError(err)
60
106
  }
61
107
  }
62
108
 
63
109
  const getParticipantLimitByParticipantIdAndCurrencyId = async (participantId, currencyId, ledgerAccountTypeId) => {
64
110
  try {
65
- return await Db.participant.query(async (builder) => {
111
+ return await Db.from('participant').query(async (builder) => {
66
112
  return builder
67
113
  .where({
68
114
  'participant.participantId': participantId,
@@ -96,7 +142,7 @@ const getParticipantLimitByParticipantIdAndCurrencyId = async (participantId, cu
96
142
 
97
143
  const getLimitsForAllParticipants = async (currencyId, type, ledgerAccountTypeId) => {
98
144
  try {
99
- return Db.participant.query(async (builder) => {
145
+ return Db.from('participant').query(async (builder) => {
100
146
  return builder
101
147
  .where({
102
148
  'pc.ledgerAccountTypeId': ledgerAccountTypeId,
@@ -147,7 +193,7 @@ const getLimitsForAllParticipants = async (currencyId, type, ledgerAccountTypeId
147
193
 
148
194
  const getEndpoint = async (participantId, endpointType) => {
149
195
  try {
150
- return Db.participantEndpoint.query(builder => {
196
+ return Db.from('participantEndpoint').query(builder => {
151
197
  return builder.innerJoin('endpointType AS et', 'participantEndpoint.endpointTypeId', 'et.endpointTypeId')
152
198
  .where({
153
199
  'participantEndpoint.participantId': participantId,
@@ -175,7 +221,7 @@ const getEndpoint = async (participantId, endpointType) => {
175
221
 
176
222
  const getAllEndpoints = async (participantId) => {
177
223
  try {
178
- return Db.participantEndpoint.query(builder => {
224
+ return Db.from('participantEndpoint').query(builder => {
179
225
  return builder.innerJoin('endpointType AS et', 'participantEndpoint.endpointTypeId', 'et.endpointTypeId')
180
226
  .where({
181
227
  'participantEndpoint.participantId': participantId,
@@ -219,7 +265,7 @@ const addEndpoint = async (participantId, endpoint) => {
219
265
 
220
266
  const existingEndpoint = await knex('participantEndpoint').transacting(trx).forUpdate().select('*')
221
267
  .where({
222
- participantId: participantId,
268
+ participantId,
223
269
  endpointTypeId: endpointType.endpointTypeId,
224
270
  isActive: 1
225
271
  })
@@ -227,7 +273,7 @@ const addEndpoint = async (participantId, endpoint) => {
227
273
  await knex('participantEndpoint').transacting(trx).update({ isActive: 0 }).where('participantEndpointId', existingEndpoint[0].participantEndpointId)
228
274
  }
229
275
  const newEndpoint = {
230
- participantId: participantId,
276
+ participantId,
231
277
  endpointTypeId: endpointType.endpointTypeId,
232
278
  value: endpoint.value,
233
279
  isActive: 1,
@@ -248,27 +294,72 @@ const addEndpoint = async (participantId, endpoint) => {
248
294
  }
249
295
 
250
296
  const getParticipantLimitByParticipantCurrencyLimit = async (participantId, currencyId, ledgerAccountTypeId, participantLimitTypeId) => {
297
+ const histGetParticipantLimitEnd = Metrics.getHistogram(
298
+ 'model_participant',
299
+ 'facade_getParticipantLimitByParticipantCurrencyLimit - Metrics for participant model',
300
+ ['success', 'queryName']
301
+ ).startTimer()
302
+
251
303
  try {
252
- return await Db.participant.query(async (builder) => {
253
- return builder
254
- .where({
255
- 'participant.participantId': participantId,
256
- 'pc.currencyId': currencyId,
257
- 'pc.ledgerAccountTypeId': ledgerAccountTypeId,
258
- 'pl.participantLimitTypeId': participantLimitTypeId,
259
- 'participant.isActive': 1,
260
- 'pc.IsActive': 1,
261
- 'pl.isActive': 1
262
- })
263
- .innerJoin('participantCurrency AS pc', 'pc.participantId', 'participant.participantId')
264
- .innerJoin('participantLimit AS pl', 'pl.participantCurrencyId', 'pc.participantCurrencyId')
265
- .select(
266
- 'participant.participantID AS participantId',
267
- 'pc.currencyId AS currencyId',
268
- 'pl.participantLimitTypeId as participantLimitTypeId',
269
- 'pl.value AS value'
270
- ).first()
271
- })
304
+ let participantLimit
305
+ if (Cache.isCacheEnabled()) {
306
+ /* Cached version - fetch data from Models (which we trust are cached) */
307
+ const participant = await ParticipantModelCached.getById(participantId)
308
+
309
+ /* Checkpoint #1: participant found and is active */
310
+ if ((participant) && (participant.isActive)) {
311
+ /* use the paricipant id and incoming params to prepare the filter */
312
+ const searchFilter = {
313
+ participantId: participant.participantId,
314
+ currencyId,
315
+ ledgerAccountTypeId,
316
+ isActive: 1
317
+ }
318
+
319
+ /* find the participantCurrency by prepared filter */
320
+ const participantCurrency = await ParticipantCurrencyModelCached.findOneByParams(searchFilter)
321
+
322
+ /* Checkpoint #2: participantCurrency found and is active */
323
+ if ((participantCurrency) && (participantCurrency.isActive)) {
324
+ const participantLimitRow = await ParticipantLimitCached.getByParticipantCurrencyId(participantCurrency.participantCurrencyId)
325
+
326
+ /* Checkpoint #3: participantLimit found */
327
+ if ((participantLimitRow) && (participantLimitRow.isActive)) {
328
+ /* combine all needed info */
329
+ participantLimit = {
330
+ participantId,
331
+ currencyId: participantCurrency.currencyId,
332
+ participantLimitTypeId: participantLimitRow.participantLimitTypeId,
333
+ value: participantLimitRow.value
334
+ }
335
+ }
336
+ }
337
+ }
338
+ } else {
339
+ /* Non-cached version - direct call to DB */
340
+ participantLimit = await Db.from('participant').query(async (builder) => {
341
+ return builder
342
+ .where({
343
+ 'participant.participantId': participantId,
344
+ 'pc.currencyId': currencyId,
345
+ 'pc.ledgerAccountTypeId': ledgerAccountTypeId,
346
+ 'pl.participantLimitTypeId': participantLimitTypeId,
347
+ 'participant.isActive': 1,
348
+ 'pc.IsActive': 1,
349
+ 'pl.isActive': 1
350
+ })
351
+ .innerJoin('participantCurrency AS pc', 'pc.participantId', 'participant.participantId')
352
+ .innerJoin('participantLimit AS pl', 'pl.participantCurrencyId', 'pc.participantCurrencyId')
353
+ .select(
354
+ 'participant.participantId AS participantId',
355
+ 'pc.currencyId AS currencyId',
356
+ 'pl.participantLimitTypeId as participantLimitTypeId',
357
+ 'pl.value AS value'
358
+ ).first()
359
+ })
360
+ }
361
+ histGetParticipantLimitEnd({ success: true, queryName: 'facade_getParticipantLimitByParticipantCurrencyLimit' })
362
+ return participantLimit
272
363
  } catch (err) {
273
364
  throw ErrorHandler.Factory.reformatFSPIOPError(err)
274
365
  }
@@ -276,7 +367,7 @@ const getParticipantLimitByParticipantCurrencyLimit = async (participantId, curr
276
367
 
277
368
  const getParticipantPositionByParticipantIdAndCurrencyId = async (participantId, currencyId, ledgerAccountTypeId) => {
278
369
  try {
279
- return await Db.participant.query(async (builder) => {
370
+ return await Db.from('participant').query(async (builder) => {
280
371
  return builder
281
372
  .where({
282
373
  'participant.participantId': participantId,
@@ -323,9 +414,7 @@ const addLimitAndInitialPosition = async (participantCurrencyId, settlementAccou
323
414
  const knex = Db.getKnex()
324
415
  return knex.transaction(async trx => {
325
416
  try {
326
- let result
327
417
  const limitType = await knex('participantLimitType').where({ name: limitPositionObj.limit.type, isActive: 1 }).select('participantLimitTypeId').first()
328
- // let limitType = await trx.first('participantLimitTypeId').from('participantLimitType').where({ 'name': limitPositionObj.limit.type, 'isActive': 1 })
329
418
  const participantLimit = {
330
419
  participantCurrencyId,
331
420
  participantLimitTypeId: limitType.participantLimitTypeId,
@@ -333,33 +422,60 @@ const addLimitAndInitialPosition = async (participantCurrencyId, settlementAccou
333
422
  isActive: 1,
334
423
  createdBy: 'unknown'
335
424
  }
336
- result = await knex('participantLimit').transacting(trx).insert(participantLimit)
425
+ const result = await knex('participantLimit').transacting(trx).insert(participantLimit)
337
426
  participantLimit.participantLimitId = result[0]
338
- const participantPosition = {
339
- participantCurrencyId,
340
- value: limitPositionObj.initialPosition,
341
- reservedValue: 0
342
- }
343
- result = await knex('participantPosition').transacting(trx).insert(participantPosition)
344
- participantPosition.participantPositionId = result[0]
345
- const settlementPosition = {
346
- participantCurrencyId: settlementAccountId,
347
- value: 0,
348
- reservedValue: 0
349
- }
350
- result = await knex('participantPosition').transacting(trx).insert(settlementPosition)
351
- settlementPosition.participantPositionId = result[0]
352
- if (setCurrencyActive) { // if the flag is true then set the isActive flag for corresponding participantCurrency record to true
353
- await knex('participantCurrency').transacting(trx).update({ isActive: 1 }).where('participantCurrencyId', participantCurrencyId)
354
- await knex('participantCurrency').transacting(trx).update({ isActive: 1 }).where('participantCurrencyId', settlementAccountId)
355
- await ParticipantCurrencyModelCached.invalidateParticipantCurrencyCache()
427
+
428
+ const allSettlementModels = await SettlementModelModel.getAll()
429
+ const settlementModels = allSettlementModels.filter(model => model.currencyId === limitPositionObj.currency)
430
+ if (Array.isArray(settlementModels) && settlementModels.length > 0) {
431
+ for (const settlementModel of settlementModels) {
432
+ const positionAccount = await getByNameAndCurrency(limitPositionObj.name, limitPositionObj.currency, settlementModel.ledgerAccountTypeId)
433
+ const settlementAccount = await getByNameAndCurrency(limitPositionObj.name, limitPositionObj.currency, settlementModel.settlementAccountTypeId)
434
+
435
+ const participantPosition = {
436
+ participantCurrencyId: positionAccount.participantCurrencyId,
437
+ value: (settlementModel.ledgerAccountTypeId === Enum.Accounts.LedgerAccountType.POSITION ? limitPositionObj.initialPosition : 0),
438
+ reservedValue: 0
439
+ }
440
+ await knex('participantPosition').transacting(trx).insert(participantPosition)
441
+
442
+ const settlementPosition = {
443
+ participantCurrencyId: settlementAccount.participantCurrencyId,
444
+ value: 0,
445
+ reservedValue: 0
446
+ }
447
+ await knex('participantPosition').transacting(trx).insert(settlementPosition)
448
+ if (setCurrencyActive) { // if the flag is true then set the isActive flag for corresponding participantCurrency record to true
449
+ await knex('participantCurrency').transacting(trx).update({ isActive: 1 }).where('participantCurrencyId', positionAccount.participantCurrencyId)
450
+ await knex('participantCurrency').transacting(trx).update({ isActive: 1 }).where('participantCurrencyId', settlementAccount.participantCurrencyId)
451
+ await ParticipantCurrencyModelCached.invalidateParticipantCurrencyCache()
452
+ await ParticipantLimitCached.invalidateParticipantLimitCache()
453
+ }
454
+ }
455
+ } else {
456
+ const participantPosition = {
457
+ participantCurrencyId,
458
+ value: limitPositionObj.initialPosition,
459
+ reservedValue: 0
460
+ }
461
+ const participantPositionResult = await knex('participantPosition').transacting(trx).insert(participantPosition)
462
+ participantPosition.participantPositionId = participantPositionResult[0]
463
+ const settlementPosition = {
464
+ participantCurrencyId: settlementAccountId,
465
+ value: 0,
466
+ reservedValue: 0
467
+ }
468
+ await knex('participantPosition').transacting(trx).insert(settlementPosition)
469
+ if (setCurrencyActive) { // if the flag is true then set the isActive flag for corresponding participantCurrency record to true
470
+ await knex('participantCurrency').transacting(trx).update({ isActive: 1 }).where('participantCurrencyId', participantCurrencyId)
471
+ await knex('participantCurrency').transacting(trx).update({ isActive: 1 }).where('participantCurrencyId', settlementAccountId)
472
+ await ParticipantCurrencyModelCached.invalidateParticipantCurrencyCache()
473
+ await ParticipantLimitCached.invalidateParticipantLimitCache()
474
+ }
356
475
  }
476
+
357
477
  await trx.commit
358
- return {
359
- participantLimit,
360
- participantPosition,
361
- settlementPosition
362
- }
478
+ return true
363
479
  } catch (err) {
364
480
  await trx.rollback
365
481
  throw err
@@ -400,7 +516,7 @@ const adjustLimits = async (participantCurrencyId, limit, trx) => {
400
516
  // const limitType = await trx.first('participantLimitTypeId').from('participantLimitType').where({ 'name': limit.type, 'isActive': 1 })
401
517
  const existingLimit = await knex('participantLimit').transacting(trx).forUpdate().select('*')
402
518
  .where({
403
- participantCurrencyId: participantCurrencyId,
519
+ participantCurrencyId,
404
520
  participantLimitTypeId: limitType.participantLimitTypeId,
405
521
  isActive: 1
406
522
  })
@@ -410,7 +526,7 @@ const adjustLimits = async (participantCurrencyId, limit, trx) => {
410
526
  throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.INTERNAL_SERVER_ERROR, 'Participant Limit does not exist')
411
527
  }
412
528
  const newLimit = {
413
- participantCurrencyId: participantCurrencyId,
529
+ participantCurrencyId,
414
530
  participantLimitTypeId: limitType.participantLimitTypeId,
415
531
  value: limit.value,
416
532
  thresholdAlarmPercentage: limit.alarmPercentage,
@@ -459,7 +575,7 @@ const adjustLimits = async (participantCurrencyId, limit, trx) => {
459
575
 
460
576
  const getParticipantLimitsByCurrencyId = async (participantCurrencyId, type) => {
461
577
  try {
462
- return Db.participantLimit.query(builder => {
578
+ return Db.from('participantLimit').query(builder => {
463
579
  return builder.innerJoin('participantLimitType AS lt', 'participantLimit.participantLimitTypeId', 'lt.participantLimitTypeId')
464
580
  .where({
465
581
  'participantLimit.participantCurrencyId': participantCurrencyId,
@@ -495,7 +611,7 @@ const getParticipantLimitsByCurrencyId = async (participantCurrencyId, type) =>
495
611
 
496
612
  const getParticipantLimitsByParticipantId = async (participantId, type, ledgerAccountTypeId) => {
497
613
  try {
498
- return Db.participantLimit.query(builder => {
614
+ return Db.from('participantLimit').query(builder => {
499
615
  return builder.innerJoin('participantLimitType AS lt', 'participantLimit.participantLimitTypeId', 'lt.participantLimitTypeId')
500
616
  .innerJoin('participantCurrency AS pc', 'participantLimit.participantCurrencyId', 'pc.participantCurrencyId')
501
617
  .where({
@@ -561,7 +677,7 @@ const addHubAccountAndInitPosition = async (participantId, currencyId, ledgerAcc
561
677
 
562
678
  const getAllAccountsByNameAndCurrency = async (name, currencyId = null, isAccountActive = 1) => {
563
679
  try {
564
- return Db.participantCurrency.query(builder => {
680
+ return Db.from('participantCurrency').query(builder => {
565
681
  return builder
566
682
  .innerJoin('ledgerAccountType AS lap', 'lap.ledgerAccountTypeId', 'participantCurrency.ledgerAccountTypeId')
567
683
  .innerJoin('participant AS p', 'p.participantId', 'participantCurrency.participantId')
@@ -586,6 +702,39 @@ const getAllAccountsByNameAndCurrency = async (name, currencyId = null, isAccoun
586
702
  }
587
703
  }
588
704
 
705
+ const getAllNonHubParticipantsWithCurrencies = async (trx) => {
706
+ try {
707
+ const HUB_ACCOUNT_NAME = Config.HUB_NAME
708
+ const knex = Db.getKnex()
709
+ const trxFunction = async (trx, doCommit = true) => {
710
+ try {
711
+ const res = await knex.distinct('participant.participantId', 'pc.participantId', 'pc.currencyId')
712
+ .from('participant')
713
+ .innerJoin('participantCurrency as pc', 'participant.participantId', 'pc.participantId')
714
+ .whereNot('participant.name', HUB_ACCOUNT_NAME)
715
+ .transacting(trx)
716
+
717
+ if (doCommit) {
718
+ await trx.commit
719
+ }
720
+ return res
721
+ } catch (err) {
722
+ if (doCommit) {
723
+ await trx.rollback
724
+ }
725
+ throw ErrorHandler.Factory.reformatFSPIOPError(err)
726
+ }
727
+ }
728
+ if (trx) {
729
+ return trxFunction(trx, false)
730
+ } else {
731
+ return knex.transaction(trxFunction)
732
+ }
733
+ } catch (err) {
734
+ throw ErrorHandler.Factory.reformatFSPIOPError(err)
735
+ }
736
+ }
737
+
589
738
  module.exports = {
590
739
  addHubAccountAndInitPosition,
591
740
  getByNameAndCurrency,
@@ -600,5 +749,6 @@ module.exports = {
600
749
  getParticipantLimitsByCurrencyId,
601
750
  getParticipantLimitsByParticipantId,
602
751
  getAllAccountsByNameAndCurrency,
603
- getLimitsForAllParticipants
752
+ getLimitsForAllParticipants,
753
+ getAllNonHubParticipantsWithCurrencies
604
754
  }
@@ -32,7 +32,8 @@ const ErrorHandler = require('@mojaloop/central-services-error-handling')
32
32
 
33
33
  exports.getAll = async () => {
34
34
  try {
35
- return Db.participant.find({}, { order: 'name asc' })
35
+ const result = await Db.from('participant').find({}, { order: 'name asc' })
36
+ return result
36
37
  } catch (err) {
37
38
  throw ErrorHandler.Factory.reformatFSPIOPError(err)
38
39
  }
@@ -40,7 +41,7 @@ exports.getAll = async () => {
40
41
 
41
42
  exports.create = async (participant) => {
42
43
  try {
43
- const result = await Db.participant.insert({
44
+ const result = await Db.from('participant').insert({
44
45
  name: participant.name,
45
46
  createdBy: 'unknown'
46
47
  })
@@ -52,7 +53,7 @@ exports.create = async (participant) => {
52
53
 
53
54
  exports.update = async (participant, isActive) => {
54
55
  try {
55
- const result = await Db.participant.update({ participantId: participant.participantId }, { isActive })
56
+ const result = await Db.from('participant').update({ participantId: participant.participantId }, { isActive })
56
57
  return result
57
58
  } catch (err) {
58
59
  throw ErrorHandler.Factory.reformatFSPIOPError(err)
@@ -61,7 +62,7 @@ exports.update = async (participant, isActive) => {
61
62
 
62
63
  exports.destroyByName = async (name) => {
63
64
  try {
64
- const result = await Db.participant.destroy({ name: name })
65
+ const result = await Db.from('participant').destroy({ name })
65
66
  return result
66
67
  } catch (err) {
67
68
  throw ErrorHandler.Factory.reformatFSPIOPError(err)
@@ -70,7 +71,7 @@ exports.destroyByName = async (name) => {
70
71
 
71
72
  exports.destroyParticipantEndpointByParticipantId = async (participantId) => {
72
73
  try {
73
- const result = Db.participantEndpoint.destroy({ participantId: participantId })
74
+ const result = Db.from('participantEndpoint').destroy({ participantId })
74
75
  return result
75
76
  } catch (err) {
76
77
  throw ErrorHandler.Factory.reformatFSPIOPError(err)
@@ -27,6 +27,7 @@
27
27
  const ErrorHandler = require('@mojaloop/central-services-error-handling')
28
28
  const Cache = require('../../lib/cache')
29
29
  const ParticipantModel = require('../../models/participant/participant')
30
+ const Metrics = require('@mojaloop/central-services-metrics')
30
31
 
31
32
  let cacheClient
32
33
  let participantsAllCacheKey
@@ -62,6 +63,11 @@ const buildUnifiedParticipantsData = (allParticipants) => {
62
63
  }
63
64
 
64
65
  const getParticipantsCached = async () => {
66
+ const histTimer = Metrics.getHistogram(
67
+ 'model_participant',
68
+ 'model_getParticipantsCached - Metrics for participant model',
69
+ ['success', 'queryName', 'hit']
70
+ ).startTimer()
65
71
  // Do we have valid participants list in the cache ?
66
72
  let cachedParticipants = cacheClient.get(participantsAllCacheKey)
67
73
  if (!cachedParticipants) {
@@ -71,9 +77,11 @@ const getParticipantsCached = async () => {
71
77
 
72
78
  // store in cache
73
79
  cacheClient.set(participantsAllCacheKey, cachedParticipants)
80
+ histTimer({ success: true, queryName: 'model_getParticipantsCached', hit: false })
74
81
  } else {
75
82
  // unwrap participants list from catbox structure
76
83
  cachedParticipants = cachedParticipants.item
84
+ histTimer({ success: true, queryName: 'model_getParticipantsCached', hit: true })
77
85
  }
78
86
  return cachedParticipants
79
87
  }
@@ -29,7 +29,7 @@ const ErrorHandler = require('@mojaloop/central-services-error-handling')
29
29
 
30
30
  exports.create = async (participantId, currencyId, ledgerAccountTypeId, isActive = true) => {
31
31
  try {
32
- return await Db.participantCurrency.insert({
32
+ return await Db.from('participantCurrency').insert({
33
33
  participantId,
34
34
  currencyId,
35
35
  ledgerAccountTypeId,
@@ -43,7 +43,7 @@ exports.create = async (participantId, currencyId, ledgerAccountTypeId, isActive
43
43
 
44
44
  exports.getAll = async () => {
45
45
  try {
46
- return Db.participantCurrency.find({}, { order: 'participantCurrencyId asc' })
46
+ return Db.from('participantCurrency').find({}, { order: 'participantCurrencyId asc' })
47
47
  } catch (err) {
48
48
  throw ErrorHandler.Factory.reformatFSPIOPError(err)
49
49
  }
@@ -51,7 +51,7 @@ exports.getAll = async () => {
51
51
 
52
52
  exports.getById = async (id) => {
53
53
  try {
54
- return await Db.participantCurrency.findOne({ participantCurrencyId: id })
54
+ return await Db.from('participantCurrency').findOne({ participantCurrencyId: id })
55
55
  } catch (err) {
56
56
  throw ErrorHandler.Factory.reformatFSPIOPError(err)
57
57
  }
@@ -59,7 +59,7 @@ exports.getById = async (id) => {
59
59
 
60
60
  exports.update = async (participantCurrencyId, isActive) => {
61
61
  try {
62
- return await Db.participantCurrency.update({ participantCurrencyId }, { isActive })
62
+ return await Db.from('participantCurrency').update({ participantCurrencyId }, { isActive })
63
63
  } catch (err) {
64
64
  throw ErrorHandler.Factory.reformatFSPIOPError(err)
65
65
  }
@@ -71,7 +71,7 @@ exports.getByParticipantId = async (id, ledgerAccountTypeId = null) => {
71
71
  if (ledgerAccountTypeId) {
72
72
  params.ledgerAccountTypeId = ledgerAccountTypeId
73
73
  }
74
- return await Db.participantCurrency.find(params)
74
+ return await Db.from('participantCurrency').find(params)
75
75
  } catch (err) {
76
76
  throw ErrorHandler.Factory.reformatFSPIOPError(err)
77
77
  }
@@ -79,7 +79,7 @@ exports.getByParticipantId = async (id, ledgerAccountTypeId = null) => {
79
79
 
80
80
  exports.destroyByParticipantId = async (id) => {
81
81
  try {
82
- return await Db.participantCurrency.destroy({ participantId: id })
82
+ return await Db.from('participantCurrency').destroy({ participantId: id })
83
83
  } catch (err) {
84
84
  throw ErrorHandler.Factory.reformatFSPIOPError(err)
85
85
  }
@@ -87,7 +87,7 @@ exports.destroyByParticipantId = async (id) => {
87
87
 
88
88
  exports.getByName = async (accountParams) => {
89
89
  try {
90
- const participantCurrency = await Db.participantCurrency.findOne(accountParams)
90
+ const participantCurrency = await Db.from('participantCurrency').findOne(accountParams)
91
91
  return participantCurrency
92
92
  } catch (err) {
93
93
  throw ErrorHandler.Factory.reformatFSPIOPError(err)
@@ -28,6 +28,7 @@ const ErrorHandler = require('@mojaloop/central-services-error-handling')
28
28
  const Cache = require('../../lib/cache')
29
29
  const Config = require('../../../src/lib/config')
30
30
  const ParticipantCurrencyModel = require('../../models/participant/participantCurrency')
31
+ const Metrics = require('@mojaloop/central-services-metrics')
31
32
 
32
33
  let cacheClient
33
34
  let participantCurrencyAllCacheKey
@@ -59,6 +60,11 @@ const buildUnifiedParticipantsCurrencyData = (allCurrencyParticipants) => {
59
60
  }
60
61
 
61
62
  const getParticipantCurrencyCached = async () => {
63
+ const histTimer = Metrics.getHistogram(
64
+ 'model_participant',
65
+ 'model_getParticipantCurrencyCached - Metrics for participant model',
66
+ ['success', 'queryName', 'hit']
67
+ ).startTimer()
62
68
  // Do we have valid participantsCurrency list in the cache ?
63
69
  let cachedCurrencyParticipants = cacheClient.get(participantCurrencyAllCacheKey)
64
70
  if (!cachedCurrencyParticipants) {
@@ -68,9 +74,11 @@ const getParticipantCurrencyCached = async () => {
68
74
 
69
75
  // store in cache
70
76
  cacheClient.set(participantCurrencyAllCacheKey, cachedCurrencyParticipants)
77
+ histTimer({ success: true, queryName: 'model_getParticipantCurrencyCached', hit: false })
71
78
  } else {
72
79
  // unwrap participants list from catbox structure
73
80
  cachedCurrencyParticipants = cachedCurrencyParticipants.item
81
+ histTimer({ success: true, queryName: 'model_getParticipantCurrencyCached', hit: true })
74
82
  }
75
83
  return cachedCurrencyParticipants
76
84
  }
@@ -90,7 +98,9 @@ exports.initialize = async () => {
90
98
  }
91
99
 
92
100
  exports.invalidateParticipantCurrencyCache = async () => {
93
- cacheClient.drop(participantCurrencyAllCacheKey)
101
+ if (cacheClient) {
102
+ cacheClient.drop(participantCurrencyAllCacheKey)
103
+ }
94
104
  }
95
105
 
96
106
  exports.getByParticipantId = async (id, ledgerAccountTypeId = null) => {