account-lookup-service 15.6.0-snapshot.4 → 16.1.0-iso.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/LICENSE.md +3 -4
  3. package/README.md +2 -0
  4. package/audit-ci.jsonc +2 -27
  5. package/config/default.json +1 -0
  6. package/docker/mock-proxy/README.md +21 -0
  7. package/docker/mock-proxy/src/config.ts +7 -0
  8. package/docs/Proxy/Discovery.md +20 -0
  9. package/docs/Proxy/FXAPI_POC_payer_conversion_RECEIVE.plantuml +577 -0
  10. package/docs/Proxy/FXAPI_POC_payer_conversion_SEND.plantuml +1423 -0
  11. package/docs/Proxy/P2P.md +11 -0
  12. package/docs/Proxy/Proxy pattern - Happy path.plantuml +98 -0
  13. package/docs/Proxy/Proxy pattern - Lazy Discovery - No Oracles.plantuml +105 -0
  14. package/docs/Proxy/Proxy pattern - Lazy Discovery - No Oracles.png +0 -0
  15. package/docs/Proxy/Proxy pattern - Lazy Discovery - Oracles.plantuml +130 -0
  16. package/docs/Proxy/Proxy pattern - Lazy Discovery - Oracles.png +0 -0
  17. package/docs/Proxy/Proxy pattern - Lazy Discovery Identifier Cache Invalid.plantuml +72 -0
  18. package/docs/Proxy/Proxy pattern - Lazy Discovery Identifier Cache Invalid.png +0 -0
  19. package/docs/Proxy/Proxy pattern - P2P.plantuml +186 -0
  20. package/docs/Proxy/Proxy pattern - P2P.png +0 -0
  21. package/docs/Proxy/Proxy pattern - Unhappy path.plantuml +103 -0
  22. package/docs/Proxy/Proxy pattern - Unhappy path.png +0 -0
  23. package/docs/Proxy/Proxy pattern - happy path.png +0 -0
  24. package/docs/Proxy/Readme.md +39 -0
  25. package/docs/Proxy/SettingUpProxys.plantuml +31 -0
  26. package/docs/Proxy/SettingUpProxys.png +0 -0
  27. package/package.json +33 -18
  28. package/src/constants.js +2 -1
  29. package/src/domain/oracle/oracle.js +63 -4
  30. package/src/domain/participants/participants.js +246 -129
  31. package/src/domain/parties/getPartiesByTypeAndID.js +28 -7
  32. package/src/domain/parties/parties.js +32 -3
  33. package/src/domain/timeout/index.js +12 -1
  34. package/src/handlers/monitoring/index.js +1 -1
  35. package/src/interface/api-swagger-iso20022-parties.yaml +7 -6
  36. package/src/interface/api-swagger.yaml +7 -6
  37. package/src/lib/config.js +2 -1
  38. package/src/lib/db.js +2 -1
  39. package/src/models/currency/currency.js +10 -1
  40. package/src/models/endpointType/endpointType.js +10 -1
  41. package/src/models/oracle/facade.js +42 -16
  42. package/src/models/oracle/oracleEndpoint.js +65 -10
  43. package/src/models/oracle/oracleEndpointCached.js +29 -9
  44. package/src/models/participantEndpoint/facade.js +40 -4
  45. package/src/models/partyIdType/partyIdType.js +10 -1
  46. package/src/plugins.js +8 -21
  47. package/src/server.js +11 -0
  48. package/test/fixtures/index.js +30 -6
  49. package/test/unit/api/health.test.js +3 -0
  50. package/test/unit/api/participants/participants.test.js +5 -7
  51. package/test/unit/api/participants/{Type}/{ID}/{SubId}.test.js +0 -3
  52. package/test/unit/api/participants/{Type}/{ID}.test.js +0 -3
  53. package/test/unit/api/participants.test.js +36 -3
  54. package/test/unit/domain/oracle/oracle.test.js +8 -0
  55. package/test/unit/domain/participants/participants.test.js +83 -48
  56. package/test/unit/domain/parties/parties.test.js +8 -0
  57. package/test/unit/domain/timeout/index.test.js +8 -0
  58. package/test/unit/lib/config.test.js +7 -0
  59. package/test/unit/mocks.js +16 -11
  60. package/test/unit/models/oracle/oracleEndpointCached.test.js +32 -0
  61. package/test/unit/plugins.test.js +2 -2
  62. package/src/lib/requestLogger.js +0 -54
  63. package/src/metrics/handler.js +0 -33
  64. package/src/metrics/plugin.js +0 -52
  65. package/src/metrics/routes.js +0 -43
  66. package/test/unit/lib/requestLogger.test.js +0 -115
@@ -0,0 +1,103 @@
1
+ @startuml
2
+
3
+ title Proxy Patterns - Unhappy Path
4
+
5
+ participant "Payer DFSP" as payerDFSP
6
+ box "Scheme A"
7
+ participant "ALS\nScheme A" as schemeA
8
+ participant "Proxy Cache\nScheme A" as pc_A
9
+ end box
10
+ participant "Proxy AB" as xnp
11
+ box "Scheme B"
12
+ participant "ALS\nScheme B" as schemeB
13
+ participant "Proxy Cache\nScheme B" as pc_B
14
+ end box
15
+ participant "Payee DFS" as payeeDFSP
16
+
17
+ autonumber 1 "<b>[0]"
18
+
19
+ == POST ==
20
+ payerDFSP ->> schemeA: POST/GET/PATCH/PUT /xxx
21
+ note left
22
+ header
23
+ source: payerDFSP
24
+ destination: payeeDFSP
25
+ end note
26
+ alt if OpenAPI Error
27
+ schemeA -->> payerDFSP: 400 Bad Request
28
+ end
29
+
30
+ alt if error in schemeA
31
+ schemeA ->> payerDFSP: PUT /xxx/{ID}/error
32
+ note right
33
+ Error Codes: 2xxx, 3xxx, 4xxx, 5xxx
34
+ end note
35
+ end
36
+
37
+ schemeA -> pc_A: lookup proxy for payeeDFSP = Proxy AB
38
+ alt if not in proxy cache
39
+ schemeA ->> payerDFSP: PUT /xxx/{ID}/error
40
+ note right
41
+ Error Code: 3201
42
+ end note
43
+ end
44
+ schemeA ->> xnp: POST/GET/PATCH/PUT /xxx
45
+
46
+ alt if error in xnp
47
+ xnp ->> schemeA: PUT /xxx/{ID}/error
48
+ note right
49
+ header
50
+ source: Proxy AB
51
+ destination: payerDFSP
52
+ JWS Signed by Proxy AB
53
+ Error Codes: 3100
54
+ end note
55
+ schemeA -->> xnp: 200 OK
56
+ schemeA ->> payerDFSP: PUT /xxx/{ID}/error
57
+ end
58
+
59
+ xnp->xnp: Add header
60
+ note left
61
+ fxpiop-proxy = "Proxy AB"
62
+ end note
63
+
64
+ xnp ->> schemeB: POST/GET/PATCH/PUT /xxx
65
+ schemeB -->> xnp: 202 OK
66
+ xnp -->> schemeA: 202 OK
67
+
68
+ alt if error in schemeB
69
+ schemeB ->> xnp: PUT /xxx/{ID}/error
70
+ note right
71
+ Error Codes: 2xxx, 3xxx, 4xxx, 5xxx
72
+ end note
73
+ xnp->xnp: Add header
74
+ note left
75
+ fxpiop-proxy = "Proxy AB"
76
+ end note
77
+ xnp ->> schemeA: PUT /xxx/{ID}/error
78
+ schemeA -->> xnp: 200 OK
79
+ xnp -->> schemeB: 200 OK
80
+ schemeA ->> payerDFSP: PUT /xxx/{ID}/error
81
+ end
82
+
83
+ schemeB ->> payeeDFSP: POST/GET/PATCH/PUT /xxx
84
+
85
+ alt if error in payeeDFSP
86
+ payeeDFSP->> schemeB: PUT /xxx/{ID}/error
87
+ note right
88
+ header destination: PayerDFSP
89
+ Error Codes: 5xxx
90
+ end note
91
+ schemeB -> schemeB: Lookup proxy for payerDFSP = Proxy AB
92
+ schemeB ->> xnp: PUT /xxx/{ID}/error
93
+ xnp->xnp: Add header
94
+ note left
95
+ fxpiop-proxy = "Proxy AB"
96
+ end note
97
+ xnp ->> schemeA: PUT /xxx/{ID}/error
98
+ schemeA -->> xnp: 200 OK
99
+ xnp -->> schemeB: 200 OK
100
+ schemeA ->> payerDFSP: PUT /xxx/{ID}/error
101
+ end
102
+
103
+ @enduml
@@ -0,0 +1,39 @@
1
+ # Proxy Implementation
2
+ The proxy implementation method to connect schemes does the following.
3
+ 1. Leverages the trust relationship between scheme so that a transaction only has a single pre-funding requirement at the Payer's scheme.
4
+ 2. Ensures non-repudiation across schemes; removing the requirement for the cross-network proxy to take on responsibility for clearing; which removes costs
5
+
6
+ The schemes are connected via a proxy participant, that is registered to act as a proxy in the scheme for adjacent but connected dfsps in other schemes.
7
+ Essentially, the two connected schemes behave as if they where a single scheme.
8
+
9
+ This design make the following assumptions
10
+ 1. No two connected participant have the same identifier
11
+ 1. No limit checks are done against proxy participants
12
+ 1. Get \transaction request are resolved at the payee scheme
13
+ 1. Timeouts in non-payee schemes are disabled (maybe enlarged)
14
+
15
+ ## General Patterns
16
+ There are certain general patterns that emerge
17
+ ### Happy Path Patterns
18
+ ![Happy Path Patterns](Proxy%20pattern%20-%20happy%20path.png)
19
+
20
+ ### Error Patterns
21
+ ![Error Patterns](Proxy%20pattern%20-%20Unhappy%20path.png)
22
+
23
+ ## Detailed Designs
24
+ 1. [Discovery - On Demand Implementation](./Discovery.md)
25
+ 2. [P2P](./P2P.md)
26
+
27
+ ## Admin API - defining Proxy Participants
28
+ ![Admin API](SettingUpProxys.png)
29
+
30
+ ### ALS Proxy Timeout flow
31
+ 1. If no party info returned from Oracle (see [diagram](./Discovery.md)), and there's some proxies in the hub, we need to send
32
+ GET /parties/... requests to each proxy. And wait for the response.
33
+ 2. At this moment we add 2 records in cache (redis) using `inter-scheme-proxy-cache-lib`:
34
+ - key: `als:${sourceId}:${type}:${partyId}` value: `[proxy_1, proxy_2, ...]` (no TTL)
35
+ - key: `als:${sourceId}:${type}:${partyId}:expiresAt` value: `expiresAt` (TTL: default 40 seconds)
36
+ 3. When we get success/failure callbacks from all proxies within TTL period, we process it, and remove `...:expiresAt` key from cache.
37
+ 4. If not all callbacks received within TTL period, redis will expire `...:expiresAt` key, emit appropriate event, and pass _expired cacheKey_.
38
+ 5. We subscribe to these events, and provide a [callback](https://github.com/mojaloop/account-lookup-service/blob/feat/fx-impl/src/domain/timeout/index.js#L53) to be executed in case of timeout.
39
+ 6. From _expired cacheKey_, we get `destination`, `partyType` and `partyId`, which is used to send error callback to appropriate participant.
@@ -0,0 +1,31 @@
1
+ @startuml
2
+ title Central Ledger API / Admin API
3
+
4
+ participant "Onboarding Script" as script
5
+ participant "Mojaloop\nScheme A" as schemeA
6
+ participant "XN Proxy" as xnp
7
+ participant "Mojaloop\nScheme B" as schemeB
8
+
9
+ autonumber 1 "<b>[0]"
10
+
11
+ == Create Participant Types ==
12
+
13
+ script -> schemeA: POST /participants
14
+ note left
15
+ {
16
+ "name": "XN Proxy",
17
+ "currency": "USD",
18
+ <color:#ff0000>"isProxy": true
19
+ }
20
+ end note
21
+
22
+ script -> schemeB: POST /participants
23
+ note left
24
+ {
25
+ "name": "XN Proxy",
26
+ "currency": "USD",
27
+ <color:#ff0000>"isProxy": true
28
+ }
29
+ end note
30
+
31
+ @enduml
Binary file
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "account-lookup-service",
3
3
  "description": "Account Lookup Service is used to validate Party and Participant lookups.",
4
- "version": "15.6.0-snapshot.4",
4
+ "version": "16.1.0-iso.0",
5
5
  "license": "Apache-2.0",
6
6
  "author": "ModusBox",
7
7
  "contributors": [
@@ -90,23 +90,23 @@
90
90
  "@hapi/hapi": "21.3.12",
91
91
  "@hapi/inert": "7.1.0",
92
92
  "@hapi/vision": "7.0.3",
93
- "@mojaloop/central-services-error-handling": "13.0.2",
93
+ "@mojaloop/central-services-error-handling": "13.0.3",
94
94
  "@mojaloop/central-services-health": "15.0.0",
95
- "@mojaloop/central-services-logger": "11.5.1",
96
- "@mojaloop/central-services-metrics": "12.1.0",
97
- "@mojaloop/central-services-shared": "18.11.2",
98
- "@mojaloop/central-services-stream": "11.3.1",
99
- "@mojaloop/database-lib": "11.0.6",
100
- "@mojaloop/event-sdk": "14.1.1",
101
- "@mojaloop/inter-scheme-proxy-cache-lib": "2.3.0",
102
- "@mojaloop/ml-schema-transformer-lib": "2.4.1",
103
- "@mojaloop/sdk-standard-components": "19.5.1",
95
+ "@mojaloop/central-services-logger": "11.5.2",
96
+ "@mojaloop/central-services-metrics": "12.4.3",
97
+ "@mojaloop/central-services-shared": "18.15.1",
98
+ "@mojaloop/central-services-stream": "11.4.2",
99
+ "@mojaloop/database-lib": "11.1.1",
100
+ "@mojaloop/event-sdk": "14.1.2",
101
+ "@mojaloop/inter-scheme-proxy-cache-lib": "2.3.1",
102
+ "@mojaloop/ml-schema-transformer-lib": "2.5.1",
103
+ "@mojaloop/sdk-standard-components": "19.6.3",
104
104
  "@now-ims/hapi-now-auth": "2.1.0",
105
105
  "ajv": "8.17.1",
106
106
  "ajv-keywords": "5.1.0",
107
107
  "blipp": "4.0.2",
108
- "commander": "12.1.0",
109
- "cron": "3.2.1",
108
+ "commander": "13.0.0",
109
+ "cron": "3.5.0",
110
110
  "fast-safe-stringify": "^2.1.1",
111
111
  "hapi-auth-bearer-token": "8.0.0",
112
112
  "joi": "17.13.3",
@@ -118,6 +118,9 @@
118
118
  "rc": "1.2.8"
119
119
  },
120
120
  "overrides": {
121
+ "postcss": {
122
+ "nanoid": "^3.3.8"
123
+ },
121
124
  "@mojaloop/central-services-health": {
122
125
  "@mojaloop/central-services-logger": ">=11.4.0"
123
126
  },
@@ -139,28 +142,40 @@
139
142
  "yargs-parser": "13.1.2",
140
143
  "markdown-it": "12.3.2"
141
144
  },
145
+ "swagger2openapi": {
146
+ "yaml": "2.7.0"
147
+ },
148
+ "oas-validator": {
149
+ "yaml": "2.7.0"
150
+ },
151
+ "oas-linter": {
152
+ "yaml": "2.7.0"
153
+ },
154
+ "cross-spawn": "7.0.6",
142
155
  "yargs": {
143
156
  "yargs-parser": "^21.1.1"
144
157
  },
145
158
  "jsonwebtoken": "9.0.0",
146
- "jsonpointer": "5.0.0"
159
+ "jsonpointer": "5.0.0",
160
+ "validator": "13.7.0"
147
161
  },
148
162
  "devDependencies": {
149
163
  "@types/jest": "29.5.14",
150
164
  "audit-ci": "^7.1.0",
151
- "axios": "1.7.7",
165
+ "axios": "1.7.9",
152
166
  "axios-retry": "^4.5.0",
153
167
  "docdash": "2.0.2",
154
- "dotenv": "^16.4.5",
168
+ "dotenv": "^16.4.7",
155
169
  "get-port": "5.1.1",
156
170
  "ioredis-mock": "^8.9.0",
157
171
  "jest": "29.7.0",
158
172
  "jest-junit": "16.0.0",
159
173
  "jsdoc": "4.0.4",
160
- "nodemon": "3.1.7",
161
- "npm-check-updates": "17.1.11",
174
+ "nodemon": "3.1.9",
175
+ "npm-check-updates": "17.1.13",
162
176
  "nyc": "17.1.0",
163
177
  "pre-commit": "1.2.2",
178
+ "proxyquire": "2.1.3",
164
179
  "replace": "^1.2.2",
165
180
  "sinon": "19.0.2",
166
181
  "standard": "17.1.2",
package/src/constants.js CHANGED
@@ -1,5 +1,6 @@
1
1
  const ERROR_MESSAGES = Object.freeze({
2
- partySourceFspNotFound: 'Requester FSP not found',
2
+ sourceFspNotFound: 'Requester FSP not found',
3
+ partySourceFspNotFound: 'Requester FSP not found', // todo: use sourceFspNotFound
3
4
  partyDestinationFspNotFound: 'Destination FSP not found',
4
5
  partyProxyNotFound: 'Proxy not found',
5
6
  proxyConnectionError: 'Proxy connection error',
@@ -49,9 +49,15 @@ exports.createOracle = async (payload) => {
49
49
  'Create Oracle',
50
50
  ['success']
51
51
  ).startTimer()
52
+ const errorCounter = Metrics.getCounter('errorCount')
53
+ let step
54
+
52
55
  try {
56
+ step = 'getPartyIdTypeByName-1'
53
57
  const partyIdTypeModel = await partyIdType.getPartyIdTypeByName(payload.oracleIdType)
58
+ step = 'getEndpointTypeByType-2'
54
59
  const endpointTypeModel = await endpointType.getEndpointTypeByType(payload.endpoint.endpointType)
60
+ step = 'getAllOracleEndpointsByMatchCondition-3'
55
61
  const existingActiveOracle = await oracleEndpoint.getAllOracleEndpointsByMatchCondition(
56
62
  payload,
57
63
  partyIdTypeModel.partyIdTypeId,
@@ -77,13 +83,23 @@ exports.createOracle = async (payload) => {
77
83
  oracleEntity.createdBy = 'Admin'
78
84
  oracleEntity.partyIdTypeId = partyIdTypeModel.partyIdTypeId
79
85
  oracleEntity.endpointTypeId = endpointTypeModel.endpointTypeId
86
+ step = 'createOracleEndpoint-4'
80
87
  await oracleEndpoint.createOracleEndpoint(oracleEntity)
81
88
  histTimerEnd({ success: true })
82
89
  return true
83
90
  } catch (err) {
84
91
  histTimerEnd({ success: false })
85
92
  Logger.isErrorEnabled && Logger.error(err)
86
- throw ErrorHandler.Factory.reformatFSPIOPError(err)
93
+ const fspiopError = ErrorHandler.Factory.reformatFSPIOPError(err)
94
+ const extensions = err.extensions || []
95
+ const system = extensions.find((element) => element.key === 'system')?.value || ''
96
+ errorCounter.inc({
97
+ code: fspiopError?.apiErrorCode?.code,
98
+ system,
99
+ operation: 'createOracle',
100
+ step
101
+ })
102
+ throw fspiopError
87
103
  }
88
104
  }
89
105
 
@@ -100,6 +116,8 @@ exports.getOracle = async (query) => {
100
116
  'Get Oracle',
101
117
  ['success']
102
118
  ).startTimer()
119
+ const errorCounter = Metrics.getCounter('errorCount')
120
+ let step
103
121
  try {
104
122
  let oracleEndpointModelList
105
123
  let isCurrency; let isType = false
@@ -111,12 +129,16 @@ exports.getOracle = async (query) => {
111
129
  isType = true
112
130
  }
113
131
  if (isCurrency && isType) {
132
+ step = 'getOracleEndpointByTypeAndCurrency-1'
114
133
  oracleEndpointModelList = await cachedOracleEndpoint.getOracleEndpointByTypeAndCurrency(query.type, query.currency)
115
134
  } else if (isCurrency && !isType) {
135
+ step = 'getOracleEndpointByCurrency-2'
116
136
  oracleEndpointModelList = await cachedOracleEndpoint.getOracleEndpointByCurrency(query.currency)
117
137
  } else if (isType && !isCurrency) {
138
+ step = 'getOracleEndpointByType-3'
118
139
  oracleEndpointModelList = await cachedOracleEndpoint.getOracleEndpointByType(query.type)
119
140
  } else {
141
+ step = 'getAllOracleEndpoint-4'
120
142
  oracleEndpointModelList = await oracleEndpoint.getAllOracleEndpoint()
121
143
  }
122
144
  for (const oracleEndpointModel of oracleEndpointModelList) {
@@ -137,7 +159,16 @@ exports.getOracle = async (query) => {
137
159
  } catch (err) {
138
160
  histTimerEnd({ success: false })
139
161
  Logger.isErrorEnabled && Logger.error(err)
140
- throw ErrorHandler.Factory.reformatFSPIOPError(err)
162
+ const fspiopError = ErrorHandler.Factory.reformatFSPIOPError(err)
163
+ const extensions = err.extensions || []
164
+ const system = extensions.find((element) => element.key === 'system')?.value || ''
165
+ errorCounter.inc({
166
+ code: fspiopError?.apiErrorCode?.code,
167
+ system,
168
+ operation: 'getOracle',
169
+ step
170
+ })
171
+ throw fspiopError
141
172
  }
142
173
  }
143
174
 
@@ -155,11 +186,17 @@ exports.updateOracle = async (params, payload) => {
155
186
  'Update Oracle',
156
187
  ['success']
157
188
  ).startTimer()
189
+ const errorCounter = Metrics.getCounter('errorCount')
190
+ let step
158
191
  try {
192
+ step = 'getOracleEndpointById-1'
159
193
  const currentOracleEndpointList = await oracleEndpoint.getOracleEndpointById(params.ID)
160
194
  if (currentOracleEndpointList.length > 0) {
195
+ step = 'getPartyIdTypeByName-2'
161
196
  const partyIdTypeModel = await partyIdType.getPartyIdTypeByName(payload.oracleIdType)
197
+ step = 'getEndpointTypeByType-3'
162
198
  const endpointTypeModel = await endpointType.getEndpointTypeByType(payload.endpoint.endpointType)
199
+ step = 'getAllOracleEndpointsByMatchCondition-4'
163
200
  const existingActiveOracle = await oracleEndpoint.getAllOracleEndpointsByMatchCondition(
164
201
  payload,
165
202
  partyIdTypeModel.partyIdTypeId,
@@ -175,6 +212,7 @@ exports.updateOracle = async (params, payload) => {
175
212
  const currentOracleEndpoint = currentOracleEndpointList[0]
176
213
  const newOracleEntry = {}
177
214
  if (payload.oracleIdType && payload.oracleIdType !== currentOracleEndpoint.idType) {
215
+ step = 'getPartyIdTypeByName-5'
178
216
  const partyTypeModel = await partyIdType.getPartyIdTypeByName(payload.oracleIdType)
179
217
  newOracleEntry.partyIdTypeId = partyTypeModel.partyIdTypeId
180
218
  }
@@ -182,10 +220,12 @@ exports.updateOracle = async (params, payload) => {
182
220
  newOracleEntry.value = payload.endpoint.value
183
221
  }
184
222
  if (payload.endpoint && payload.endpoint.endpointType && payload.endpoint.endpointType !== currentOracleEndpoint.endpointType) {
223
+ step = 'getEndpointTypeByType-6'
185
224
  const endpointTypeModel = await endpointType.getEndpointTypeByType(payload.endpoint.endpointType)
186
225
  newOracleEntry.endpointTypeId = endpointTypeModel.endpointTypeId
187
226
  }
188
227
  if (payload.currency && payload.currency !== currentOracleEndpoint.currency) {
228
+ step = 'getCurrencyById-7'
189
229
  const currencyModel = await currency.getCurrencyById(payload.currency)
190
230
  if (currencyModel) {
191
231
  newOracleEntry.currencyId = payload.currency
@@ -196,6 +236,7 @@ exports.updateOracle = async (params, payload) => {
196
236
  if (payload.isDefault && payload.isDefault !== currentOracleEndpoint.isDefault) {
197
237
  newOracleEntry.isDefault = payload.isDefault
198
238
  }
239
+ step = 'updateOracleEndpointById-8'
199
240
  await oracleEndpoint.updateOracleEndpointById(params.ID, newOracleEntry)
200
241
  histTimerEnd({ success: true })
201
242
  return true
@@ -205,7 +246,16 @@ exports.updateOracle = async (params, payload) => {
205
246
  } catch (err) {
206
247
  histTimerEnd({ success: false })
207
248
  Logger.isErrorEnabled && Logger.error(err)
208
- throw ErrorHandler.Factory.reformatFSPIOPError(err)
249
+ const fspiopError = ErrorHandler.Factory.reformatFSPIOPError(err)
250
+ const extensions = err.extensions || []
251
+ const system = extensions.find((element) => element.key === 'system')?.value || ''
252
+ errorCounter.inc({
253
+ code: fspiopError?.apiErrorCode?.code,
254
+ system,
255
+ operation: 'updateOracle',
256
+ step
257
+ })
258
+ throw fspiopError
209
259
  }
210
260
  }
211
261
 
@@ -222,6 +272,7 @@ exports.deleteOracle = async (params) => {
222
272
  'Delete Oracle',
223
273
  ['success']
224
274
  ).startTimer()
275
+ const errorCounter = Metrics.getCounter('errorCount')
225
276
  try {
226
277
  await oracleEndpoint.destroyOracleEndpointById(params.ID)
227
278
  histTimerEnd({ success: true })
@@ -229,6 +280,14 @@ exports.deleteOracle = async (params) => {
229
280
  } catch (err) {
230
281
  histTimerEnd({ success: false })
231
282
  Logger.isErrorEnabled && Logger.error(err)
232
- throw ErrorHandler.Factory.reformatFSPIOPError(err)
283
+ const fspiopError = ErrorHandler.Factory.reformatFSPIOPError(err)
284
+ const extensions = err.extensions || []
285
+ const system = extensions.find((element) => element.key === 'system')?.value || ''
286
+ errorCounter.inc({
287
+ code: fspiopError?.apiErrorCode?.code,
288
+ system,
289
+ operation: 'deleteOracle'
290
+ })
291
+ throw fspiopError
233
292
  }
234
293
  }