account-lookup-service 15.5.0-iso.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (209) hide show
  1. package/.circleci/config.yml +11 -0
  2. package/.ncurc.yaml +6 -0
  3. package/.nvmrc +1 -0
  4. package/.nycrc.yml +20 -0
  5. package/.versionrc +15 -0
  6. package/CHANGELOG.md +330 -0
  7. package/CODEOWNERS +38 -0
  8. package/Dockerfile +45 -0
  9. package/LICENSE.md +10 -0
  10. package/README.md +252 -0
  11. package/audit-ci.jsonc +32 -0
  12. package/audit-resolve.json +161 -0
  13. package/config/default.json +109 -0
  14. package/config/knexfile.js +21 -0
  15. package/docker/account-lookup-service/default.json +106 -0
  16. package/docker/account-lookup-service/make-default-json.sh +5 -0
  17. package/docker/account-lookup-service/override.json +15 -0
  18. package/docker/central-ledger/default.json +458 -0
  19. package/docker/config-modifier/account-lookup-service.js +31 -0
  20. package/docker/kafka/consumer.properties +26 -0
  21. package/docker/kafka/producer.properties +45 -0
  22. package/docker/kafka/server.properties +143 -0
  23. package/docker/kafka/tools-log4j.properties +21 -0
  24. package/docker/mock-proxy/Dockerfile +15 -0
  25. package/docker/mock-proxy/package-lock.json +4986 -0
  26. package/docker/mock-proxy/package.json +24 -0
  27. package/docker/mock-proxy/src/config.ts +14 -0
  28. package/docker/mock-proxy/src/server.ts +94 -0
  29. package/docker/mock-proxy/src/utils.ts +29 -0
  30. package/docker/mock-proxy/tsconfig.json +24 -0
  31. package/docker/sql-init/01_permissions.sql +2 -0
  32. package/docker/sql-init-central-ledger/01_permissions.sql +2 -0
  33. package/docker/wait-for/wait-for-account-lookup-service.sh +10 -0
  34. package/docker/wait-for/wait-for-central-ledger.sh +11 -0
  35. package/docker/wait-for/wait-for-kafka.sh +7 -0
  36. package/docker/wait-for/wait-for-ml-api-adapter.sh +9 -0
  37. package/docker/wait-for/wait-for-mockserver.sh +20 -0
  38. package/docker/wait-for/wait-for-mysql-als.sh +14 -0
  39. package/docker/wait-for/wait-for-mysql-central-ledger.sh +11 -0
  40. package/docker/wait-for/wait-for-mysql.sh +11 -0
  41. package/docker/wait-for/wait-for-objstore.sh +12 -0
  42. package/docker/wait-for/wait-for.env +18 -0
  43. package/docker/wait-for/wait-for.sh +81 -0
  44. package/docker-compose.integration.yml +29 -0
  45. package/docker-compose.yml +243 -0
  46. package/jest-int.config.js +8 -0
  47. package/jest.config.js +16 -0
  48. package/jsdoc.json +38 -0
  49. package/migrations/01_currency.js +42 -0
  50. package/migrations/02_endpointType.js +43 -0
  51. package/migrations/03_endpointType-indexes.js +37 -0
  52. package/migrations/04_partyIdType.js +43 -0
  53. package/migrations/05_partyIdType-indexes.js +38 -0
  54. package/migrations/08_oracleEndpoint.js +51 -0
  55. package/migrations/09_oracleEndpoint-indexes.js +41 -0
  56. package/migrations/10_oracleEndpoint-remove-constraints.js +38 -0
  57. package/package.json +180 -0
  58. package/scripts/_wait4_all.js +143 -0
  59. package/scripts/test-functional.sh +76 -0
  60. package/secrets/jwsSigningKey.key +27 -0
  61. package/seeds/currency.js +765 -0
  62. package/seeds/endpointType.js +65 -0
  63. package/seeds/partyIdType.js +79 -0
  64. package/src/api/endpointcache.js +67 -0
  65. package/src/api/health.js +66 -0
  66. package/src/api/index.js +85 -0
  67. package/src/api/oracles/{ID}.js +100 -0
  68. package/src/api/oracles.js +96 -0
  69. package/src/api/participants/{ID}/error.js +44 -0
  70. package/src/api/participants/{ID}.js +44 -0
  71. package/src/api/participants/{Type}/{ID}/error.js +74 -0
  72. package/src/api/participants/{Type}/{ID}/{SubId}/error.js +68 -0
  73. package/src/api/participants/{Type}/{ID}/{SubId}.js +113 -0
  74. package/src/api/participants/{Type}/{ID}.js +133 -0
  75. package/src/api/participants.js +63 -0
  76. package/src/api/parties/{Type}/{ID}/error.js +66 -0
  77. package/src/api/parties/{Type}/{ID}/{SubId}/error.js +56 -0
  78. package/src/api/parties/{Type}/{ID}/{SubId}.js +77 -0
  79. package/src/api/parties/{Type}/{ID}.js +98 -0
  80. package/src/api/routes.js +294 -0
  81. package/src/constants.js +16 -0
  82. package/src/domain/oracle/index.js +33 -0
  83. package/src/domain/oracle/oracle.js +234 -0
  84. package/src/domain/participants/index.js +35 -0
  85. package/src/domain/participants/participants.js +560 -0
  86. package/src/domain/parties/getPartiesByTypeAndID.js +239 -0
  87. package/src/domain/parties/index.js +32 -0
  88. package/src/domain/parties/parties.js +215 -0
  89. package/src/domain/parties/utils.js +84 -0
  90. package/src/domain/timeout/dto.js +48 -0
  91. package/src/domain/timeout/index.js +104 -0
  92. package/src/handlers/TimeoutHandler.js +94 -0
  93. package/src/handlers/index.js +70 -0
  94. package/src/handlers/monitoring/index.js +51 -0
  95. package/src/handlers/monitoring/plugins/health.js +61 -0
  96. package/src/handlers/monitoring/plugins/metrics.js +48 -0
  97. package/src/handlers/register.js +102 -0
  98. package/src/index.js +66 -0
  99. package/src/interface/admin-swagger.yaml +804 -0
  100. package/src/interface/admin_swagger.json +959 -0
  101. package/src/interface/api-swagger-iso20022-parties.yaml +1734 -0
  102. package/src/interface/api-swagger.yaml +1733 -0
  103. package/src/interface/api_swagger.json +3046 -0
  104. package/src/interface/fspiop-rest-v2.0-ISO20022_parties.yaml +2256 -0
  105. package/src/interface/thirdparty/admin-swagger.yaml +808 -0
  106. package/src/interface/thirdparty/admin_swagger.json +961 -0
  107. package/src/interface/thirdparty/api-swagger.yaml +1739 -0
  108. package/src/interface/thirdparty/api_swagger.json +3142 -0
  109. package/src/lib/argv.js +39 -0
  110. package/src/lib/cache.js +126 -0
  111. package/src/lib/config.js +183 -0
  112. package/src/lib/db.js +26 -0
  113. package/src/lib/headers.js +53 -0
  114. package/src/lib/healthCheck/subServiceHealth.js +84 -0
  115. package/src/lib/index.js +11 -0
  116. package/src/lib/migrator.js +17 -0
  117. package/src/lib/requestLogger.js +54 -0
  118. package/src/lib/util.js +66 -0
  119. package/src/metrics/handler.js +33 -0
  120. package/src/metrics/plugin.js +52 -0
  121. package/src/metrics/routes.js +43 -0
  122. package/src/models/currency/currency.js +48 -0
  123. package/src/models/currency/index.js +32 -0
  124. package/src/models/endpointType/endpointType.js +48 -0
  125. package/src/models/endpointType/index.js +32 -0
  126. package/src/models/misc/migrationLock.js +49 -0
  127. package/src/models/oracle/facade.js +341 -0
  128. package/src/models/oracle/index.js +41 -0
  129. package/src/models/oracle/oracleEndpoint.js +192 -0
  130. package/src/models/oracle/oracleEndpointCached.js +108 -0
  131. package/src/models/participantEndpoint/facade.js +238 -0
  132. package/src/models/partyIdType/index.js +32 -0
  133. package/src/models/partyIdType/partyIdType.js +41 -0
  134. package/src/plugins.js +139 -0
  135. package/src/server.js +199 -0
  136. package/test/fixtures/index.js +131 -0
  137. package/test/fixtures/iso.js +110 -0
  138. package/test/integration/.env +8 -0
  139. package/test/integration/api/parties.test.js +137 -0
  140. package/test/integration/constants.js +20 -0
  141. package/test/integration/domain/oracle/index.test.js +324 -0
  142. package/test/integration/domain/timeout/index.test.js +75 -0
  143. package/test/integration/env.sh +15 -0
  144. package/test/integration/example.test.js +12 -0
  145. package/test/integration/models/currency/currency.test.js +68 -0
  146. package/test/integration/plugins.test.js +62 -0
  147. package/test/integration/prepareTestParticipants.js +30 -0
  148. package/test/integration/setup.js +5 -0
  149. package/test/integration-config.json +81 -0
  150. package/test/integration-runner.sh +108 -0
  151. package/test/unit/api/health.test.js +142 -0
  152. package/test/unit/api/oracles/{ID}.test.js +264 -0
  153. package/test/unit/api/oracles.test.js +173 -0
  154. package/test/unit/api/participants/participants.test.js +117 -0
  155. package/test/unit/api/participants/{Type}/{ID}/error.test.js +155 -0
  156. package/test/unit/api/participants/{Type}/{ID}/{SubId}/error.test.js +131 -0
  157. package/test/unit/api/participants/{Type}/{ID}/{SubId}.test.js +377 -0
  158. package/test/unit/api/participants/{Type}/{ID}.test.js +383 -0
  159. package/test/unit/api/participants.test.js +108 -0
  160. package/test/unit/api/parties/endpointcache.test.js +83 -0
  161. package/test/unit/api/parties/parties.test.js +102 -0
  162. package/test/unit/api/parties/{Type}/{ID}/error.test.js +145 -0
  163. package/test/unit/api/parties/{Type}/{ID}/{SubId}/error.test.js +141 -0
  164. package/test/unit/api/parties/{Type}/{ID}/{SubId}.test.js +241 -0
  165. package/test/unit/api/parties/{Type}/{ID}.test.js +240 -0
  166. package/test/unit/domain/oracle/oracle.test.js +505 -0
  167. package/test/unit/domain/participants/participants.test.js +1724 -0
  168. package/test/unit/domain/parties/parties.test.js +940 -0
  169. package/test/unit/domain/timeout/dto.test.js +28 -0
  170. package/test/unit/domain/timeout/index.test.js +81 -0
  171. package/test/unit/handlers/TimeoutHandler.test.js +125 -0
  172. package/test/unit/handlers/index.test.js +56 -0
  173. package/test/unit/handlers/register.test.js +90 -0
  174. package/test/unit/index.test.js +139 -0
  175. package/test/unit/iso20022/partiesValidation.test.js +129 -0
  176. package/test/unit/lib/TransformFacades.test.js +18 -0
  177. package/test/unit/lib/argv.test.js +40 -0
  178. package/test/unit/lib/cache.test.js +172 -0
  179. package/test/unit/lib/config.test.js +108 -0
  180. package/test/unit/lib/healthCheck/subServiceHealth.test.js +89 -0
  181. package/test/unit/lib/migrator.test.js +52 -0
  182. package/test/unit/lib/requestLogger.test.js +115 -0
  183. package/test/unit/lib/util.test.js +68 -0
  184. package/test/unit/mocks.js +66 -0
  185. package/test/unit/models/currency/currency.test.js +91 -0
  186. package/test/unit/models/endpointType/endpointType.test.js +69 -0
  187. package/test/unit/models/misc/migrationLock.test.js +96 -0
  188. package/test/unit/models/oracle/facade.test.js +546 -0
  189. package/test/unit/models/oracle/oracleEndpoint.test.js +409 -0
  190. package/test/unit/models/oracle/oracleEndpointCached.test.js +153 -0
  191. package/test/unit/models/participantEndpoint/facade.test.js +295 -0
  192. package/test/unit/models/partyIdType/partyIdType.test.js +88 -0
  193. package/test/unit/plugins.test.js +89 -0
  194. package/test/unit/setup.js +7 -0
  195. package/test/util/apiClients/AlsApiClient.js +44 -0
  196. package/test/util/apiClients/BasicApiClient.js +34 -0
  197. package/test/util/apiClients/ProxyApiClient.js +25 -0
  198. package/test/util/apiClients/index.js +7 -0
  199. package/test/util/helper.js +332 -0
  200. package/test/util/index.js +11 -0
  201. package/test/util/mockgen.js +43 -0
  202. package/test/util/onboarding.js +132 -0
  203. package/test/util/scripts/addAlsDb.sh +33 -0
  204. package/test/util/scripts/configureMockServer.sh +35 -0
  205. package/test/util/scripts/env.sh +19 -0
  206. package/test/util/scripts/populateTestData.sh +62 -0
  207. package/test/util/scripts/startMockCentralServer.sh +45 -0
  208. package/test/util/scripts/startMockOracleServer.sh +45 -0
  209. package/test/util/testConfig.js +44 -0
@@ -0,0 +1,35 @@
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
+ - Rajiv Mothilal <rajiv.mothilal@modusbox.com>
22
+
23
+ --------------
24
+ ******/
25
+
26
+ 'use strict'
27
+
28
+ const participants = require('./participants')
29
+
30
+ exports.getParticipantsByTypeAndID = participants.getParticipantsByTypeAndID
31
+ exports.putParticipantsByTypeAndID = participants.putParticipantsByTypeAndID
32
+ exports.putParticipantsErrorByTypeAndID = participants.putParticipantsErrorByTypeAndID
33
+ exports.postParticipants = participants.postParticipants
34
+ exports.postParticipantsBatch = participants.postParticipantsBatch
35
+ exports.deleteParticipants = participants.deleteParticipants
@@ -0,0 +1,560 @@
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
+ - Rajiv Mothilal <rajiv.mothilal@modusbox.com>
22
+ - Steven Oderayi <steven.oderayi@modusbox.com>
23
+ - Juan Correa <juan.correa@modusbox.com>
24
+
25
+ --------------
26
+ ******/
27
+ 'use strict'
28
+
29
+ const Enums = require('@mojaloop/central-services-shared').Enum
30
+ const { decodePayload } = require('@mojaloop/central-services-shared').Util.StreamingProtocol
31
+ const Logger = require('@mojaloop/central-services-logger')
32
+ const ErrorHandler = require('@mojaloop/central-services-error-handling')
33
+ const EventSdk = require('@mojaloop/event-sdk')
34
+ const Metrics = require('@mojaloop/central-services-metrics')
35
+
36
+ const oracle = require('../../models/oracle/facade')
37
+ const participant = require('../../models/participantEndpoint/facade')
38
+ const Config = require('../../lib/config')
39
+
40
+ /**
41
+ * @function getParticipantsByTypeAndID
42
+ *
43
+ * @description sends request to applicable oracle based on type and sends results back to requester
44
+ *
45
+ * @param {object} headers - incoming http request headers
46
+ * @param {object} params - uri parameters of the http request
47
+ * @param {string} method - http request method
48
+ * @param {object} query - uri query parameters of the http request
49
+ * @param {object} span
50
+ * */
51
+ const getParticipantsByTypeAndID = async (headers, params, method, query, span, cache) => {
52
+ const childSpan = span ? span.getChild('getParticipantsByTypeAndID') : undefined
53
+ const histTimerEnd = Metrics.getHistogram(
54
+ 'getParticipantsByTypeAndID',
55
+ 'Get participants by ID',
56
+ ['success']
57
+ ).startTimer()
58
+ 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
+ let fspiopError
64
+ 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)
87
+ }
88
+ Logger.isInfoEnabled && Logger.info('getParticipantsByTypeAndID::end')
89
+ } 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')
92
+ }
93
+ if (childSpan && !childSpan.isFinished) {
94
+ await childSpan.finish()
95
+ }
96
+ } catch (err) {
97
+ Logger.isErrorEnabled && Logger.error(err)
98
+ fspiopError = ErrorHandler.Factory.reformatFSPIOPError(err, ErrorHandler.Enums.FSPIOPErrorCodes.ADD_PARTY_INFO_ERROR)
99
+ 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
+ await participant.sendErrorToParticipant(
102
+ headers[Enums.Http.Headers.FSPIOP.SOURCE], errorCallbackEndpointType,
103
+ fspiopError.toApiErrorObject(Config.ERROR_HANDLING), headers, params, childSpan)
104
+ } catch (exc) {
105
+ fspiopError = ErrorHandler.Factory.reformatFSPIOPError(exc)
106
+ // We can't do anything else here- we _must_ handle all errors _within_ this function because
107
+ // we've already sent a sync response- we cannot throw.
108
+ Logger.isErrorEnabled && Logger.error(exc)
109
+ }
110
+ } finally {
111
+ if (childSpan && !childSpan.isFinished && fspiopError) {
112
+ const state = new EventSdk.EventStateMetadata(EventSdk.EventStatusType.failed, fspiopError.apiErrorCode.code, fspiopError.apiErrorCode.message)
113
+ await childSpan.error(fspiopError, state)
114
+ await childSpan.finish(fspiopError.message, state)
115
+ histTimerEnd({ success: false })
116
+ }
117
+ histTimerEnd({ success: true })
118
+ }
119
+ }
120
+
121
+ /**
122
+ * @function putParticipantsByTypeAndID
123
+ *
124
+ * @description This informs the client of a successful result of the lookup, creation, or deletion of the FSP
125
+ * information related to the Party. If the FSP information is deleted, the fspId element should be empty;
126
+ * otherwise the element should include the FSP information for the Party.
127
+ *
128
+ * @param {object} headers - incoming http request headers
129
+ * @param {object} params - uri parameters of the http request
130
+ * @param {string} method - http request method
131
+ * @param {object} payload - payload of the request being sent out
132
+ *
133
+ */
134
+ const putParticipantsByTypeAndID = async (headers, params, method, payload, cache) => {
135
+ const histTimerEnd = Metrics.getHistogram(
136
+ 'putParticipantsByTypeAndID',
137
+ 'Put participants by type and ID',
138
+ ['success']
139
+ ).startTimer()
140
+ try {
141
+ Logger.isInfoEnabled && Logger.info('putParticipantsByTypeAndID::begin')
142
+ const type = params.Type
143
+ const partySubIdOrType = params.SubId || undefined
144
+ const callbackEndpointType = partySubIdOrType ? Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT : Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT
145
+ const errorCallbackEndpointType = partySubIdOrType ? Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT_ERROR : Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR
146
+ if (Object.values(Enums.Accounts.PartyAccountTypes).includes(type)) {
147
+ const requesterParticipantModel = await participant.validateParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE])
148
+ if (requesterParticipantModel) {
149
+ const response = await oracle.oracleRequest(headers, method, params, undefined, payload, cache)
150
+ if (response && response.data) {
151
+ const responsePayload = {
152
+ partyList: [
153
+ {
154
+ partyIdType: type,
155
+ partyIdentifier: params.ID,
156
+ fspId: payload.fspId
157
+ }
158
+ ],
159
+ currency: payload.currency
160
+ }
161
+ if (partySubIdOrType) {
162
+ responsePayload.partyList[0].partySubIdOrType = partySubIdOrType
163
+ }
164
+ let options = {
165
+ partyIdType: params.Type,
166
+ partyIdentifier: params.ID
167
+ }
168
+ options = partySubIdOrType ? { ...options, partySubIdOrType } : options
169
+ const clonedHeaders = { ...headers }
170
+ if (!clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION] || clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION] === '') {
171
+ clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION] = payload.fspId
172
+ clonedHeaders[Enums.Http.Headers.FSPIOP.SOURCE] = Config.HUB_NAME
173
+ }
174
+ await participant.sendRequest(clonedHeaders, clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION], callbackEndpointType, Enums.Http.RestMethods.PUT, responsePayload, options)
175
+ } else {
176
+ await participant.sendErrorToParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], errorCallbackEndpointType,
177
+ ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ADD_PARTY_INFO_ERROR).toApiErrorObject(Config.ERROR_HANDLING), headers, params)
178
+ }
179
+ } 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')
182
+ }
183
+ } else {
184
+ await participant.sendErrorToParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], errorCallbackEndpointType,
185
+ ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ADD_PARTY_INFO_ERROR).toApiErrorObject(Config.ERROR_HANDLING), headers, params)
186
+ }
187
+ Logger.isInfoEnabled && Logger.info('putParticipantsByTypeAndID::end')
188
+ histTimerEnd({ success: true })
189
+ } catch (err) {
190
+ Logger.isErrorEnabled && Logger.error(err)
191
+ try {
192
+ 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
+ await participant.sendErrorToParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], errorCallbackEndpointType,
194
+ ErrorHandler.Factory.reformatFSPIOPError(err, ErrorHandler.Enums.FSPIOPErrorCodes.ADD_PARTY_INFO_ERROR).toApiErrorObject(Config.ERROR_HANDLING), headers, params)
195
+ } catch (exc) {
196
+ // We can't do anything else here- we _must_ handle all errors _within_ this function because
197
+ // we've already sent a sync response- we cannot throw.
198
+ Logger.isErrorEnabled && Logger.error(exc)
199
+ }
200
+ histTimerEnd({ success: false })
201
+ }
202
+ }
203
+
204
+ /**
205
+ * @function putParticipantsErrorByTypeAndID
206
+ *
207
+ *
208
+ * @description If the server is unable to find, create or delete the associated FSP of the provided identity,
209
+ * or another processing error occurred, the error callback PUT /participants/<Type>/<ID>/error
210
+ * (or PUT /participants/<Type>/<ID>/<SubId>/error) is used.
211
+ *
212
+ * @param {object} headers - incoming http request headers
213
+ * @param {object} params - uri parameters of the http request
214
+ * @param {object} payload - payload of the request being sent out
215
+ * @param {string} dataUri - encoded payload of the request being sent out
216
+ */
217
+ const putParticipantsErrorByTypeAndID = async (headers, params, payload, dataUri) => {
218
+ const histTimerEnd = Metrics.getHistogram(
219
+ 'putParticipantsErrorByTypeAndID',
220
+ 'Put participants error by type and ID',
221
+ ['success']
222
+ ).startTimer()
223
+ try {
224
+ 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
226
+ const destinationParticipant = await participant.validateParticipant(headers[Enums.Http.Headers.FSPIOP.DESTINATION])
227
+ if (destinationParticipant) {
228
+ const decodedPayload = decodePayload(dataUri, { asParsed: false })
229
+ await participant.sendErrorToParticipant(
230
+ headers[Enums.Http.Headers.FSPIOP.DESTINATION],
231
+ callbackEndpointType,
232
+ decodedPayload.body.toString(),
233
+ headers,
234
+ params)
235
+ } else {
236
+ await participant.sendErrorToParticipant(
237
+ headers[Enums.Http.Headers.FSPIOP.SOURCE],
238
+ callbackEndpointType,
239
+ ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.DESTINATION_FSP_ERROR).toApiErrorObject(),
240
+ headers,
241
+ params,
242
+ payload)
243
+ }
244
+ histTimerEnd({ success: true })
245
+ } catch (err) {
246
+ Logger.isErrorEnabled && Logger.error(err)
247
+ 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)
251
+ } catch (exc) {
252
+ // We can't do anything else here- we _must_ handle all errors _within_ this function because
253
+ // we've already sent a sync response- we cannot throw.
254
+ Logger.isErrorEnabled && Logger.error(exc)
255
+ }
256
+ histTimerEnd({ success: false })
257
+ }
258
+ }
259
+
260
+ /**
261
+ * @function postParticipants
262
+ *
263
+ * @description This sends request to all applicable oracles to store
264
+ *
265
+ * @param {object} headers - incoming http request headers
266
+ * @param {string} method - http request method
267
+ * @param {object} params - uri parameters of the http request
268
+ * @param {object} payload - payload of the request being sent out
269
+ * @param {object} span
270
+ */
271
+ const postParticipants = async (headers, method, params, payload, span, cache) => {
272
+ const histTimerEnd = Metrics.getHistogram(
273
+ 'postParticipants',
274
+ 'Post participants',
275
+ ['success']
276
+ ).startTimer()
277
+ const childSpan = span ? span.getChild('postParticipants') : undefined
278
+ let fspiopError
279
+ try {
280
+ Logger.isInfoEnabled && Logger.info('postParticipants::begin')
281
+ const type = params.Type
282
+ const partySubIdOrType = params.SubId
283
+ const callbackEndpointType = partySubIdOrType
284
+ ? Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT
285
+ : Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT
286
+ const errorCallbackEndpointType = partySubIdOrType
287
+ ? Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT_ERROR
288
+ : Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR
289
+
290
+ if (Object.values(Enums.Accounts.PartyAccountTypes).includes(type)) {
291
+ const requesterParticipantModel = await participant.validateParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], childSpan)
292
+ if (requesterParticipantModel) {
293
+ const response = await oracle.oracleRequest(headers, method, params, undefined, payload, cache)
294
+ if (response && response.status === Enums.Http.ReturnCodes.CREATED.CODE) {
295
+ const responsePayload = {
296
+ partyList: [
297
+ {
298
+ partyIdType: type,
299
+ partyIdentifier: params.ID,
300
+ fspId: payload.fspId
301
+ }
302
+ ],
303
+ currency: payload.currency
304
+ }
305
+ if (partySubIdOrType) {
306
+ responsePayload.partyList[0].partySubIdOrType = partySubIdOrType
307
+ }
308
+ let options = {
309
+ partyIdType: params.Type,
310
+ partyIdentifier: params.ID
311
+ }
312
+ options = partySubIdOrType ? { ...options, partySubIdOrType } : options
313
+ const clonedHeaders = { ...headers }
314
+ if (!clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION] || clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION] === '') {
315
+ clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION] = payload.fspId
316
+ clonedHeaders[Enums.Http.Headers.FSPIOP.SOURCE] = Config.HUB_NAME
317
+ }
318
+ await participant.sendRequest(clonedHeaders, clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION], callbackEndpointType, Enums.Http.RestMethods.PUT, responsePayload, options, childSpan)
319
+ if (childSpan && !childSpan.isFinished) {
320
+ await childSpan.finish()
321
+ }
322
+ } else {
323
+ fspiopError = ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ADD_PARTY_INFO_ERROR)
324
+ await participant.sendErrorToParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], errorCallbackEndpointType,
325
+ fspiopError.toApiErrorObject(Config.ERROR_HANDLING), headers, params, childSpan)
326
+ }
327
+ } 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')
330
+ throw fspiopError
331
+ }
332
+ } else {
333
+ fspiopError = ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ADD_PARTY_INFO_ERROR)
334
+ await participant.sendErrorToParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], errorCallbackEndpointType,
335
+ fspiopError.toApiErrorObject(Config.ERROR_HANDLING), headers, params, childSpan)
336
+ }
337
+ Logger.isInfoEnabled && Logger.info('postParticipants::end')
338
+ histTimerEnd({ success: true })
339
+ } catch (err) {
340
+ Logger.isErrorEnabled && Logger.error(`error in postParticipants: ${err?.message}`)
341
+ fspiopError = ErrorHandler.Factory.reformatFSPIOPError(err, ErrorHandler.Enums.FSPIOPErrorCodes.ADD_PARTY_INFO_ERROR)
342
+ try {
343
+ const errorCallbackEndpointType = params.SubId
344
+ ? Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT_ERROR
345
+ : Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR
346
+ await participant.sendErrorToParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], errorCallbackEndpointType,
347
+ fspiopError.toApiErrorObject(Config.ERROR_HANDLING), headers, params, childSpan)
348
+ } catch (exc) {
349
+ // We can't do anything else here- we _must_ handle all errors _within_ this function because
350
+ // 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}`)
352
+ }
353
+ histTimerEnd({ success: false })
354
+ } finally {
355
+ if (childSpan && !childSpan.isFinished && fspiopError) {
356
+ const state = new EventSdk.EventStateMetadata(EventSdk.EventStatusType.failed, fspiopError.apiErrorCode.code, fspiopError.apiErrorCode.message)
357
+ await childSpan.error(fspiopError, state)
358
+ await childSpan.finish(fspiopError.message, state)
359
+ }
360
+ }
361
+ }
362
+
363
+ /**
364
+ * @function postParticipantsBatch
365
+ *
366
+ * @description This sends request to all applicable oracles to store
367
+ *
368
+ * @param {object} headers - incoming http request headers
369
+ * @param {string} method - http request method
370
+ * @param {object} requestPayload - payload of the request being sent out
371
+ * @param {object} span
372
+ */
373
+ const postParticipantsBatch = async (headers, method, requestPayload, span) => {
374
+ const histTimerEnd = Metrics.getHistogram(
375
+ 'postParticipantsBatch',
376
+ 'Post participants batch',
377
+ ['success']
378
+ ).startTimer()
379
+ const childSpan = span ? span.getChild('postParticipantsBatch') : undefined
380
+ let fspiopError
381
+ try {
382
+ Logger.isInfoEnabled && Logger.info('postParticipantsBatch::begin')
383
+ const typeMap = new Map()
384
+ const overallReturnList = []
385
+ const requestId = requestPayload.requestId
386
+ 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
+ }
412
+
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
+ }
426
+ } 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
+ }
433
+ }
434
+ } 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
+ }
441
+ }
442
+ }
443
+ 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
451
+ }
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()
455
+ }
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
+ }
462
+ histTimerEnd({ success: true })
463
+ } catch (err) {
464
+ Logger.isErrorEnabled && Logger.error(err)
465
+ fspiopError = ErrorHandler.Factory.reformatFSPIOPError(err)
466
+ try {
467
+ await participant.sendErrorToParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_BATCH_PUT_ERROR,
468
+ fspiopError.toApiErrorObject(Config.ERROR_HANDLING), headers, undefined, requestPayload)
469
+ } catch (exc) {
470
+ // We can't do anything else here- we _must_ handle all errors _within_ this function because
471
+ // we've already sent a sync response- we cannot throw.
472
+ Logger.isErrorEnabled && Logger.error(exc)
473
+ }
474
+ histTimerEnd({ success: false })
475
+ } finally {
476
+ if (childSpan && !childSpan.isFinished && fspiopError) {
477
+ const state = new EventSdk.EventStateMetadata(EventSdk.EventStatusType.failed, fspiopError.apiErrorCode.code, fspiopError.apiErrorCode.message)
478
+ await childSpan.error(fspiopError, state)
479
+ await childSpan.finish(fspiopError.message, state)
480
+ }
481
+ }
482
+ }
483
+
484
+ /**
485
+ * @function deleteParticipants
486
+ *
487
+ * @description This sends request to all applicable oracles to delete participant(s)
488
+ *
489
+ * @param {object} headers - incoming http request headers
490
+ * @param {object} params - uri parameters of the http request
491
+ * @param {string} method - http request method
492
+ * @param {object} query - uri query parameters of the http request
493
+ *
494
+ */
495
+ const deleteParticipants = async (headers, params, method, query, cache) => {
496
+ const histTimerEnd = Metrics.getHistogram(
497
+ 'deleteParticipants',
498
+ 'Delete participants',
499
+ ['success']
500
+ ).startTimer()
501
+ try {
502
+ Logger.isInfoEnabled && Logger.info('deleteParticipants::begin')
503
+ const type = params.Type
504
+ const partySubIdOrType = params.SubId || undefined
505
+ const callbackEndpointType = partySubIdOrType ? Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT : Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT
506
+ const errorCallbackEndpointType = partySubIdOrType ? Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT_ERROR : Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR
507
+ if (Object.values(Enums.Accounts.PartyAccountTypes).includes(type)) {
508
+ const requesterParticipantModel = await participant.validateParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE])
509
+ if (requesterParticipantModel) {
510
+ const response = await oracle.oracleRequest(headers, method, params, query, undefined, cache)
511
+ if (response) {
512
+ const responsePayload = {
513
+ fspId: headers[Enums.Http.Headers.FSPIOP.SOURCE]
514
+ }
515
+ let options = {
516
+ partyIdType: params.Type,
517
+ partyIdentifier: params.ID
518
+ }
519
+ options = partySubIdOrType ? { ...options, partySubIdOrType } : options
520
+ const clonedHeaders = { ...headers }
521
+ clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION] = headers[Enums.Http.Headers.FSPIOP.SOURCE]
522
+ clonedHeaders[Enums.Http.Headers.FSPIOP.SOURCE] = Config.HUB_NAME
523
+ await participant.sendRequest(clonedHeaders, clonedHeaders[Enums.Http.Headers.FSPIOP.DESTINATION], callbackEndpointType, Enums.Http.RestMethods.PUT, responsePayload, options)
524
+ } else {
525
+ await participant.sendErrorToParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], errorCallbackEndpointType,
526
+ ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.DELETE_PARTY_INFO_ERROR).toApiErrorObject(Config.ERROR_HANDLING), headers, params)
527
+ }
528
+ } 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')
531
+ }
532
+ } else {
533
+ await participant.sendErrorToParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], errorCallbackEndpointType,
534
+ ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.DELETE_PARTY_INFO_ERROR).toApiErrorObject(Config.ERROR_HANDLING), headers, params)
535
+ }
536
+ Logger.isInfoEnabled && Logger.info('deleteParticipants::end')
537
+ histTimerEnd({ success: true })
538
+ } catch (err) {
539
+ Logger.isErrorEnabled && Logger.error(err)
540
+ try {
541
+ 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
+ await participant.sendErrorToParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], errorCallbackEndpointType,
543
+ ErrorHandler.Factory.reformatFSPIOPError(err, ErrorHandler.Enums.FSPIOPErrorCodes.DELETE_PARTY_INFO_ERROR).toApiErrorObject(Config.ERROR_HANDLING), headers, params)
544
+ } catch (exc) {
545
+ // We can't do anything else here- we _must_ handle all errors _within_ this function because
546
+ // we've already sent a sync response- we cannot throw.
547
+ Logger.isErrorEnabled && Logger.error(exc)
548
+ }
549
+ histTimerEnd({ success: false })
550
+ }
551
+ }
552
+
553
+ module.exports = {
554
+ getParticipantsByTypeAndID,
555
+ putParticipantsByTypeAndID,
556
+ putParticipantsErrorByTypeAndID,
557
+ postParticipants,
558
+ postParticipantsBatch,
559
+ deleteParticipants
560
+ }