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.
- package/.circleci/config.yml +11 -0
- package/.ncurc.yaml +6 -0
- package/.nvmrc +1 -0
- package/.nycrc.yml +20 -0
- package/.versionrc +15 -0
- package/CHANGELOG.md +330 -0
- package/CODEOWNERS +38 -0
- package/Dockerfile +45 -0
- package/LICENSE.md +10 -0
- package/README.md +252 -0
- package/audit-ci.jsonc +32 -0
- package/audit-resolve.json +161 -0
- package/config/default.json +109 -0
- package/config/knexfile.js +21 -0
- package/docker/account-lookup-service/default.json +106 -0
- package/docker/account-lookup-service/make-default-json.sh +5 -0
- package/docker/account-lookup-service/override.json +15 -0
- package/docker/central-ledger/default.json +458 -0
- package/docker/config-modifier/account-lookup-service.js +31 -0
- package/docker/kafka/consumer.properties +26 -0
- package/docker/kafka/producer.properties +45 -0
- package/docker/kafka/server.properties +143 -0
- package/docker/kafka/tools-log4j.properties +21 -0
- package/docker/mock-proxy/Dockerfile +15 -0
- package/docker/mock-proxy/package-lock.json +4986 -0
- package/docker/mock-proxy/package.json +24 -0
- package/docker/mock-proxy/src/config.ts +14 -0
- package/docker/mock-proxy/src/server.ts +94 -0
- package/docker/mock-proxy/src/utils.ts +29 -0
- package/docker/mock-proxy/tsconfig.json +24 -0
- package/docker/sql-init/01_permissions.sql +2 -0
- package/docker/sql-init-central-ledger/01_permissions.sql +2 -0
- package/docker/wait-for/wait-for-account-lookup-service.sh +10 -0
- package/docker/wait-for/wait-for-central-ledger.sh +11 -0
- package/docker/wait-for/wait-for-kafka.sh +7 -0
- package/docker/wait-for/wait-for-ml-api-adapter.sh +9 -0
- package/docker/wait-for/wait-for-mockserver.sh +20 -0
- package/docker/wait-for/wait-for-mysql-als.sh +14 -0
- package/docker/wait-for/wait-for-mysql-central-ledger.sh +11 -0
- package/docker/wait-for/wait-for-mysql.sh +11 -0
- package/docker/wait-for/wait-for-objstore.sh +12 -0
- package/docker/wait-for/wait-for.env +18 -0
- package/docker/wait-for/wait-for.sh +81 -0
- package/docker-compose.integration.yml +29 -0
- package/docker-compose.yml +243 -0
- package/jest-int.config.js +8 -0
- package/jest.config.js +16 -0
- package/jsdoc.json +38 -0
- package/migrations/01_currency.js +42 -0
- package/migrations/02_endpointType.js +43 -0
- package/migrations/03_endpointType-indexes.js +37 -0
- package/migrations/04_partyIdType.js +43 -0
- package/migrations/05_partyIdType-indexes.js +38 -0
- package/migrations/08_oracleEndpoint.js +51 -0
- package/migrations/09_oracleEndpoint-indexes.js +41 -0
- package/migrations/10_oracleEndpoint-remove-constraints.js +38 -0
- package/package.json +180 -0
- package/scripts/_wait4_all.js +143 -0
- package/scripts/test-functional.sh +76 -0
- package/secrets/jwsSigningKey.key +27 -0
- package/seeds/currency.js +765 -0
- package/seeds/endpointType.js +65 -0
- package/seeds/partyIdType.js +79 -0
- package/src/api/endpointcache.js +67 -0
- package/src/api/health.js +66 -0
- package/src/api/index.js +85 -0
- package/src/api/oracles/{ID}.js +100 -0
- package/src/api/oracles.js +96 -0
- package/src/api/participants/{ID}/error.js +44 -0
- package/src/api/participants/{ID}.js +44 -0
- package/src/api/participants/{Type}/{ID}/error.js +74 -0
- package/src/api/participants/{Type}/{ID}/{SubId}/error.js +68 -0
- package/src/api/participants/{Type}/{ID}/{SubId}.js +113 -0
- package/src/api/participants/{Type}/{ID}.js +133 -0
- package/src/api/participants.js +63 -0
- package/src/api/parties/{Type}/{ID}/error.js +66 -0
- package/src/api/parties/{Type}/{ID}/{SubId}/error.js +56 -0
- package/src/api/parties/{Type}/{ID}/{SubId}.js +77 -0
- package/src/api/parties/{Type}/{ID}.js +98 -0
- package/src/api/routes.js +294 -0
- package/src/constants.js +16 -0
- package/src/domain/oracle/index.js +33 -0
- package/src/domain/oracle/oracle.js +234 -0
- package/src/domain/participants/index.js +35 -0
- package/src/domain/participants/participants.js +560 -0
- package/src/domain/parties/getPartiesByTypeAndID.js +239 -0
- package/src/domain/parties/index.js +32 -0
- package/src/domain/parties/parties.js +215 -0
- package/src/domain/parties/utils.js +84 -0
- package/src/domain/timeout/dto.js +48 -0
- package/src/domain/timeout/index.js +104 -0
- package/src/handlers/TimeoutHandler.js +94 -0
- package/src/handlers/index.js +70 -0
- package/src/handlers/monitoring/index.js +51 -0
- package/src/handlers/monitoring/plugins/health.js +61 -0
- package/src/handlers/monitoring/plugins/metrics.js +48 -0
- package/src/handlers/register.js +102 -0
- package/src/index.js +66 -0
- package/src/interface/admin-swagger.yaml +804 -0
- package/src/interface/admin_swagger.json +959 -0
- package/src/interface/api-swagger-iso20022-parties.yaml +1734 -0
- package/src/interface/api-swagger.yaml +1733 -0
- package/src/interface/api_swagger.json +3046 -0
- package/src/interface/fspiop-rest-v2.0-ISO20022_parties.yaml +2256 -0
- package/src/interface/thirdparty/admin-swagger.yaml +808 -0
- package/src/interface/thirdparty/admin_swagger.json +961 -0
- package/src/interface/thirdparty/api-swagger.yaml +1739 -0
- package/src/interface/thirdparty/api_swagger.json +3142 -0
- package/src/lib/argv.js +39 -0
- package/src/lib/cache.js +126 -0
- package/src/lib/config.js +183 -0
- package/src/lib/db.js +26 -0
- package/src/lib/headers.js +53 -0
- package/src/lib/healthCheck/subServiceHealth.js +84 -0
- package/src/lib/index.js +11 -0
- package/src/lib/migrator.js +17 -0
- package/src/lib/requestLogger.js +54 -0
- package/src/lib/util.js +66 -0
- package/src/metrics/handler.js +33 -0
- package/src/metrics/plugin.js +52 -0
- package/src/metrics/routes.js +43 -0
- package/src/models/currency/currency.js +48 -0
- package/src/models/currency/index.js +32 -0
- package/src/models/endpointType/endpointType.js +48 -0
- package/src/models/endpointType/index.js +32 -0
- package/src/models/misc/migrationLock.js +49 -0
- package/src/models/oracle/facade.js +341 -0
- package/src/models/oracle/index.js +41 -0
- package/src/models/oracle/oracleEndpoint.js +192 -0
- package/src/models/oracle/oracleEndpointCached.js +108 -0
- package/src/models/participantEndpoint/facade.js +238 -0
- package/src/models/partyIdType/index.js +32 -0
- package/src/models/partyIdType/partyIdType.js +41 -0
- package/src/plugins.js +139 -0
- package/src/server.js +199 -0
- package/test/fixtures/index.js +131 -0
- package/test/fixtures/iso.js +110 -0
- package/test/integration/.env +8 -0
- package/test/integration/api/parties.test.js +137 -0
- package/test/integration/constants.js +20 -0
- package/test/integration/domain/oracle/index.test.js +324 -0
- package/test/integration/domain/timeout/index.test.js +75 -0
- package/test/integration/env.sh +15 -0
- package/test/integration/example.test.js +12 -0
- package/test/integration/models/currency/currency.test.js +68 -0
- package/test/integration/plugins.test.js +62 -0
- package/test/integration/prepareTestParticipants.js +30 -0
- package/test/integration/setup.js +5 -0
- package/test/integration-config.json +81 -0
- package/test/integration-runner.sh +108 -0
- package/test/unit/api/health.test.js +142 -0
- package/test/unit/api/oracles/{ID}.test.js +264 -0
- package/test/unit/api/oracles.test.js +173 -0
- package/test/unit/api/participants/participants.test.js +117 -0
- package/test/unit/api/participants/{Type}/{ID}/error.test.js +155 -0
- package/test/unit/api/participants/{Type}/{ID}/{SubId}/error.test.js +131 -0
- package/test/unit/api/participants/{Type}/{ID}/{SubId}.test.js +377 -0
- package/test/unit/api/participants/{Type}/{ID}.test.js +383 -0
- package/test/unit/api/participants.test.js +108 -0
- package/test/unit/api/parties/endpointcache.test.js +83 -0
- package/test/unit/api/parties/parties.test.js +102 -0
- package/test/unit/api/parties/{Type}/{ID}/error.test.js +145 -0
- package/test/unit/api/parties/{Type}/{ID}/{SubId}/error.test.js +141 -0
- package/test/unit/api/parties/{Type}/{ID}/{SubId}.test.js +241 -0
- package/test/unit/api/parties/{Type}/{ID}.test.js +240 -0
- package/test/unit/domain/oracle/oracle.test.js +505 -0
- package/test/unit/domain/participants/participants.test.js +1724 -0
- package/test/unit/domain/parties/parties.test.js +940 -0
- package/test/unit/domain/timeout/dto.test.js +28 -0
- package/test/unit/domain/timeout/index.test.js +81 -0
- package/test/unit/handlers/TimeoutHandler.test.js +125 -0
- package/test/unit/handlers/index.test.js +56 -0
- package/test/unit/handlers/register.test.js +90 -0
- package/test/unit/index.test.js +139 -0
- package/test/unit/iso20022/partiesValidation.test.js +129 -0
- package/test/unit/lib/TransformFacades.test.js +18 -0
- package/test/unit/lib/argv.test.js +40 -0
- package/test/unit/lib/cache.test.js +172 -0
- package/test/unit/lib/config.test.js +108 -0
- package/test/unit/lib/healthCheck/subServiceHealth.test.js +89 -0
- package/test/unit/lib/migrator.test.js +52 -0
- package/test/unit/lib/requestLogger.test.js +115 -0
- package/test/unit/lib/util.test.js +68 -0
- package/test/unit/mocks.js +66 -0
- package/test/unit/models/currency/currency.test.js +91 -0
- package/test/unit/models/endpointType/endpointType.test.js +69 -0
- package/test/unit/models/misc/migrationLock.test.js +96 -0
- package/test/unit/models/oracle/facade.test.js +546 -0
- package/test/unit/models/oracle/oracleEndpoint.test.js +409 -0
- package/test/unit/models/oracle/oracleEndpointCached.test.js +153 -0
- package/test/unit/models/participantEndpoint/facade.test.js +295 -0
- package/test/unit/models/partyIdType/partyIdType.test.js +88 -0
- package/test/unit/plugins.test.js +89 -0
- package/test/unit/setup.js +7 -0
- package/test/util/apiClients/AlsApiClient.js +44 -0
- package/test/util/apiClients/BasicApiClient.js +34 -0
- package/test/util/apiClients/ProxyApiClient.js +25 -0
- package/test/util/apiClients/index.js +7 -0
- package/test/util/helper.js +332 -0
- package/test/util/index.js +11 -0
- package/test/util/mockgen.js +43 -0
- package/test/util/onboarding.js +132 -0
- package/test/util/scripts/addAlsDb.sh +33 -0
- package/test/util/scripts/configureMockServer.sh +35 -0
- package/test/util/scripts/env.sh +19 -0
- package/test/util/scripts/populateTestData.sh +62 -0
- package/test/util/scripts/startMockCentralServer.sh +45 -0
- package/test/util/scripts/startMockOracleServer.sh +45 -0
- package/test/util/testConfig.js +44 -0
@@ -0,0 +1,239 @@
|
|
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
|
+
|
9
|
+
Contributors
|
10
|
+
--------------
|
11
|
+
This is the official list of the Mojaloop project contributors for this file.
|
12
|
+
Names of the original copyright holders (individuals or organizations)
|
13
|
+
should be listed with a '*' in the first column. People who have
|
14
|
+
contributed from an organization can be listed under the organization
|
15
|
+
that actually holds the copyright for their contributions (see the
|
16
|
+
Gates Foundation organization for an example). Those individuals should have
|
17
|
+
their names indented and be marked with a '-'. Email address can be added
|
18
|
+
optionally within square brackets <email>.
|
19
|
+
* Gates Foundation
|
20
|
+
- Name Surname <name.surname@gatesfoundation.com>
|
21
|
+
|
22
|
+
* Eugen Klymniuk <eugen.klymniuk@infitx.com>
|
23
|
+
--------------
|
24
|
+
**********/
|
25
|
+
|
26
|
+
const { Enum, Util } = require('@mojaloop/central-services-shared')
|
27
|
+
const ErrorHandler = require('@mojaloop/central-services-error-handling')
|
28
|
+
const Metrics = require('@mojaloop/central-services-metrics')
|
29
|
+
|
30
|
+
const config = require('../../lib/config')
|
31
|
+
const oracle = require('../../models/oracle/facade')
|
32
|
+
const participant = require('../../models/participantEndpoint/facade')
|
33
|
+
const { createCallbackHeaders } = require('../../lib/headers')
|
34
|
+
const { ERROR_MESSAGES } = require('../../constants')
|
35
|
+
const { loggerFactory } = require('../../lib')
|
36
|
+
const Config = require('../../lib/config')
|
37
|
+
const utils = require('./utils')
|
38
|
+
|
39
|
+
const { FspEndpointTypes, FspEndpointTemplates } = Enum.EndPoints
|
40
|
+
const { Headers, RestMethods } = Enum.Http
|
41
|
+
|
42
|
+
const logger = loggerFactory('domain:get-parties')
|
43
|
+
|
44
|
+
const proxyCacheTtlSec = 40 // todo: make configurable
|
45
|
+
|
46
|
+
const validateRequester = async ({ source, proxy, proxyCache }) => {
|
47
|
+
const sourceParticipant = await participant.validateParticipant(source)
|
48
|
+
if (sourceParticipant) {
|
49
|
+
logger.debug('source is in scheme', { source })
|
50
|
+
return source
|
51
|
+
}
|
52
|
+
|
53
|
+
if (!proxy) {
|
54
|
+
const errMessage = ERROR_MESSAGES.partySourceFspNotFound
|
55
|
+
throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, errMessage)
|
56
|
+
}
|
57
|
+
|
58
|
+
const proxyParticipant = await participant.validateParticipant(proxy)
|
59
|
+
if (!proxyParticipant) {
|
60
|
+
const errMessage = ERROR_MESSAGES.partyProxyNotFound
|
61
|
+
throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, errMessage)
|
62
|
+
}
|
63
|
+
|
64
|
+
const isCached = await proxyCache.addDfspIdToProxyMapping(source, proxy)
|
65
|
+
// think, what if isCached !== true?
|
66
|
+
logger.info('source is added to proxyMapping cache:', { source, proxy, isCached })
|
67
|
+
return proxy
|
68
|
+
}
|
69
|
+
|
70
|
+
/**
|
71
|
+
* @function getPartiesByTypeAndID
|
72
|
+
*
|
73
|
+
* @description sends request to applicable oracle based on type and sends results to a callback url
|
74
|
+
*
|
75
|
+
* @param {object} headers - incoming http request headers
|
76
|
+
* @param {object} params - uri parameters of the http request
|
77
|
+
* @param {string} method - http request method
|
78
|
+
* @param {object} query - uri query parameters of the http request
|
79
|
+
* @param {object} span
|
80
|
+
* @param {object} cache
|
81
|
+
* @param {IProxyCache} [proxyCache] - IProxyCache instance
|
82
|
+
*/
|
83
|
+
const getPartiesByTypeAndID = async (headers, params, method, query, span, cache, proxyCache = undefined) => {
|
84
|
+
const histTimerEnd = Metrics.getHistogram(
|
85
|
+
'getPartiesByTypeAndID',
|
86
|
+
'Get party by Type and Id',
|
87
|
+
['success']
|
88
|
+
).startTimer()
|
89
|
+
const proxyEnabled = !!(Config.PROXY_CACHE_CONFIG.enabled && proxyCache)
|
90
|
+
const type = params.Type
|
91
|
+
const partySubId = params.SubId
|
92
|
+
const source = headers[Headers.FSPIOP.SOURCE]
|
93
|
+
const proxy = proxyEnabled && headers[Headers.FSPIOP.PROXY]
|
94
|
+
const callbackEndpointType = utils.getPartyCbType(partySubId)
|
95
|
+
|
96
|
+
const childSpan = span ? span.getChild('getPartiesByTypeAndID') : undefined
|
97
|
+
logger.info('parties::getPartiesByTypeAndID::begin', { source, proxy, params })
|
98
|
+
|
99
|
+
let requester
|
100
|
+
let fspiopError
|
101
|
+
|
102
|
+
try {
|
103
|
+
requester = await validateRequester({ source, proxy, proxyCache })
|
104
|
+
|
105
|
+
const options = {
|
106
|
+
partyIdType: type,
|
107
|
+
partyIdentifier: params.ID,
|
108
|
+
...(partySubId && { partySubIdOrType: partySubId })
|
109
|
+
}
|
110
|
+
|
111
|
+
let destination = headers[Headers.FSPIOP.DESTINATION]
|
112
|
+
// see https://github.com/mojaloop/design-authority/issues/79
|
113
|
+
// the requester has specified a destination routing header. We should respect that and forward the request directly to the destination
|
114
|
+
// without consulting any oracles.
|
115
|
+
if (destination) {
|
116
|
+
const destParticipantModel = await participant.validateParticipant(destination)
|
117
|
+
if (!destParticipantModel) {
|
118
|
+
const proxyId = proxyEnabled && await proxyCache.lookupProxyByDfspId(destination)
|
119
|
+
|
120
|
+
if (!proxyId) {
|
121
|
+
const errMessage = ERROR_MESSAGES.partyDestinationFspNotFound
|
122
|
+
throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, errMessage)
|
123
|
+
}
|
124
|
+
destination = proxyId
|
125
|
+
}
|
126
|
+
// all ok, go ahead and forward the request
|
127
|
+
await participant.sendRequest(headers, destination, callbackEndpointType, RestMethods.GET, undefined, options, childSpan)
|
128
|
+
|
129
|
+
histTimerEnd({ success: true })
|
130
|
+
logger.info('discovery getPartiesByTypeAndID request was sent to destination', { destination })
|
131
|
+
return
|
132
|
+
}
|
133
|
+
|
134
|
+
const response = await oracle.oracleRequest(headers, method, params, query, undefined, cache)
|
135
|
+
if (Array.isArray(response?.data?.partyList) && response.data.partyList.length > 0) {
|
136
|
+
// Oracle's API is a standard rest-style end-point Thus a GET /party on the oracle will return all participant-party records. We must filter the results based on the callbackEndpointType to make sure we remove records containing partySubIdOrType when we are in FSPIOP_CALLBACK_URL_PARTIES_GET mode:
|
137
|
+
let filteredResponsePartyList
|
138
|
+
switch (callbackEndpointType) {
|
139
|
+
case FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTIES_GET:
|
140
|
+
filteredResponsePartyList = response.data.partyList.filter(party => party.partySubIdOrType == null) // Filter records that DON'T contain a partySubIdOrType
|
141
|
+
break
|
142
|
+
case FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTIES_SUB_ID_GET:
|
143
|
+
filteredResponsePartyList = response.data.partyList.filter(party => party.partySubIdOrType === partySubId) // Filter records that match partySubIdOrType
|
144
|
+
break
|
145
|
+
default:
|
146
|
+
filteredResponsePartyList = response // Fallback to providing the standard list
|
147
|
+
}
|
148
|
+
|
149
|
+
if (!Array.isArray(filteredResponsePartyList) || !filteredResponsePartyList.length) {
|
150
|
+
const errMessage = 'Requested FSP/Party not found'
|
151
|
+
throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, errMessage)
|
152
|
+
}
|
153
|
+
|
154
|
+
let sentCount = 0 // if sentCount === 0 after sending, should we restart the whole process?
|
155
|
+
const sending = filteredResponsePartyList.map(async party => {
|
156
|
+
const { fspId } = party
|
157
|
+
const clonedHeaders = { ...headers }
|
158
|
+
if (!destination) {
|
159
|
+
clonedHeaders[Headers.FSPIOP.DESTINATION] = fspId
|
160
|
+
}
|
161
|
+
const schemeParticipant = await participant.validateParticipant(fspId)
|
162
|
+
if (schemeParticipant) {
|
163
|
+
sentCount++
|
164
|
+
logger.debug('participant is in scheme', { fspId })
|
165
|
+
return participant.sendRequest(clonedHeaders, party.fspId, callbackEndpointType, RestMethods.GET, undefined, options, childSpan)
|
166
|
+
}
|
167
|
+
|
168
|
+
// If the participant is not in the scheme and proxy routing is enabled,
|
169
|
+
// we should check if there is a proxy for it and send the request to the proxy
|
170
|
+
if (proxyEnabled) {
|
171
|
+
const proxyName = await proxyCache.lookupProxyByDfspId(fspId)
|
172
|
+
if (!proxyName) {
|
173
|
+
logger.warn('no proxyMapping for participant! TODO: Delete reference in oracle...', { fspId })
|
174
|
+
// todo: delete reference in oracle
|
175
|
+
} else {
|
176
|
+
sentCount++
|
177
|
+
logger.debug('participant NOT is in scheme, use proxy name', { fspId, proxyName })
|
178
|
+
return participant.sendRequest(clonedHeaders, proxyName, callbackEndpointType, RestMethods.GET, undefined, options, childSpan)
|
179
|
+
}
|
180
|
+
}
|
181
|
+
})
|
182
|
+
await Promise.all(sending)
|
183
|
+
logger.info('participant.sendRequests to filtered oracle partyList are done', { sentCount })
|
184
|
+
// todo: think what if sentCount === 0 here
|
185
|
+
} else {
|
186
|
+
logger.info('empty partyList form oracle, getting proxies list...', { proxyEnabled, params })
|
187
|
+
let filteredProxyNames = []
|
188
|
+
|
189
|
+
if (proxyEnabled) {
|
190
|
+
const proxyNames = await Util.proxies.getAllProxiesNames(Config.SWITCH_ENDPOINT)
|
191
|
+
filteredProxyNames = proxyNames.filter(name => name !== proxy)
|
192
|
+
}
|
193
|
+
|
194
|
+
if (!filteredProxyNames.length) {
|
195
|
+
const callbackHeaders = createCallbackHeaders({
|
196
|
+
requestHeaders: headers,
|
197
|
+
partyIdType: type,
|
198
|
+
partyIdentifier: params.ID,
|
199
|
+
endpointTemplate: partySubId
|
200
|
+
? FspEndpointTemplates.PARTIES_SUB_ID_PUT_ERROR
|
201
|
+
: FspEndpointTemplates.PARTIES_PUT_ERROR
|
202
|
+
})
|
203
|
+
fspiopError = ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.PARTY_NOT_FOUND)
|
204
|
+
const errorCallbackEndpointType = utils.errorPartyCbType(partySubId)
|
205
|
+
await participant.sendErrorToParticipant(requester, errorCallbackEndpointType,
|
206
|
+
fspiopError.toApiErrorObject(config.ERROR_HANDLING), callbackHeaders, params, childSpan)
|
207
|
+
} else {
|
208
|
+
const alsReq = utils.alsRequestDto(source, params)
|
209
|
+
logger.info('starting setSendToProxiesList flow: ', { filteredProxyNames, alsReq, proxyCacheTtlSec })
|
210
|
+
const isCached = await proxyCache.setSendToProxiesList(alsReq, filteredProxyNames, proxyCacheTtlSec)
|
211
|
+
if (!isCached) {
|
212
|
+
throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, ERROR_MESSAGES.failedToCacheSendToProxiesList)
|
213
|
+
}
|
214
|
+
|
215
|
+
const sending = filteredProxyNames.map(
|
216
|
+
proxyName => participant.sendRequest(headers, proxyName, callbackEndpointType, RestMethods.GET, undefined, options, childSpan)
|
217
|
+
.then(({ status, data } = {}) => ({ status, data }))
|
218
|
+
)
|
219
|
+
const results = await Promise.allSettled(sending)
|
220
|
+
const isOk = results.some(result => result.status === 'fulfilled')
|
221
|
+
// If, at least, one request is sent to proxy, we treat the whole flow as successful.
|
222
|
+
// Failed requests should be handled by TTL expired/timeout handler
|
223
|
+
// todo: - think, if we should handle failed requests here (e.g., by calling receivedErrorResponse)
|
224
|
+
logger.info('setSendToProxiesList flow is done:', { isOk, results, filteredProxyNames, alsReq })
|
225
|
+
if (!isOk) {
|
226
|
+
throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, ERROR_MESSAGES.proxyConnectionError)
|
227
|
+
}
|
228
|
+
}
|
229
|
+
}
|
230
|
+
histTimerEnd({ success: true })
|
231
|
+
} catch (err) {
|
232
|
+
fspiopError = await utils.handleErrorOnSendingCallback(err, headers, params, requester)
|
233
|
+
histTimerEnd({ success: false })
|
234
|
+
} finally {
|
235
|
+
await utils.finishSpanWithError(childSpan, fspiopError)
|
236
|
+
}
|
237
|
+
}
|
238
|
+
|
239
|
+
module.exports = getPartiesByTypeAndID
|
@@ -0,0 +1,32 @@
|
|
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 parties = require('./parties')
|
29
|
+
|
30
|
+
exports.getPartiesByTypeAndID = parties.getPartiesByTypeAndID
|
31
|
+
exports.putPartiesByTypeAndID = parties.putPartiesByTypeAndID
|
32
|
+
exports.putPartiesErrorByTypeAndID = parties.putPartiesErrorByTypeAndID
|
@@ -0,0 +1,215 @@
|
|
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
|
+
- Henk Kodde <henk.kodde@modusbox.com>
|
23
|
+
- Steven Oderayi <steven.oderayi@modusbox.com>
|
24
|
+
- Juan Correa <juan.correa@modusbox.com>
|
25
|
+
- James Bush <james.bush@modusbox.com>
|
26
|
+
|
27
|
+
--------------
|
28
|
+
******/
|
29
|
+
|
30
|
+
'use strict'
|
31
|
+
|
32
|
+
const { Headers, RestMethods } = require('@mojaloop/central-services-shared').Enum.Http
|
33
|
+
const { decodePayload } = require('@mojaloop/central-services-shared').Util.StreamingProtocol
|
34
|
+
const { MojaloopApiErrorCodes } = require('@mojaloop/sdk-standard-components').Errors
|
35
|
+
const ErrorHandler = require('@mojaloop/central-services-error-handling')
|
36
|
+
const Metrics = require('@mojaloop/central-services-metrics')
|
37
|
+
|
38
|
+
const oracle = require('../../models/oracle/facade')
|
39
|
+
const participant = require('../../models/participantEndpoint/facade')
|
40
|
+
const { ERROR_MESSAGES } = require('../../constants')
|
41
|
+
const { loggerFactory } = require('../../lib')
|
42
|
+
const Config = require('../../lib/config')
|
43
|
+
const utils = require('./utils')
|
44
|
+
const getPartiesByTypeAndID = require('./getPartiesByTypeAndID')
|
45
|
+
|
46
|
+
const logger = loggerFactory('domain:put-parties')
|
47
|
+
|
48
|
+
/**
|
49
|
+
* @function putPartiesByTypeAndID
|
50
|
+
*
|
51
|
+
* @description This sends a callback to inform participant of successful lookup
|
52
|
+
*
|
53
|
+
* @param {object} headers - incoming http request headers
|
54
|
+
* @param {object} params - uri parameters of the http request
|
55
|
+
* @param {string} method - http request method
|
56
|
+
* @param {object} payload - payload of the request being sent out
|
57
|
+
* @param {string} dataUri - encoded payload of the request being sent out
|
58
|
+
* @param {CacheClient} cache - in-memory cache with CatboxMemory engine
|
59
|
+
* @param {IProxyCache} [proxyCache] - IProxyCache instance
|
60
|
+
*/
|
61
|
+
const putPartiesByTypeAndID = async (headers, params, method, payload, dataUri, cache, proxyCache = undefined) => {
|
62
|
+
const histTimerEnd = Metrics.getHistogram(
|
63
|
+
'putPartiesByTypeAndID',
|
64
|
+
'Put parties by type and id',
|
65
|
+
['success']
|
66
|
+
).startTimer()
|
67
|
+
const type = params.Type
|
68
|
+
const partySubId = params.SubId
|
69
|
+
const source = headers[Headers.FSPIOP.SOURCE]
|
70
|
+
const destination = headers[Headers.FSPIOP.DESTINATION]
|
71
|
+
const proxy = headers[Headers.FSPIOP.PROXY]
|
72
|
+
const proxyEnabled = !!(Config.PROXY_CACHE_CONFIG.enabled && proxyCache)
|
73
|
+
logger.info('parties::putPartiesByTypeAndID::begin', { source, destination, proxy, params })
|
74
|
+
|
75
|
+
let sendTo
|
76
|
+
try {
|
77
|
+
const requesterParticipant = await participant.validateParticipant(source)
|
78
|
+
if (!requesterParticipant) {
|
79
|
+
if (!proxyEnabled || !proxy) {
|
80
|
+
const errMessage = ERROR_MESSAGES.partySourceFspNotFound
|
81
|
+
throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, errMessage)
|
82
|
+
}
|
83
|
+
const isCached = await proxyCache.addDfspIdToProxyMapping(source, proxy)
|
84
|
+
// think,if we should throw error if isCached === false?
|
85
|
+
logger.info('addDfspIdToProxyMapping is done', { source, proxy, isCached })
|
86
|
+
}
|
87
|
+
|
88
|
+
if (proxyEnabled && proxy) {
|
89
|
+
const alsReq = utils.alsRequestDto(destination, params) // or source?
|
90
|
+
const isExists = await proxyCache.receivedSuccessResponse(alsReq)
|
91
|
+
if (!isExists) {
|
92
|
+
logger.warn('destination is NOT in scheme, and no cached sendToProxiesList', { destination, alsReq })
|
93
|
+
// think, if we need to throw an error here
|
94
|
+
} else {
|
95
|
+
const mappingPayload = {
|
96
|
+
fspId: source
|
97
|
+
}
|
98
|
+
await oracle.oracleRequest(headers, RestMethods.POST, params, null, mappingPayload, cache)
|
99
|
+
logger.info('oracle was updated with mappingPayload', { mappingPayload, params })
|
100
|
+
}
|
101
|
+
}
|
102
|
+
|
103
|
+
const destinationParticipant = await participant.validateParticipant(destination)
|
104
|
+
if (!destinationParticipant) {
|
105
|
+
const proxyName = proxyEnabled && await proxyCache.lookupProxyByDfspId(destination)
|
106
|
+
if (!proxyName) {
|
107
|
+
const errMessage = ERROR_MESSAGES.partyDestinationFspNotFound
|
108
|
+
throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.DESTINATION_FSP_ERROR, errMessage)
|
109
|
+
}
|
110
|
+
sendTo = proxyName
|
111
|
+
} else {
|
112
|
+
sendTo = destinationParticipant.name
|
113
|
+
}
|
114
|
+
|
115
|
+
const decodedPayload = decodePayload(dataUri, { asParsed: false })
|
116
|
+
const callbackEndpointType = utils.putPartyCbType(partySubId)
|
117
|
+
const options = {
|
118
|
+
partyIdType: type,
|
119
|
+
partyIdentifier: params.ID,
|
120
|
+
...(partySubId && { partySubIdOrType: partySubId })
|
121
|
+
}
|
122
|
+
await participant.sendRequest(headers, sendTo, callbackEndpointType, RestMethods.PUT, decodedPayload.body.toString(), options)
|
123
|
+
|
124
|
+
logger.info('parties::putPartiesByTypeAndID::callback was sent', { sendTo, options })
|
125
|
+
histTimerEnd({ success: true })
|
126
|
+
} catch (err) {
|
127
|
+
await utils.handleErrorOnSendingCallback(err, headers, params, sendTo)
|
128
|
+
histTimerEnd({ success: false })
|
129
|
+
}
|
130
|
+
}
|
131
|
+
|
132
|
+
/**
|
133
|
+
* @function putPartiesErrorByTypeAndID
|
134
|
+
*
|
135
|
+
* @description This populates the cache of endpoints
|
136
|
+
*
|
137
|
+
* @param {object} headers - incoming http request headers
|
138
|
+
* @param {object} params - uri parameters of the http request
|
139
|
+
* @param {object} payload - payload of the request being sent out
|
140
|
+
* @param {string} dataUri - encoded payload of the request being sent out
|
141
|
+
* @param {object} span
|
142
|
+
* @param {CacheClient} cache - in-memory cache with CatboxMemory engine
|
143
|
+
* @param {IProxyCache} [proxyCache] - IProxyCache instance
|
144
|
+
*/
|
145
|
+
const putPartiesErrorByTypeAndID = async (headers, params, payload, dataUri, span, cache, proxyCache = undefined) => {
|
146
|
+
const histTimerEnd = Metrics.getHistogram(
|
147
|
+
'putPartiesErrorByTypeAndID',
|
148
|
+
'Put parties error by type and id',
|
149
|
+
['success']
|
150
|
+
).startTimer()
|
151
|
+
const partySubId = params.SubId
|
152
|
+
const destination = headers[Headers.FSPIOP.DESTINATION]
|
153
|
+
const callbackEndpointType = utils.errorPartyCbType(partySubId)
|
154
|
+
const proxyEnabled = !!(Config.PROXY_CACHE_CONFIG.enabled && proxyCache)
|
155
|
+
|
156
|
+
const childSpan = span ? span.getChild('putPartiesErrorByTypeAndID') : undefined
|
157
|
+
|
158
|
+
let sendTo
|
159
|
+
let fspiopError
|
160
|
+
|
161
|
+
try {
|
162
|
+
const proxy = proxyEnabled && headers[Headers.FSPIOP.PROXY]
|
163
|
+
if (proxy) {
|
164
|
+
if (isNotValidPayeeCase(payload)) {
|
165
|
+
const swappedHeaders = utils.swapSourceDestinationHeaders(headers)
|
166
|
+
await oracle.oracleRequest(swappedHeaders, RestMethods.DELETE, params, null, null, cache)
|
167
|
+
getPartiesByTypeAndID(swappedHeaders, params, RestMethods.GET, {}, span, cache, proxyCache)
|
168
|
+
// todo: - think if we need to send errorCallback?
|
169
|
+
// - or sentCallback after getPartiesByTypeAndID is done
|
170
|
+
logger.info('notValidPayee case - deleted Participants and run getPartiesByTypeAndID:', { proxy, params, payload })
|
171
|
+
return
|
172
|
+
}
|
173
|
+
|
174
|
+
const alsReq = utils.alsRequestDto(destination, params) // or source?
|
175
|
+
const isLast = await proxyCache.receivedErrorResponse(alsReq, proxy)
|
176
|
+
if (!isLast) {
|
177
|
+
logger.info('got NOT last error callback from proxy:', { proxy, alsReq })
|
178
|
+
return
|
179
|
+
}
|
180
|
+
}
|
181
|
+
|
182
|
+
const destinationParticipant = await participant.validateParticipant(destination)
|
183
|
+
|
184
|
+
if (destinationParticipant) {
|
185
|
+
sendTo = destination
|
186
|
+
} else {
|
187
|
+
const proxyName = proxyEnabled && await proxyCache.lookupProxyByDfspId(destination)
|
188
|
+
if (!proxyName) {
|
189
|
+
const errMessage = ERROR_MESSAGES.partyDestinationFspNotFound
|
190
|
+
throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.DESTINATION_FSP_ERROR, errMessage)
|
191
|
+
}
|
192
|
+
sendTo = proxyName
|
193
|
+
}
|
194
|
+
const decodedPayload = decodePayload(dataUri, { asParsed: false })
|
195
|
+
await participant.sendErrorToParticipant(sendTo, callbackEndpointType, decodedPayload.body.toString(), headers, params, childSpan)
|
196
|
+
|
197
|
+
logger.info('putPartiesErrorByTypeAndID callback was sent', { sendTo })
|
198
|
+
histTimerEnd({ success: true })
|
199
|
+
} catch (err) {
|
200
|
+
fspiopError = await utils.handleErrorOnSendingCallback(err, headers, params, sendTo)
|
201
|
+
histTimerEnd({ success: false })
|
202
|
+
} finally {
|
203
|
+
await utils.finishSpanWithError(childSpan, fspiopError)
|
204
|
+
}
|
205
|
+
}
|
206
|
+
|
207
|
+
function isNotValidPayeeCase (payload) {
|
208
|
+
return payload?.errorInformation?.errorCode === MojaloopApiErrorCodes.PAYEE_IDENTIFIER_NOT_VALID.code
|
209
|
+
}
|
210
|
+
|
211
|
+
module.exports = {
|
212
|
+
getPartiesByTypeAndID,
|
213
|
+
putPartiesByTypeAndID,
|
214
|
+
putPartiesErrorByTypeAndID
|
215
|
+
}
|
@@ -0,0 +1,84 @@
|
|
1
|
+
const { Enum } = require('@mojaloop/central-services-shared')
|
2
|
+
const EventSdk = require('@mojaloop/event-sdk')
|
3
|
+
const ErrorHandler = require('@mojaloop/central-services-error-handling')
|
4
|
+
|
5
|
+
const participant = require('../../models/participantEndpoint/facade')
|
6
|
+
const Config = require('../../lib/config')
|
7
|
+
const { logger } = require('../../lib')
|
8
|
+
|
9
|
+
const { FspEndpointTypes } = Enum.EndPoints
|
10
|
+
const { Headers } = Enum.Http
|
11
|
+
|
12
|
+
const getPartyCbType = (partySubId) => partySubId
|
13
|
+
? FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTIES_SUB_ID_GET
|
14
|
+
: FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTIES_GET
|
15
|
+
|
16
|
+
const putPartyCbType = (partySubId) => partySubId
|
17
|
+
? FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTIES_SUB_ID_PUT
|
18
|
+
: FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTIES_PUT
|
19
|
+
|
20
|
+
const errorPartyCbType = (partySubId) => partySubId
|
21
|
+
? FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTIES_SUB_ID_PUT_ERROR
|
22
|
+
: FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTIES_PUT_ERROR
|
23
|
+
|
24
|
+
const finishSpanWithError = async (childSpan, fspiopError) => {
|
25
|
+
if (childSpan && !childSpan.isFinished) {
|
26
|
+
if (fspiopError) {
|
27
|
+
const state = new EventSdk.EventStateMetadata(EventSdk.EventStatusType.failed, fspiopError.apiErrorCode.code, fspiopError.apiErrorCode.message)
|
28
|
+
await childSpan.error(fspiopError, state)
|
29
|
+
await childSpan.finish(fspiopError.message, state)
|
30
|
+
} else {
|
31
|
+
await childSpan.finish()
|
32
|
+
}
|
33
|
+
}
|
34
|
+
}
|
35
|
+
|
36
|
+
const alsRequestDto = (sourceId, params) => ({
|
37
|
+
sourceId,
|
38
|
+
type: params.Type,
|
39
|
+
partyId: params.ID
|
40
|
+
})
|
41
|
+
|
42
|
+
const swapSourceDestinationHeaders = (headers) => {
|
43
|
+
const {
|
44
|
+
[Headers.FSPIOP.SOURCE]: source,
|
45
|
+
[Headers.FSPIOP.DESTINATION]: destination,
|
46
|
+
[Headers.FSPIOP.PROXY]: proxy,
|
47
|
+
...restHeaders
|
48
|
+
} = headers
|
49
|
+
return {
|
50
|
+
...restHeaders,
|
51
|
+
[Headers.FSPIOP.SOURCE]: destination,
|
52
|
+
[Headers.FSPIOP.DESTINATION]: source
|
53
|
+
}
|
54
|
+
}
|
55
|
+
|
56
|
+
// change signature to accept object
|
57
|
+
const handleErrorOnSendingCallback = async (err, headers, params, requester) => {
|
58
|
+
try {
|
59
|
+
logger.error('error in sending parties callback', err)
|
60
|
+
const sendTo = requester || headers[Headers.FSPIOP.SOURCE]
|
61
|
+
const errorCallbackEndpointType = errorPartyCbType(params.SubId)
|
62
|
+
const fspiopError = ErrorHandler.Factory.reformatFSPIOPError(err)
|
63
|
+
const errInfo = fspiopError.toApiErrorObject(Config.ERROR_HANDLING)
|
64
|
+
|
65
|
+
await participant.sendErrorToParticipant(sendTo, errorCallbackEndpointType, errInfo, headers, params)
|
66
|
+
|
67
|
+
logger.info('handleErrorOnSendingCallback in done', { sendTo, params, errInfo })
|
68
|
+
return fspiopError
|
69
|
+
} catch (exc) {
|
70
|
+
// We can't do anything else here- we _must_ handle all errors _within_ this function because
|
71
|
+
// we've already sent a sync response- we cannot throw.
|
72
|
+
logger.error('error in handleErrorOnSendingCallback', exc)
|
73
|
+
}
|
74
|
+
}
|
75
|
+
|
76
|
+
module.exports = {
|
77
|
+
getPartyCbType,
|
78
|
+
putPartyCbType,
|
79
|
+
errorPartyCbType,
|
80
|
+
finishSpanWithError,
|
81
|
+
handleErrorOnSendingCallback,
|
82
|
+
alsRequestDto,
|
83
|
+
swapSourceDestinationHeaders
|
84
|
+
}
|
@@ -0,0 +1,48 @@
|
|
1
|
+
const {
|
2
|
+
Factory: { createFSPIOPError },
|
3
|
+
Enums: { FSPIOPErrorCodes }
|
4
|
+
} = require('@mojaloop/central-services-error-handling')
|
5
|
+
const {
|
6
|
+
Http: { Headers: { FSPIOP: FSPIOPHeaders } },
|
7
|
+
Events: { Event: { Type: EventType, Action: EventAction } },
|
8
|
+
EndPoints: { FspEndpointTypes }
|
9
|
+
} = require('@mojaloop/central-services-shared').Enum
|
10
|
+
const { Tracer } = require('@mojaloop/event-sdk')
|
11
|
+
const { API_TYPES } = require('@mojaloop/central-services-shared').Util.Hapi
|
12
|
+
|
13
|
+
const { TransformFacades } = require('../../lib')
|
14
|
+
const LibUtil = require('../../lib/util')
|
15
|
+
const Config = require('../../lib/config')
|
16
|
+
|
17
|
+
const makeErrorPayload = async (headers, params) => {
|
18
|
+
const body = createFSPIOPError(FSPIOPErrorCodes.EXPIRED_ERROR).toApiErrorObject(Config.ERROR_HANDLING)
|
19
|
+
return Config.API_TYPE === API_TYPES.iso20022
|
20
|
+
? (await TransformFacades.FSPIOP.parties.putError({ body, headers, params })).body
|
21
|
+
: body
|
22
|
+
}
|
23
|
+
|
24
|
+
const timeoutCallbackDto = async ({ destination, partyId, partyType }) => {
|
25
|
+
const headers = {
|
26
|
+
[FSPIOPHeaders.SOURCE]: Config.HUB_NAME,
|
27
|
+
[FSPIOPHeaders.DESTINATION]: destination
|
28
|
+
}
|
29
|
+
const params = {
|
30
|
+
ID: partyId,
|
31
|
+
Type: partyType
|
32
|
+
}
|
33
|
+
const dto = {
|
34
|
+
errorInformation: await makeErrorPayload(headers, params),
|
35
|
+
headers,
|
36
|
+
params,
|
37
|
+
endpointType: FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTIES_PUT_ERROR
|
38
|
+
}
|
39
|
+
const span = Tracer.createSpan('timeoutInterschemePartiesLookups', { headers: dto.headers })
|
40
|
+
const spanTags = LibUtil.getSpanTags({ headers: dto.headers }, EventType.PARTY, EventAction.PUT)
|
41
|
+
span.setTags(spanTags)
|
42
|
+
|
43
|
+
return { ...dto, span }
|
44
|
+
}
|
45
|
+
|
46
|
+
module.exports = {
|
47
|
+
timeoutCallbackDto
|
48
|
+
}
|