account-lookup-service 15.6.0-iso.2 → 15.6.0-iso.20

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 (43) hide show
  1. package/.circleci/config.yml +1 -1
  2. package/.ncurc.yaml +1 -2
  3. package/audit-ci.jsonc +3 -1
  4. package/jest.config.js +2 -0
  5. package/package.json +14 -16
  6. package/src/constants.js +2 -1
  7. package/src/domain/participants/participants.js +173 -130
  8. package/src/domain/parties/getPartiesByTypeAndID.js +15 -14
  9. package/src/domain/parties/parties.js +13 -12
  10. package/src/domain/parties/utils.js +13 -6
  11. package/src/domain/timeout/dto.js +4 -10
  12. package/src/handlers/index.js +4 -4
  13. package/src/handlers/monitoring/index.js +1 -1
  14. package/src/interface/api-swagger-iso20022-parties.yaml +7 -6
  15. package/src/interface/api-swagger.yaml +7 -6
  16. package/src/interface/fspiop-rest-v2.0-ISO20022_parties.yaml +2043 -1583
  17. package/src/lib/config.js +1 -1
  18. package/src/lib/index.js +1 -2
  19. package/src/models/participantEndpoint/facade.js +21 -19
  20. package/src/plugins.js +20 -9
  21. package/src/server.js +3 -19
  22. package/test/fixtures/index.js +30 -6
  23. package/test/fixtures/iso.js +1 -1
  24. package/test/unit/api/health.test.js +3 -0
  25. package/test/unit/api/participants/participants.test.js +5 -7
  26. package/test/unit/api/participants/{Type}/{ID}/{SubId}.test.js +0 -3
  27. package/test/unit/api/participants/{Type}/{ID}.test.js +0 -3
  28. package/test/unit/api/participants.test.js +36 -3
  29. package/test/unit/domain/participants/participants.test.js +76 -48
  30. package/test/unit/domain/parties/parties.test.js +3 -3
  31. package/test/unit/domain/parties/utils.test.js +60 -0
  32. package/test/unit/domain/timeout/dto.test.js +1 -2
  33. package/test/unit/lib/TransformFacades.test.js +2 -1
  34. package/test/unit/lib/config.test.js +7 -0
  35. package/test/unit/models/participantEndpoint/facade.test.js +25 -8
  36. package/test/unit/plugins.test.js +4 -2
  37. package/test/util/apiClients/BasicApiClient.js +2 -2
  38. package/src/handlers/monitoring/plugins/metrics.js +0 -48
  39. package/src/lib/requestLogger.js +0 -54
  40. package/src/metrics/handler.js +0 -33
  41. package/src/metrics/plugin.js +0 -52
  42. package/src/metrics/routes.js +0 -43
  43. package/test/unit/lib/requestLogger.test.js +0 -115
@@ -1,7 +1,7 @@
1
1
  version: 2.1
2
2
  setup: true
3
3
  orbs:
4
- build: mojaloop/build@1.0.25
4
+ build: mojaloop/build@1.0.27
5
5
  workflows:
6
6
  setup:
7
7
  jobs:
package/.ncurc.yaml CHANGED
@@ -1,6 +1,5 @@
1
1
  ## Add a TODO comment indicating the reason for each rejected dependency upgrade added to this list, and what should be done to resolve it (i.e. handle it through a story, etc).
2
2
  reject: [
3
3
  # TODO: v6+ (ref: https://github.com/sindresorhus/get-port/releases/tag/v6.0.0) is an ESM library and thus not compatible with CommonJS. Future story needed to resolve.
4
- "get-port",
5
- "@mojaloop/central-services-shared" ## need to remove before merging proxyCache functionality to main
4
+ "get-port"
6
5
  ]
package/audit-ci.jsonc CHANGED
@@ -27,6 +27,8 @@
27
27
  "GHSA-7fh5-64p2-3v2j",
28
28
  "GHSA-rm97-x556-q36h", // https://github.com/advisories/GHSA-rm97-x556-q36h
29
29
  "GHSA-rv95-896h-c2vc", // https://github.com/advisories/GHSA-rv95-896h-c2vc
30
- "GHSA-952p-6rrq-rcjv" // https://github.com/advisories/GHSA-952p-6rrq-rcjv
30
+ "GHSA-952p-6rrq-rcjv", // https://github.com/advisories/GHSA-952p-6rrq-rcjv
31
+ "GHSA-3xgq-45jj-v275", // https://github.com/advisories/GHSA-3xgq-45jj-v275
32
+ "GHSA-rhx6-c78j-4q9w" // https://github.com/advisories/GHSA-rhx6-c78j-4q9w
31
33
  ]
32
34
  }
package/jest.config.js CHANGED
@@ -1,5 +1,7 @@
1
1
  module.exports = {
2
2
  verbose: true,
3
+ clearMocks: true,
4
+
3
5
  collectCoverageFrom: [
4
6
  '**/src/**/**/*.js'
5
7
  ],
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "account-lookup-service",
3
3
  "description": "Account Lookup Service is used to validate Party and Participant lookups.",
4
- "version": "15.6.0-iso.2",
4
+ "version": "15.6.0-iso.20",
5
5
  "license": "Apache-2.0",
6
6
  "author": "ModusBox",
7
7
  "contributors": [
@@ -54,7 +54,7 @@
54
54
  "test:coverage-check": "npm test -- --coverage",
55
55
  "test:junit": "npm test -- --reporters=default --reporters=jest-junit",
56
56
  "test:xunit": "npm run test:junit",
57
- "test:functional": "sh ./scripts/test-functional.sh",
57
+ "test:functional": "bash ./scripts/test-functional.sh",
58
58
  "test:int": "npm run migrate && npm run onboarding && jest --config=./jest-int.config.js --runInBand",
59
59
  "test:integration": "npm run dc:up && npm run wait-4-docker && npm run test:int | tee ./test/results/test-int.log",
60
60
  "test:integration-runner": "TEST_MODE=rm ./test/integration-runner.sh",
@@ -87,27 +87,26 @@
87
87
  "@hapi/boom": "10.0.1",
88
88
  "@hapi/catbox-memory": "6.0.2",
89
89
  "@hapi/good": "9.0.1",
90
- "@hapi/hapi": "21.3.10",
90
+ "@hapi/hapi": "21.3.12",
91
91
  "@hapi/inert": "7.1.0",
92
- "@hapi/joi": "17.1.1",
93
92
  "@hapi/vision": "7.0.3",
94
- "@mojaloop/central-services-error-handling": "13.0.1",
93
+ "@mojaloop/central-services-error-handling": "13.0.2",
95
94
  "@mojaloop/central-services-health": "15.0.0",
96
95
  "@mojaloop/central-services-logger": "11.5.1",
97
- "@mojaloop/central-services-metrics": "12.0.8",
98
- "@mojaloop/central-services-shared": "18.10.0-snapshot.4",
96
+ "@mojaloop/central-services-metrics": "12.4.1",
97
+ "@mojaloop/central-services-shared": "18.13.0",
99
98
  "@mojaloop/central-services-stream": "11.3.1",
100
99
  "@mojaloop/database-lib": "11.0.6",
101
100
  "@mojaloop/event-sdk": "14.1.1",
102
101
  "@mojaloop/inter-scheme-proxy-cache-lib": "2.3.0",
103
- "@mojaloop/ml-schema-transformer-lib": "1.1.1",
104
- "@mojaloop/sdk-standard-components": "19.0.0",
102
+ "@mojaloop/ml-schema-transformer-lib": "2.4.1",
103
+ "@mojaloop/sdk-standard-components": "19.6.2",
105
104
  "@now-ims/hapi-now-auth": "2.1.0",
106
105
  "ajv": "8.17.1",
107
106
  "ajv-keywords": "5.1.0",
108
107
  "blipp": "4.0.2",
109
108
  "commander": "12.1.0",
110
- "cron": "3.1.7",
109
+ "cron": "3.3.0",
111
110
  "fast-safe-stringify": "^2.1.1",
112
111
  "hapi-auth-bearer-token": "8.0.0",
113
112
  "joi": "17.13.3",
@@ -147,22 +146,21 @@
147
146
  "jsonpointer": "5.0.0"
148
147
  },
149
148
  "devDependencies": {
150
- "@types/jest": "29.5.13",
149
+ "@types/jest": "29.5.14",
151
150
  "audit-ci": "^7.1.0",
152
- "axios": "1.7.7",
151
+ "axios": "1.7.9",
153
152
  "axios-retry": "^4.5.0",
154
153
  "docdash": "2.0.2",
155
- "dotenv": "^16.4.5",
154
+ "dotenv": "^16.4.7",
156
155
  "get-port": "5.1.1",
157
156
  "ioredis-mock": "^8.9.0",
158
157
  "jest": "29.7.0",
159
158
  "jest-junit": "16.0.0",
160
- "jsdoc": "4.0.3",
159
+ "jsdoc": "4.0.4",
161
160
  "nodemon": "3.1.7",
162
- "npm-check-updates": "17.1.4",
161
+ "npm-check-updates": "17.1.11",
163
162
  "nyc": "17.1.0",
164
163
  "pre-commit": "1.2.2",
165
- "proxyquire": "2.1.3",
166
164
  "replace": "^1.2.2",
167
165
  "sinon": "19.0.2",
168
166
  "standard": "17.1.2",
package/src/constants.js CHANGED
@@ -1,5 +1,6 @@
1
1
  const ERROR_MESSAGES = Object.freeze({
2
- partySourceFspNotFound: 'Requester FSP not found',
2
+ sourceFspNotFound: 'Requester FSP not found',
3
+ partySourceFspNotFound: 'Requester FSP not found', // todo: use sourceFspNotFound
3
4
  partyDestinationFspNotFound: 'Destination FSP not found',
4
5
  partyProxyNotFound: 'Proxy not found',
5
6
  proxyConnectionError: 'Proxy connection error',
@@ -28,7 +28,6 @@
28
28
 
29
29
  const Enums = require('@mojaloop/central-services-shared').Enum
30
30
  const { decodePayload } = require('@mojaloop/central-services-shared').Util.StreamingProtocol
31
- const Logger = require('@mojaloop/central-services-logger')
32
31
  const ErrorHandler = require('@mojaloop/central-services-error-handling')
33
32
  const EventSdk = require('@mojaloop/event-sdk')
34
33
  const Metrics = require('@mojaloop/central-services-metrics')
@@ -36,6 +35,10 @@ const Metrics = require('@mojaloop/central-services-metrics')
36
35
  const oracle = require('../../models/oracle/facade')
37
36
  const participant = require('../../models/participantEndpoint/facade')
38
37
  const Config = require('../../lib/config')
38
+ const { logger } = require('../../lib')
39
+ const { ERROR_MESSAGES } = require('../../constants')
40
+
41
+ const { FSPIOPErrorCodes } = ErrorHandler.Enums
39
42
 
40
43
  /**
41
44
  * @function getParticipantsByTypeAndID
@@ -55,57 +58,85 @@ const getParticipantsByTypeAndID = async (headers, params, method, query, span,
55
58
  'Get participants by ID',
56
59
  ['success']
57
60
  ).startTimer()
61
+ const log = logger.child('getParticipantsByTypeAndID')
58
62
  const type = params.Type
59
- const partySubIdOrType = params.SubId || undefined
60
- const requesterName = headers[Enums.Http.Headers.FSPIOP.SOURCE]
61
- const callbackEndpointType = partySubIdOrType ? Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT : Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT
62
- const errorCallbackEndpointType = params.SubId ? Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT_ERROR : Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR
63
+ const partySubIdOrType = params.SubId
64
+ const source = headers[Enums.Http.Headers.FSPIOP.SOURCE]
65
+ const callbackEndpointType = partySubIdOrType
66
+ ? Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT
67
+ : Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT
68
+ const errorCallbackEndpointType = params.SubId
69
+ ? Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT_ERROR
70
+ : Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR
71
+
63
72
  let fspiopError
73
+
64
74
  try {
65
- Logger.isInfoEnabled && Logger.info('getParticipantsByTypeAndID::begin')
66
- const requesterParticipantModel = await participant.validateParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], childSpan)
67
- if (requesterParticipantModel) {
68
- const response = await oracle.oracleRequest(headers, method, params, query, undefined, cache)
69
- if (response && response.data && Array.isArray(response.data.partyList) && response.data.partyList.length > 0) {
70
- let options = {
71
- partyIdType: type,
72
- partyIdentifier: params.ID
73
- }
74
- options = partySubIdOrType ? { ...options, partySubIdOrType } : options
75
- const payload = {
76
- fspId: response.data.partyList[0].fspId
77
- }
78
- const clonedHeaders = { ...headers }
79
- if (!clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION] || clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION] === '') {
80
- clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION] = clonedHeaders[Enums.Http.Headers.FSPIOP.SOURCE]
81
- }
82
- clonedHeaders[Enums.Http.Headers.FSPIOP.SOURCE] = Config.HUB_NAME
83
- await participant.sendRequest(clonedHeaders, requesterName, callbackEndpointType, Enums.Http.RestMethods.PUT, payload, options, childSpan)
84
- } else {
85
- await participant.sendErrorToParticipant(requesterName, errorCallbackEndpointType,
86
- ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.PARTY_NOT_FOUND).toApiErrorObject(Config.ERROR_HANDLING), headers, params, childSpan)
75
+ log.info('processing started...', { source, params })
76
+ const requesterParticipantModel = await participant.validateParticipant(source)
77
+
78
+ if (!requesterParticipantModel) {
79
+ const errMessage = ERROR_MESSAGES.sourceFspNotFound
80
+ logger.warn(errMessage, { requesterName: source })
81
+ throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, errMessage)
82
+ }
83
+
84
+ const response = await oracle.oracleRequest(headers, method, params, query, undefined, cache)
85
+ if (response?.data && Array.isArray(response.data.partyList) && response.data.partyList.length > 0) {
86
+ const options = {
87
+ partyIdType: type,
88
+ partyIdentifier: params.ID,
89
+ ...(partySubIdOrType && { partySubIdOrType })
90
+ }
91
+ const payload = {
92
+ fspId: response.data.partyList[0].fspId
87
93
  }
88
- Logger.isInfoEnabled && Logger.info('getParticipantsByTypeAndID::end')
94
+ const clonedHeaders = { ...headers }
95
+ if (!clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION] || clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION] === '') {
96
+ clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION] = clonedHeaders[Enums.Http.Headers.FSPIOP.SOURCE]
97
+ }
98
+ clonedHeaders[Enums.Http.Headers.FSPIOP.SOURCE] = Config.HUB_NAME
99
+ await participant.sendRequest(
100
+ clonedHeaders,
101
+ source,
102
+ callbackEndpointType,
103
+ Enums.Http.RestMethods.PUT,
104
+ payload,
105
+ options,
106
+ childSpan
107
+ )
89
108
  } else {
90
- Logger.isErrorEnabled && Logger.error('Requester FSP not found')
91
- throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, 'Requester FSP not found')
109
+ await participant.sendErrorToParticipant(
110
+ source,
111
+ errorCallbackEndpointType,
112
+ ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.PARTY_NOT_FOUND).toApiErrorObject(Config.ERROR_HANDLING),
113
+ headers,
114
+ params,
115
+ childSpan
116
+ )
92
117
  }
118
+ log.info('processing finished', { source, params })
119
+
93
120
  if (childSpan && !childSpan.isFinished) {
94
121
  await childSpan.finish()
95
122
  }
96
123
  } catch (err) {
97
- Logger.isErrorEnabled && Logger.error(err)
124
+ log.warn('error in getParticipantsByTypeAndID', err)
98
125
  fspiopError = ErrorHandler.Factory.reformatFSPIOPError(err, ErrorHandler.Enums.FSPIOPErrorCodes.ADD_PARTY_INFO_ERROR)
99
126
  try {
100
- const errorCallbackEndpointType = params.SubId ? Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT_ERROR : Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR
101
127
  await participant.sendErrorToParticipant(
102
- headers[Enums.Http.Headers.FSPIOP.SOURCE], errorCallbackEndpointType,
103
- fspiopError.toApiErrorObject(Config.ERROR_HANDLING), headers, params, childSpan)
128
+ headers[Enums.Http.Headers.FSPIOP.SOURCE],
129
+ errorCallbackEndpointType,
130
+ fspiopError.toApiErrorObject(Config.ERROR_HANDLING),
131
+ headers,
132
+ params,
133
+ childSpan
134
+ )
104
135
  } catch (exc) {
105
136
  fspiopError = ErrorHandler.Factory.reformatFSPIOPError(exc)
106
137
  // We can't do anything else here- we _must_ handle all errors _within_ this function because
107
138
  // we've already sent a sync response- we cannot throw.
108
- Logger.isErrorEnabled && Logger.error(exc)
139
+ log.error('error in final participant.sendErrorToParticipant', exc)
109
140
  }
110
141
  } finally {
111
142
  if (childSpan && !childSpan.isFinished && fspiopError) {
@@ -138,7 +169,7 @@ const putParticipantsByTypeAndID = async (headers, params, method, payload, cach
138
169
  ['success']
139
170
  ).startTimer()
140
171
  try {
141
- Logger.isInfoEnabled && Logger.info('putParticipantsByTypeAndID::begin')
172
+ logger.info('putParticipantsByTypeAndID::begin')
142
173
  const type = params.Type
143
174
  const partySubIdOrType = params.SubId || undefined
144
175
  const callbackEndpointType = partySubIdOrType ? Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT : Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT
@@ -177,17 +208,17 @@ const putParticipantsByTypeAndID = async (headers, params, method, payload, cach
177
208
  ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ADD_PARTY_INFO_ERROR).toApiErrorObject(Config.ERROR_HANDLING), headers, params)
178
209
  }
179
210
  } else {
180
- Logger.isErrorEnabled && Logger.error('Requester FSP not found')
181
- throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, 'Requester FSP not found')
211
+ logger.warn(ERROR_MESSAGES.sourceFspNotFound)
212
+ throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, ERROR_MESSAGES.sourceFspNotFound)
182
213
  }
183
214
  } else {
184
215
  await participant.sendErrorToParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], errorCallbackEndpointType,
185
216
  ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ADD_PARTY_INFO_ERROR).toApiErrorObject(Config.ERROR_HANDLING), headers, params)
186
217
  }
187
- Logger.isInfoEnabled && Logger.info('putParticipantsByTypeAndID::end')
218
+ logger.info('putParticipantsByTypeAndID::end')
188
219
  histTimerEnd({ success: true })
189
220
  } catch (err) {
190
- Logger.isErrorEnabled && Logger.error(err)
221
+ logger.error('error in putParticipantsByTypeAndID:', err)
191
222
  try {
192
223
  const errorCallbackEndpointType = params.SubId ? Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT_ERROR : Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR
193
224
  await participant.sendErrorToParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], errorCallbackEndpointType,
@@ -195,7 +226,7 @@ const putParticipantsByTypeAndID = async (headers, params, method, payload, cach
195
226
  } catch (exc) {
196
227
  // We can't do anything else here- we _must_ handle all errors _within_ this function because
197
228
  // we've already sent a sync response- we cannot throw.
198
- Logger.isErrorEnabled && Logger.error(exc)
229
+ logger.error('error in participant.sendErrorToParticipant:', exc)
199
230
  }
200
231
  histTimerEnd({ success: false })
201
232
  }
@@ -222,7 +253,9 @@ const putParticipantsErrorByTypeAndID = async (headers, params, payload, dataUri
222
253
  ).startTimer()
223
254
  try {
224
255
  const partySubIdOrType = params.SubId || undefined
225
- const callbackEndpointType = partySubIdOrType ? Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT_ERROR : Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR
256
+ const callbackEndpointType = partySubIdOrType
257
+ ? Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT_ERROR
258
+ : Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR
226
259
  const destinationParticipant = await participant.validateParticipant(headers[Enums.Http.Headers.FSPIOP.DESTINATION])
227
260
  if (destinationParticipant) {
228
261
  const decodedPayload = decodePayload(dataUri, { asParsed: false })
@@ -231,7 +264,8 @@ const putParticipantsErrorByTypeAndID = async (headers, params, payload, dataUri
231
264
  callbackEndpointType,
232
265
  decodedPayload.body.toString(),
233
266
  headers,
234
- params)
267
+ params
268
+ )
235
269
  } else {
236
270
  await participant.sendErrorToParticipant(
237
271
  headers[Enums.Http.Headers.FSPIOP.SOURCE],
@@ -239,19 +273,27 @@ const putParticipantsErrorByTypeAndID = async (headers, params, payload, dataUri
239
273
  ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.DESTINATION_FSP_ERROR).toApiErrorObject(),
240
274
  headers,
241
275
  params,
242
- payload)
276
+ payload
277
+ )
243
278
  }
244
279
  histTimerEnd({ success: true })
245
280
  } catch (err) {
246
- Logger.isErrorEnabled && Logger.error(err)
281
+ logger.error('error in putParticipantsErrorByTypeAndID:', err)
247
282
  try {
248
- const callbackEndpointType = params.SubId ? Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT_ERROR : Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR
249
- await participant.sendErrorToParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], callbackEndpointType,
250
- ErrorHandler.Factory.reformatFSPIOPError(err).toApiErrorObject(), headers, params)
283
+ const callbackEndpointType = params.SubId
284
+ ? Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT_ERROR
285
+ : Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR
286
+ await participant.sendErrorToParticipant(
287
+ headers[Enums.Http.Headers.FSPIOP.SOURCE],
288
+ callbackEndpointType,
289
+ ErrorHandler.Factory.reformatFSPIOPError(err).toApiErrorObject(),
290
+ headers,
291
+ params
292
+ )
251
293
  } catch (exc) {
252
294
  // We can't do anything else here- we _must_ handle all errors _within_ this function because
253
295
  // we've already sent a sync response- we cannot throw.
254
- Logger.isErrorEnabled && Logger.error(exc)
296
+ logger.error('error in participant.sendErrorToParticipant:', exc)
255
297
  }
256
298
  histTimerEnd({ success: false })
257
299
  }
@@ -277,7 +319,7 @@ const postParticipants = async (headers, method, params, payload, span, cache) =
277
319
  const childSpan = span ? span.getChild('postParticipants') : undefined
278
320
  let fspiopError
279
321
  try {
280
- Logger.isInfoEnabled && Logger.info('postParticipants::begin')
322
+ logger.info('postParticipants::begin')
281
323
  const type = params.Type
282
324
  const partySubIdOrType = params.SubId
283
325
  const callbackEndpointType = partySubIdOrType
@@ -325,8 +367,9 @@ const postParticipants = async (headers, method, params, payload, span, cache) =
325
367
  fspiopError.toApiErrorObject(Config.ERROR_HANDLING), headers, params, childSpan)
326
368
  }
327
369
  } else {
328
- fspiopError = ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, 'Requester FSP not found')
329
- Logger.isErrorEnabled && Logger.error('Requester FSP not found')
370
+ const errMessage = ERROR_MESSAGES.sourceFspNotFound
371
+ logger.error(errMessage)
372
+ fspiopError = ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, errMessage)
330
373
  throw fspiopError
331
374
  }
332
375
  } else {
@@ -334,10 +377,10 @@ const postParticipants = async (headers, method, params, payload, span, cache) =
334
377
  await participant.sendErrorToParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], errorCallbackEndpointType,
335
378
  fspiopError.toApiErrorObject(Config.ERROR_HANDLING), headers, params, childSpan)
336
379
  }
337
- Logger.isInfoEnabled && Logger.info('postParticipants::end')
380
+ logger.info('postParticipants::end')
338
381
  histTimerEnd({ success: true })
339
382
  } catch (err) {
340
- Logger.isErrorEnabled && Logger.error(`error in postParticipants: ${err?.message}`)
383
+ logger.error('error in postParticipants:', err)
341
384
  fspiopError = ErrorHandler.Factory.reformatFSPIOPError(err, ErrorHandler.Enums.FSPIOPErrorCodes.ADD_PARTY_INFO_ERROR)
342
385
  try {
343
386
  const errorCallbackEndpointType = params.SubId
@@ -348,7 +391,7 @@ const postParticipants = async (headers, method, params, payload, span, cache) =
348
391
  } catch (exc) {
349
392
  // We can't do anything else here- we _must_ handle all errors _within_ this function because
350
393
  // we've already sent a sync response- we cannot throw.
351
- Logger.isErrorEnabled && Logger.error(`failed to handle exception in postParticipants due to error: ${exc?.stack}`)
394
+ logger.error('failed to handle exception in postParticipants:', exc)
352
395
  }
353
396
  histTimerEnd({ success: false })
354
397
  } finally {
@@ -376,92 +419,90 @@ const postParticipantsBatch = async (headers, method, requestPayload, span) => {
376
419
  'Post participants batch',
377
420
  ['success']
378
421
  ).startTimer()
422
+ const requestId = requestPayload.requestId
423
+ const log = logger.child({ context: 'postParticipantsBatch', requestId })
379
424
  const childSpan = span ? span.getChild('postParticipantsBatch') : undefined
380
425
  let fspiopError
426
+
381
427
  try {
382
- Logger.isInfoEnabled && Logger.info('postParticipantsBatch::begin')
428
+ log.info('postParticipantsBatch::begin', { headers, requestPayload })
383
429
  const typeMap = new Map()
384
430
  const overallReturnList = []
385
- const requestId = requestPayload.requestId
431
+ const pushPartyError = (party, errCode) => {
432
+ log.debug('party error details:', { party, errCode })
433
+ overallReturnList.push({
434
+ partyId: party,
435
+ ...ErrorHandler.Factory.createFSPIOPError(errCode, undefined, undefined, undefined, [{
436
+ key: party.partyIdType,
437
+ value: party.partyIdentifier
438
+ }]).toApiErrorObject(Config.ERROR_HANDLING)
439
+ })
440
+ }
441
+
386
442
  const requesterParticipantModel = await participant.validateParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], childSpan)
387
- if (requesterParticipantModel) {
388
- for (const party of requestPayload.partyList) {
389
- if (Object.values(Enums.Accounts.PartyAccountTypes).includes(party.partyIdType)) {
390
- party.currency = requestPayload.currency
391
- if (party.fspId === headers[Enums.Http.Headers.FSPIOP.SOURCE]) {
392
- if (typeMap.get(party.partyIdType)) {
393
- const partyList = typeMap.get(party.partyIdType)
394
- partyList.push(party)
395
- typeMap.set(party.partyIdType, partyList)
396
- } else {
397
- typeMap.set(party.partyIdType, [party])
398
- }
399
- } else {
400
- overallReturnList.push(ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.PARTY_NOT_FOUND, undefined, undefined, undefined, [{
401
- key: party.partyIdType,
402
- value: party.partyIdentifier
403
- }]).toApiErrorObject(Config.ERROR_HANDLING))
404
- }
405
- } else {
406
- overallReturnList.push(ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ADD_PARTY_INFO_ERROR, undefined, undefined, undefined, [{
407
- key: party.partyIdType,
408
- value: party.partyIdentifier
409
- }]).toApiErrorObject(Config.ERROR_HANDLING))
410
- }
411
- }
443
+ if (!requesterParticipantModel) {
444
+ const errMessage = ERROR_MESSAGES.sourceFspNotFound
445
+ log.error(errMessage)
446
+ fspiopError = ErrorHandler.Factory.createFSPIOPError(FSPIOPErrorCodes.ID_NOT_FOUND, errMessage)
447
+ throw fspiopError
448
+ }
412
449
 
413
- for (const [key, value] of typeMap) {
414
- const payload = {
415
- requestId,
416
- partyList: value
417
- }
418
- Logger.isInfoEnabled && Logger.info(`postParticipantsBatch::oracleBatchRequest::type=${key}`)
419
- const response = await oracle.oracleBatchRequest(headers, method, requestPayload, key, payload)
420
- if (response && (response.data !== null || response.data !== undefined)) {
421
- if (Array.isArray(response.data.partyList) && response.data.partyList.length > 0) {
422
- for (const party of response.data.partyList) {
423
- party.partyId.currency = undefined
424
- overallReturnList.push(party)
425
- }
450
+ for (const party of requestPayload.partyList) {
451
+ if (Object.values(Enums.Accounts.PartyAccountTypes).includes(party.partyIdType)) {
452
+ party.currency = requestPayload.currency
453
+ if (party.fspId === headers[Enums.Http.Headers.FSPIOP.SOURCE]) {
454
+ if (typeMap.get(party.partyIdType)) {
455
+ const partyList = typeMap.get(party.partyIdType)
456
+ partyList.push(party)
457
+ typeMap.set(party.partyIdType, partyList)
426
458
  } else {
427
- for (const party of value) {
428
- overallReturnList.push(ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ADD_PARTY_INFO_ERROR, undefined, undefined, undefined, [{
429
- key: party.partyIdType,
430
- value: party.partyIdentifier
431
- }]).toApiErrorObject(Config.ERROR_HANDLING))
432
- }
459
+ typeMap.set(party.partyIdType, [party])
433
460
  }
434
461
  } else {
435
- for (const party of value) {
436
- overallReturnList.push(ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ADD_PARTY_INFO_ERROR, undefined, undefined, undefined, [{
437
- key: party.partyIdType,
438
- value: party.partyIdentifier
439
- }]).toApiErrorObject(Config.ERROR_HANDLING))
440
- }
462
+ pushPartyError(party, FSPIOPErrorCodes.PARTY_NOT_FOUND)
441
463
  }
464
+ } else {
465
+ pushPartyError(party, FSPIOPErrorCodes.ADD_PARTY_INFO_ERROR)
442
466
  }
467
+ }
468
+
469
+ for (const [key, value] of typeMap) {
443
470
  const payload = {
444
- partyList: overallReturnList,
445
- currency: requestPayload.currency
446
- }
447
- const clonedHeaders = { ...headers }
448
- if (!clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION] || clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION] === '') {
449
- clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION] = payload.partyList[0].partyId.fspId
450
- clonedHeaders[Enums.Http.Headers.FSPIOP.SOURCE] = Config.HUB_NAME
471
+ requestId,
472
+ partyList: value
451
473
  }
452
- await participant.sendRequest(clonedHeaders, clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION], Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_BATCH_PUT, Enums.Http.RestMethods.PUT, payload, { requestId }, childSpan)
453
- if (childSpan && !childSpan.isFinished) {
454
- await childSpan.finish()
474
+ log.info(`postParticipantsBatch::oracleBatchRequest::type=${key}`, { payload })
475
+ const response = await oracle.oracleBatchRequest(headers, method, requestPayload, key, payload)
476
+ if (Array.isArray(response?.data?.partyList) && response.data.partyList.length > 0) {
477
+ for (const party of response.data.partyList) {
478
+ party.partyId.currency = undefined
479
+ overallReturnList.push(party)
480
+ }
481
+ } else {
482
+ for (const party of value) {
483
+ pushPartyError(party, FSPIOPErrorCodes.ADD_PARTY_INFO_ERROR)
484
+ }
455
485
  }
456
- Logger.isInfoEnabled && Logger.info('postParticipantsBatch::end')
457
- } else {
458
- Logger.isErrorEnabled && Logger.error('Requester FSP not found')
459
- fspiopError = ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, 'Requester FSP not found')
460
- throw fspiopError
461
486
  }
487
+
488
+ const payload = {
489
+ partyList: overallReturnList,
490
+ currency: requestPayload.currency
491
+ }
492
+ const clonedHeaders = { ...headers }
493
+ if (!clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION] || clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION] === '') {
494
+ clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION] = headers[Enums.Http.Headers.FSPIOP.SOURCE]
495
+ clonedHeaders[Enums.Http.Headers.FSPIOP.SOURCE] = Config.HUB_NAME
496
+ }
497
+ await participant.sendRequest(clonedHeaders, clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION], Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_BATCH_PUT, Enums.Http.RestMethods.PUT, payload, { requestId }, childSpan)
498
+ if (childSpan && !childSpan.isFinished) {
499
+ await childSpan.finish()
500
+ }
501
+ log.info('postParticipantsBatch::end')
502
+
462
503
  histTimerEnd({ success: true })
463
504
  } catch (err) {
464
- Logger.isErrorEnabled && Logger.error(err)
505
+ log.error('error in postParticipantsBatch', err)
465
506
  fspiopError = ErrorHandler.Factory.reformatFSPIOPError(err)
466
507
  try {
467
508
  await participant.sendErrorToParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_BATCH_PUT_ERROR,
@@ -469,7 +510,7 @@ const postParticipantsBatch = async (headers, method, requestPayload, span) => {
469
510
  } catch (exc) {
470
511
  // We can't do anything else here- we _must_ handle all errors _within_ this function because
471
512
  // we've already sent a sync response- we cannot throw.
472
- Logger.isErrorEnabled && Logger.error(exc)
513
+ log.error('error in participant.sendErrorToParticipant', exc)
473
514
  }
474
515
  histTimerEnd({ success: false })
475
516
  } finally {
@@ -498,8 +539,9 @@ const deleteParticipants = async (headers, params, method, query, cache) => {
498
539
  'Delete participants',
499
540
  ['success']
500
541
  ).startTimer()
542
+ const log = logger.child('deleteParticipants')
501
543
  try {
502
- Logger.isInfoEnabled && Logger.info('deleteParticipants::begin')
544
+ log.debug('deleteParticipants::begin', { headers, params })
503
545
  const type = params.Type
504
546
  const partySubIdOrType = params.SubId || undefined
505
547
  const callbackEndpointType = partySubIdOrType ? Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT : Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT
@@ -526,17 +568,18 @@ const deleteParticipants = async (headers, params, method, query, cache) => {
526
568
  ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.DELETE_PARTY_INFO_ERROR).toApiErrorObject(Config.ERROR_HANDLING), headers, params)
527
569
  }
528
570
  } else {
529
- Logger.isErrorEnabled && Logger.error('Requester FSP not found')
530
- throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, 'Requester FSP not found')
571
+ const errMessage = ERROR_MESSAGES.sourceFspNotFound
572
+ log.error(errMessage)
573
+ throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, errMessage)
531
574
  }
532
575
  } else {
533
576
  await participant.sendErrorToParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], errorCallbackEndpointType,
534
577
  ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.DELETE_PARTY_INFO_ERROR).toApiErrorObject(Config.ERROR_HANDLING), headers, params)
535
578
  }
536
- Logger.isInfoEnabled && Logger.info('deleteParticipants::end')
579
+ log.info('deleteParticipants::end')
537
580
  histTimerEnd({ success: true })
538
581
  } catch (err) {
539
- Logger.isErrorEnabled && Logger.error(err)
582
+ log.error('error in deleteParticipants', err)
540
583
  try {
541
584
  const errorCallbackEndpointType = params.SubId ? Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT_ERROR : Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR
542
585
  await participant.sendErrorToParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], errorCallbackEndpointType,
@@ -544,7 +587,7 @@ const deleteParticipants = async (headers, params, method, query, cache) => {
544
587
  } catch (exc) {
545
588
  // We can't do anything else here- we _must_ handle all errors _within_ this function because
546
589
  // we've already sent a sync response- we cannot throw.
547
- Logger.isErrorEnabled && Logger.error(exc)
590
+ log.error('error in participant.sendErrorToParticipant', exc)
548
591
  }
549
592
  histTimerEnd({ success: false })
550
593
  }