account-lookup-service 17.6.0 → 17.7.0-snapshot.1

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.
@@ -25,207 +25,135 @@
25
25
  --------------
26
26
  ******/
27
27
 
28
- const ErrorHandler = require('@mojaloop/central-services-error-handling')
29
28
  const { ERROR_MESSAGES } = require('../../../constants')
30
- const { createCallbackHeaders } = require('../../../lib/headers')
31
29
  const BasePartiesService = require('./BasePartiesService')
32
30
 
33
- const {
34
- FspEndpointTypes, FspEndpointTemplates,
35
- Headers, RestMethods
36
- } = BasePartiesService.enums()
37
-
31
+ const { FspEndpointTypes, RestMethods } = BasePartiesService.enums()
38
32
  const proxyCacheTtlSec = 40 // todo: make configurable
39
33
 
40
34
  class GetPartiesService extends BasePartiesService {
41
- async handleRequest ({ headers, params, query, results }) {
42
- const source = headers[Headers.FSPIOP.SOURCE]
43
- const proxy = headers[Headers.FSPIOP.PROXY]
44
- const destination = headers[Headers.FSPIOP.DESTINATION]
35
+ async handleRequest () {
36
+ const { destination, source, proxy } = this.state
45
37
  // see https://github.com/mojaloop/design-authority/issues/79
46
38
  // the requester has specified a destination routing header. We should respect that and forward the request directly to the destination
47
39
  // without consulting any oracles.
48
- this.log.info('handling getParties request', { source, destination, proxy })
49
-
50
- const requester = await this.validateRequester({ source, proxy })
51
- results.requester = requester
40
+ this.log.info('handling getParties request...', { source, destination, proxy })
41
+ this.state.requester = await this.validateRequester()
52
42
 
53
43
  if (destination) {
54
- await this.forwardRequestToDestination({ destination, headers, params })
44
+ await this.forwardRequestToDestination()
55
45
  return
56
46
  }
57
- const response = await this.sendOracleDiscoveryRequest({ headers, params, query })
58
47
 
48
+ const response = await this.sendOracleDiscoveryRequest()
59
49
  if (Array.isArray(response?.data?.partyList) && response.data.partyList.length > 0) {
60
- const partyList = this.filterOraclePartyList({ response, params })
61
- await this.processOraclePartyList({ partyList, headers, params, destination })
62
- return
50
+ const isDone = await this.processOraclePartyListResponse(response)
51
+ if (isDone) return
63
52
  }
64
53
 
65
- this.log.info('empty partyList form oracle, getting proxyList...', { params })
66
- const proxyNames = await this.getFilteredProxyList(proxy)
67
-
68
- if (proxyNames.length) {
69
- await this.triggerSendToProxiesFlow({ proxyNames, headers, params, source })
70
- return
54
+ this.log.info('no forwarded requests for oracle partyList')
55
+ const fspiopError = await this.triggerInterSchemeDiscoveryFlow(this.inputs.headers)
56
+ if (fspiopError) {
57
+ this.state.fspiopError = fspiopError // todo: think, if we need this
71
58
  }
72
-
73
- results.fspiopError = await this.sendPartyNotFoundErrorCallback({ requester, headers, params })
74
59
  }
75
60
 
76
- async validateRequester ({ source, proxy }) {
77
- this.deps.stepState.inProgress('validateRequester-0')
61
+ async validateRequester () {
62
+ const { source, proxy, proxyEnabled } = this.state
78
63
  const log = this.log.child({ source, proxy, method: 'validateRequester' })
64
+ this.stepInProgress('validateRequester-0')
79
65
 
80
- const sourceParticipant = await this.validateParticipant(source)
81
- if (sourceParticipant) {
82
- log.debug('source is in scheme')
66
+ const schemeSource = await this.validateParticipant(source)
67
+ if (schemeSource) {
68
+ log.debug('source participant is in scheme')
83
69
  return source
84
70
  }
85
71
 
86
- if (!this.proxyEnabled || !proxy) {
87
- const errMessage = ERROR_MESSAGES.sourceFspNotFound
88
- log.warn(errMessage)
89
- throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, errMessage)
72
+ if (!proxyEnabled || !proxy) {
73
+ throw super.createFspiopIdNotFoundError(ERROR_MESSAGES.sourceFspNotFound, log)
90
74
  }
91
75
 
92
- const proxyParticipant = await this.validateParticipant(proxy)
93
- if (!proxyParticipant) {
94
- const errMessage = ERROR_MESSAGES.partyProxyNotFound
95
- log.warn(errMessage)
96
- throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, errMessage)
76
+ const schemeProxy = await this.validateParticipant(proxy)
77
+ if (!schemeProxy) {
78
+ throw super.createFspiopIdNotFoundError(ERROR_MESSAGES.partyProxyNotFound, log)
97
79
  }
98
80
 
99
81
  const isCached = await this.deps.proxyCache.addDfspIdToProxyMapping(source, proxy)
100
82
  if (!isCached) {
101
- const errMessage = 'failed to addDfspIdToProxyMapping'
102
- log.warn(errMessage)
103
- throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, errMessage)
83
+ throw super.createFspiopIdNotFoundError('failed to addDfspIdToProxyMapping', log)
104
84
  }
105
85
 
106
- log.info('source is added to proxyMapping cache:', { proxy, isCached })
86
+ log.info('source is added to proxyMapping cache')
107
87
  return proxy
108
88
  }
109
89
 
110
- async forwardRequestToDestination ({ destination, headers, params }) {
111
- this.deps.stepState.inProgress('validateDestination-1')
90
+ async forwardRequestToDestination () {
91
+ const { headers, params } = this.inputs
92
+ const { destination } = this.state
112
93
  const log = this.log.child({ method: 'forwardRequestToDestination' })
113
94
  let sendTo = destination
114
95
 
115
- const destParticipantModel = await this.validateParticipant(destination)
116
- if (!destParticipantModel) {
117
- this.deps.stepState.inProgress('lookupProxyDestination-2')
118
- const proxyId = this.proxyEnabled && await this.deps.proxyCache.lookupProxyByDfspId(destination)
96
+ const schemeParticipant = await this.validateParticipant(destination)
97
+ if (!schemeParticipant) {
98
+ this.stepInProgress('lookupProxyDestination-2')
99
+ const proxyId = this.state.proxyEnabled && await this.deps.proxyCache.lookupProxyByDfspId(destination)
119
100
 
120
101
  if (!proxyId) {
121
- log.warn('no destination participant, and no dfsp-to-proxy mapping', { destination })
122
- const errMessage = ERROR_MESSAGES.partyDestinationFspNotFound
123
- throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, errMessage)
102
+ log.warn('destination participant is not in scheme, and no dfsp-to-proxy mapping', { destination })
103
+ await super.sendDeleteOracleRequest(headers, params)
104
+ await this.triggerInterSchemeDiscoveryFlow(GetPartiesService.headersWithoutDestination(headers))
105
+ return
124
106
  }
125
107
  sendTo = proxyId
126
108
  }
127
- // all ok, go ahead and forward the request
109
+
128
110
  await this.#forwardGetPartiesRequest({ sendTo, headers, params })
129
111
  log.info('discovery getPartiesByTypeAndID request was sent', { sendTo })
130
112
  }
131
113
 
132
- filterOraclePartyList ({ response, params }) {
133
- // 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:
134
- this.deps.stepState.inProgress('filterOraclePartyList-5')
135
- const callbackEndpointType = this.deps.partiesUtils.getPartyCbType(params.SubId)
136
- let filteredResponsePartyList
137
-
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 === params.SubId) // 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
- this.log.warn(errMessage)
152
- throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, errMessage)
153
- }
154
-
155
- return filteredResponsePartyList
114
+ async sendOracleDiscoveryRequest () {
115
+ this.stepInProgress('#sendOracleDiscoveryRequest')
116
+ const { headers, params, query } = this.inputs
117
+ return this.deps.oracle.oracleRequest(headers, RestMethods.GET, params, query, undefined, this.deps.cache)
156
118
  }
157
119
 
158
- async processOraclePartyList ({ partyList, headers, params, destination }) {
159
- const log = this.log.child({ method: 'processOraclePartyList' })
120
+ async processOraclePartyListResponse (response) {
121
+ this.stepInProgress('processOraclePartyList')
122
+ const partyList = this.#filterOraclePartyList(response)
160
123
 
161
- let sentCount = 0 // if sentCount === 0 after sending, should we restart the whole process?
162
- const sending = partyList.map(async party => {
163
- const { fspId } = party
164
- const clonedHeaders = { ...headers }
165
- if (!destination) {
166
- clonedHeaders[Headers.FSPIOP.DESTINATION] = fspId
167
- }
168
- this.deps.stepState.inProgress('validateParticipant-6')
169
- const schemeParticipant = await this.validateParticipant(fspId)
170
- if (schemeParticipant) {
171
- sentCount++
172
- log.info('participant is in scheme', { fspId })
173
- return this.#forwardGetPartiesRequest({
174
- sendTo: fspId,
175
- headers: clonedHeaders,
176
- params
177
- })
178
- }
124
+ let sentCount = 0
125
+ await Promise.all(partyList.map(async party => {
126
+ const isSent = await this.#processSingleOracleParty(party)
127
+ if (isSent) sentCount++
128
+ }))
179
129
 
180
- // If the participant is not in the scheme and proxy routing is enabled,
181
- // we should check if there is a proxy for it and send the request to the proxy
182
- if (this.proxyEnabled) {
183
- this.deps.stepState.inProgress('lookupProxyByDfspId-7')
184
- const proxyName = await this.deps.proxyCache.lookupProxyByDfspId(fspId)
185
- if (!proxyName) {
186
- log.warn('no proxyMapping for participant! TODO: Delete reference in oracle...', { fspId })
187
- // todo: delete reference in oracle
188
- } else {
189
- sentCount++
190
- log.info('participant is NOT in scheme, use proxy name', { fspId, proxyName })
191
- return this.#forwardGetPartiesRequest({
192
- sendTo: proxyName,
193
- headers: clonedHeaders,
194
- params
195
- })
196
- }
197
- }
198
- })
199
- await Promise.all(sending)
200
- log.verbose('processOraclePartyList is done', { sentCount })
201
- // todo: think what if sentCount === 0 here
130
+ const isDone = sentCount > 0
131
+ this.log.verbose('processOraclePartyList is done', { isDone, sentCount })
132
+ // if NOT isDone, need to trigger interScheme discovery flow
133
+ return isDone
202
134
  }
203
135
 
204
- async getFilteredProxyList (proxy) {
205
- this.deps.stepState.inProgress('getAllProxies-8')
206
- if (!this.proxyEnabled) {
207
- this.log.warn('proxyCache is not enabled')
208
- return []
209
- }
136
+ async triggerInterSchemeDiscoveryFlow (headers) {
137
+ const { params } = this.inputs
138
+ const { proxy, source } = this.state
139
+ const log = this.log.child({ method: 'triggerInterSchemeDiscoveryFlow' })
140
+ log.verbose('triggerInterSchemeDiscoveryFlow start...', { proxy, source })
210
141
 
211
- const proxyNames = await this.deps.proxies.getAllProxiesNames(this.deps.config.SWITCH_ENDPOINT)
212
- this.log.debug('getAllProxiesNames is done', { proxyNames })
213
- return proxyNames.filter(name => name !== proxy)
214
- }
142
+ const proxyNames = await this.#getFilteredProxyList(proxy)
143
+ if (!proxyNames.length) {
144
+ return this.#sendPartyNotFoundErrorCallback(headers)
145
+ }
215
146
 
216
- async triggerSendToProxiesFlow ({ proxyNames, headers, params, source }) {
217
- const log = this.log.child({ method: 'triggerSendToProxiesFlow' })
218
- this.deps.stepState.inProgress('setSendToProxiesList-10')
147
+ this.stepInProgress('setSendToProxiesList-10')
219
148
  const alsReq = this.deps.partiesUtils.alsRequestDto(source, params)
220
- log.info('starting setSendToProxiesList flow: ', { proxyNames, alsReq, proxyCacheTtlSec })
149
+ log.verbose('starting setSendToProxiesList flow: ', { proxyNames, alsReq, proxyCacheTtlSec })
221
150
 
222
151
  const isCached = await this.deps.proxyCache.setSendToProxiesList(alsReq, proxyNames, proxyCacheTtlSec)
223
152
  if (!isCached) {
224
- log.warn('failed to setSendToProxiesList')
225
- throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, ERROR_MESSAGES.failedToCacheSendToProxiesList)
153
+ throw super.createFspiopIdNotFoundError(ERROR_MESSAGES.failedToCacheSendToProxiesList, log)
226
154
  }
227
155
 
228
- this.deps.stepState.inProgress('sendingProxyRequests-11')
156
+ this.stepInProgress('sendingProxyRequests')
229
157
  const sending = proxyNames.map(
230
158
  sendTo => this.#forwardGetPartiesRequest({ sendTo, headers, params })
231
159
  .then(({ status, data } = {}) => ({ status, data }))
@@ -234,48 +162,146 @@ class GetPartiesService extends BasePartiesService {
234
162
  const isOk = results.some(result => result.status === 'fulfilled')
235
163
  // If, at least, one request is sent to proxy, we treat the whole flow as successful.
236
164
  // Failed requests should be handled by TTL expired/timeout handler
237
- // todo: - think, if we should handle failed requests here (e.g., by calling receivedErrorResponse)
238
- log.info('triggerSendToProxiesFlow is done:', { isOk, results, proxyNames, alsReq })
239
- this.deps.stepState.inProgress('allSent-12')
165
+ log.info('triggerInterSchemeDiscoveryFlow is done:', { isOk, results, proxyNames, alsReq })
166
+ this.stepInProgress('allSent-12')
167
+
240
168
  if (!isOk) {
241
- log.warn('no successful requests sent to proxies')
242
- throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, ERROR_MESSAGES.proxyConnectionError)
169
+ throw super.createFspiopIdNotFoundError(ERROR_MESSAGES.proxyConnectionError, log)
243
170
  }
244
171
  }
245
172
 
246
- async sendPartyNotFoundErrorCallback ({ requester, headers, params }) {
247
- this.deps.stepState.inProgress('sendErrorCallback-9')
248
- const callbackHeaders = createCallbackHeaders({
249
- requestHeaders: headers,
250
- partyIdType: params.Type,
251
- partyIdentifier: params.ID,
252
- endpointTemplate: params.SubId
253
- ? FspEndpointTemplates.PARTIES_SUB_ID_PUT_ERROR
254
- : FspEndpointTemplates.PARTIES_PUT_ERROR
255
- })
256
- const fspiopError = ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.PARTY_NOT_FOUND)
173
+ isLocalSource () {
174
+ const isLocal = this.state.source === this.state.requester
175
+ this.log.debug(`isLocalSource: ${isLocal}`)
176
+ return isLocal
177
+ }
178
+
179
+ #filterOraclePartyList (response) {
180
+ // Oracle's API is a standard rest-style end-point Thus a GET /party on the oracle will return all participant-party records.
181
+ // 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:
182
+ this.stepInProgress('filterOraclePartyList')
183
+ const { params } = this.inputs
184
+ const callbackEndpointType = this.deps.partiesUtils.getPartyCbType(params.SubId)
185
+ let filteredPartyList
186
+
187
+ switch (callbackEndpointType) {
188
+ case FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTIES_GET:
189
+ filteredPartyList = response.data.partyList.filter(party => party.partySubIdOrType == null) // Filter records that DON'T contain a partySubIdOrType
190
+ break
191
+ case FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTIES_SUB_ID_GET:
192
+ filteredPartyList = response.data.partyList.filter(party => party.partySubIdOrType === params.SubId) // Filter records that match partySubIdOrType
193
+ break
194
+ default:
195
+ filteredPartyList = response // Fallback to providing the standard list
196
+ }
197
+
198
+ if (!Array.isArray(filteredPartyList) || !filteredPartyList.length) {
199
+ throw super.createFspiopIdNotFoundError(ERROR_MESSAGES.emptyFilteredPartyList)
200
+ }
201
+
202
+ return filteredPartyList
203
+ }
204
+
205
+ /** @returns {Promise<boolean>} - is request forwarded to participant */
206
+ async #processSingleOracleParty (party) {
207
+ const { headers, params } = this.inputs
208
+ const { fspId } = party
209
+
210
+ const schemeParticipant = await this.validateParticipant(fspId)
211
+ if (schemeParticipant) {
212
+ this.log.info('participant is in scheme, so forwarding to it...', { fspId })
213
+ await this.#forwardGetPartiesRequest({
214
+ sendTo: fspId,
215
+ headers: GetPartiesService.overrideDestinationHeader(headers, fspId),
216
+ params
217
+ })
218
+ return true
219
+ }
220
+
221
+ if (this.state.proxyEnabled) {
222
+ const proxyName = await this.deps.proxyCache.lookupProxyByDfspId(fspId)
223
+ if (!proxyName) {
224
+ this.log.warn('no proxyMapping for external DFSP! Deleting reference in oracle...', { fspId })
225
+ await super.sendDeleteOracleRequest(headers, params)
226
+ // todo: check if it won't delete all parties
227
+ return false
228
+ }
229
+
230
+ // Coz there's no destination header, it means we're inside initial inter-scheme discovery phase.
231
+ // So we should proceed only if source is in scheme (local participant)
232
+ const isLocalSource = this.isLocalSource()
233
+ if (isLocalSource) {
234
+ this.log.info('participant is NOT in scheme, but source is. So forwarding to proxy...', { fspId, proxyName })
235
+ await this.#forwardGetPartiesRequest({ // todo: add timeout if sendTo is proxy
236
+ sendTo: proxyName,
237
+ headers: GetPartiesService.overrideDestinationHeader(headers, fspId),
238
+ params
239
+ })
240
+ return true
241
+ }
242
+ }
243
+ return false
244
+ }
245
+
246
+ async #sendPartyNotFoundErrorCallback (headers) {
247
+ const { params } = this.inputs
248
+ const fspiopError = super.createFspiopIdNotFoundError('No proxy found to start inter-scheme discovery flow')
257
249
 
258
250
  await this.sendErrorCallback({
259
- sendTo: requester,
260
251
  errorInfo: fspiopError.toApiErrorObject(this.deps.config.ERROR_HANDLING),
261
- headers: callbackHeaders,
252
+ headers: GetPartiesService.createErrorCallbackHeaders(headers, params),
262
253
  params
263
254
  })
264
255
  return fspiopError
265
256
  }
266
257
 
267
- async sendOracleDiscoveryRequest ({ headers, params, query }) {
268
- this.deps.stepState.inProgress('oracleRequest-4')
269
- return this.deps.oracle.oracleRequest(headers, RestMethods.GET, params, query, undefined, this.deps.cache)
270
- }
271
-
272
258
  async #forwardGetPartiesRequest ({ sendTo, headers, params }) {
273
- this.deps.stepState.inProgress('forwardRequest-3')
259
+ this.stepInProgress('#forwardGetPartiesRequest')
274
260
  const callbackEndpointType = this.deps.partiesUtils.getPartyCbType(params.SubId)
275
261
  const options = this.deps.partiesUtils.partiesRequestOptionsDto(params)
276
262
 
277
- return this.deps.participant.sendRequest(headers, sendTo, callbackEndpointType, RestMethods.GET, undefined, options, this.deps.childSpan)
263
+ const sentResult = await this.deps.participant.sendRequest(
264
+ headers, sendTo, callbackEndpointType, RestMethods.GET, undefined, options, this.deps.childSpan
265
+ )
266
+ await this.#setProxyGetPartiesTimeout(sendTo)
267
+ return sentResult
268
+ }
269
+
270
+ async #getFilteredProxyList (proxy) {
271
+ this.stepInProgress('#getFilteredProxyList')
272
+ if (!this.state.proxyEnabled) {
273
+ this.log.warn('proxyCache is not enabled')
274
+ return []
275
+ }
276
+
277
+ const proxyNames = await this.deps.proxies.getAllProxiesNames(this.deps.config.SWITCH_ENDPOINT)
278
+ this.log.debug('getAllProxiesNames is done', { proxyNames })
279
+ return proxyNames.filter(name => name !== proxy)
280
+ }
281
+
282
+ async #setProxyGetPartiesTimeout (sendTo) {
283
+ const isLocalSource = this.isLocalSource()
284
+ const isSentToProxy = this.state.destination !== sendTo
285
+ this.log.verbose('isLocalSource and isSentToProxy: ', { isLocalSource, isSentToProxy })
286
+
287
+ if (isSentToProxy && isLocalSource) {
288
+ this.stepInProgress('#setProxyGetPartiesTimeout')
289
+ const { source, proxy } = this.state
290
+ const alsReq = this.deps.partiesUtils.alsRequestDto(source, this.inputs.params)
291
+ const isSet = await this.deps.proxyCache.setProxyGetPartiesTimeout(alsReq, proxy)
292
+ this.log.info('#setProxyGetPartiesTimeout is done', { isSet })
293
+ return isSet
294
+ }
278
295
  }
279
296
  }
280
297
 
281
298
  module.exports = GetPartiesService
299
+
300
+ // As Payee DFSP Scheme Oracle identifies direct participant.
301
+ // As Payer DFSP Scheme oracle identifies interscheme participant.
302
+
303
+ // zm-dfsp --> ZM
304
+ // region-dfsp --> Region
305
+ // mw-dfsp --> MW (mw-party-123)
306
+
307
+ // 1. region-dfsp gets info about mw-party-123
@@ -30,49 +30,72 @@ const { ERROR_MESSAGES } = require('../../../constants')
30
30
  const BasePartiesService = require('./BasePartiesService')
31
31
 
32
32
  class PutPartiesErrorService extends BasePartiesService {
33
- // async handleRequest () {
34
- // // todo: add impl.
35
- // }
36
-
37
- async checkPayee ({ headers, params, payload, proxy }) {
38
- const notValid = this.deps.partiesUtils.isNotValidPayeeCase(payload)
39
- if (notValid) {
40
- this.deps.stepState.inProgress('notValidPayeeCase-1')
41
- this.log.warn('notValidPayee case - deleting Participants and run getPartiesByTypeAndID', { proxy, payload })
42
- const swappedHeaders = this.deps.partiesUtils.swapSourceDestinationHeaders(headers)
43
- await super.sendDeleteOracleRequest(swappedHeaders, params)
33
+ async handleRequest () {
34
+ if (this.state.proxyEnabled && this.state.proxy) {
35
+ const alsReq = this.deps.partiesUtils.alsRequestDto(this.state.destination, this.inputs.params) // or source?
36
+ const isPending = await this.deps.proxyCache.isPendingCallback(alsReq)
37
+
38
+ if (!isPending) {
39
+ // not initial inter-scheme discovery case. Cleanup oracle and trigger inter-scheme discovery
40
+ this.log.warn('Need to cleanup oracle and trigger new inter-scheme discovery flow')
41
+ await this.cleanupOracle()
42
+ await this.removeProxyGetPartiesTimeout(alsReq)
43
+ return true // need to trigger inter-scheme discovery
44
+ }
45
+
46
+ const isLast = await this.checkLastProxyCallback(alsReq)
47
+ if (!isLast) {
48
+ this.log.verbose('putPartiesErrorByTypeAndID proxy callback was processed')
49
+ return
50
+ }
44
51
  }
45
- return notValid
52
+
53
+ await this.identifyDestinationForErrorCallback()
54
+ await this.sendErrorCallbackToParticipant()
55
+ this.log.info('putPartiesByTypeAndID is done')
46
56
  }
47
57
 
48
- async checkLastProxyCallback ({ destination, proxy, params }) {
49
- this.deps.stepState.inProgress('checkLastProxyCallback-2')
50
- const alsReq = this.deps.partiesUtils.alsRequestDto(destination, params) // or source?
58
+ async cleanupOracle () {
59
+ this.stepInProgress('cleanupOracle')
60
+ const { headers, params, payload } = this.inputs
61
+ this.log.info('cleanupOracle due to error callback...', { payload })
62
+ const swappedHeaders = this.deps.partiesUtils.swapSourceDestinationHeaders(headers)
63
+ await super.sendDeleteOracleRequest(swappedHeaders, params)
64
+ }
65
+
66
+ async checkLastProxyCallback (alsReq) {
67
+ this.stepInProgress('checkLastProxyCallback')
68
+ const { proxy } = this.state
51
69
  const isLast = await this.deps.proxyCache.receivedErrorResponse(alsReq, proxy)
52
70
  this.log.info(`got${isLast ? '' : 'NOT'} last error callback from proxy`, { proxy, alsReq, isLast })
53
71
  return isLast
54
72
  }
55
73
 
56
- async identifyDestinationForErrorCallback (destination) {
57
- this.deps.stepState.inProgress('validateParticipant-3')
58
- const destinationParticipant = await super.validateParticipant(destination)
59
- if (destinationParticipant) return destination
74
+ async identifyDestinationForErrorCallback () {
75
+ this.stepInProgress('identifyDestinationForErrorCallback')
76
+ const { destination } = this.state
77
+ const schemeParticipant = await super.validateParticipant(destination)
78
+ if (schemeParticipant) {
79
+ this.state.requester = destination
80
+ return
81
+ }
60
82
 
61
- this.deps.stepState.inProgress('lookupProxyDestination-4')
62
- const proxyName = this.proxyEnabled && await this.deps.proxyCache.lookupProxyByDfspId(destination)
63
- if (proxyName) return proxyName
83
+ this.stepInProgress('lookupProxyDestination-4')
84
+ const proxyName = this.state.proxyEnabled && await this.deps.proxyCache.lookupProxyByDfspId(destination)
85
+ if (proxyName) {
86
+ this.state.requester = proxyName
87
+ return
88
+ }
64
89
 
65
90
  const errMessage = ERROR_MESSAGES.partyDestinationFspNotFound
66
91
  this.log.warn(errMessage, { destination })
67
92
  throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.DESTINATION_FSP_ERROR, errMessage)
68
93
  }
69
94
 
70
- async sendErrorCallbackToParticipant ({ sendTo, headers, params, dataUri }) {
71
- this.deps.stepState.inProgress('sendErrorToParticipant-5')
95
+ async sendErrorCallbackToParticipant () {
96
+ const { headers, params, dataUri } = this.inputs
72
97
  const errorInfo = PutPartiesErrorService.decodeDataUriPayload(dataUri)
73
- return super.sendErrorCallback({
74
- sendTo, errorInfo, headers, params
75
- })
98
+ return super.sendErrorCallback({ errorInfo, headers, params })
76
99
  }
77
100
  }
78
101