@mojaloop/central-ledger 17.0.4 → 17.1.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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,20 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ## [17.1.0](https://github.com/mojaloop/central-ledger/compare/v17.0.5...v17.1.0) (2023-09-04)
6
+
7
+
8
+ ### Features
9
+
10
+ * **mojaloop/#3498:** alter message keys for prepare, fulfil and timeout ([#965](https://github.com/mojaloop/central-ledger/issues/965)) ([db3e3b2](https://github.com/mojaloop/central-ledger/commit/db3e3b2f0450f1093f1f20eb4f49b4f4de53ddd0)), closes [mojaloop/#3498](https://github.com/mojaloop/project/issues/3498)
11
+
12
+ ### [17.0.5](https://github.com/mojaloop/central-ledger/compare/v17.0.4...v17.0.5) (2023-09-04)
13
+
14
+
15
+ ### Bug Fixes
16
+
17
+ * json stringify on every response ([#961](https://github.com/mojaloop/central-ledger/issues/961)) ([6798bfd](https://github.com/mojaloop/central-ledger/commit/6798bfda51be18c2d44c22e10ef67bc76c8b2195))
18
+
5
19
  ### [17.0.4](https://github.com/mojaloop/central-ledger/compare/v17.0.3...v17.0.4) (2023-09-04)
6
20
 
7
21
 
@@ -205,18 +205,17 @@ services:
205
205
  retries: 10
206
206
  interval: 30s
207
207
 
208
- kowl:
209
- image: quay.io/cloudhut/kowl:v1.4.0
210
- container_name: cl_kowl
208
+ ## Debug utilities
209
+ kafka-debug-console:
210
+ # image: quay.io/cloudhut/kowl:v1.4.0
211
+ image: docker.redpanda.com/redpandadata/console:latest
211
212
  deploy:
212
213
  replicas: 1
213
214
  restart: on-failure
214
- hostname: kowl
215
+ hostname: kafka-debug-console
215
216
  ports:
216
- - "8080:8080"
217
+ - "9080:8080"
217
218
  networks:
218
219
  - cl-mojaloop-net
219
220
  environment:
220
221
  - KAFKA_BROKERS=kafka:29092
221
- depends_on:
222
- - kafka
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mojaloop/central-ledger",
3
- "version": "17.0.4",
3
+ "version": "17.1.0",
4
4
  "description": "Central ledger hosted by a scheme to record and settle transfers",
5
5
  "license": "Apache-2.0",
6
6
  "author": "ModusBox",
@@ -96,7 +96,8 @@ const timeout = async () => {
96
96
  } else if (result[i].transferStateId === Enum.Transfers.TransferInternalState.RESERVED_TIMEOUT) {
97
97
  message.metadata.event.type = Enum.Events.Event.Type.POSITION
98
98
  message.metadata.event.action = Enum.Events.Event.Action.TIMEOUT_RESERVED
99
- await Kafka.produceGeneralMessage(Config.KAFKA_CONFIG, Producer, Enum.Kafka.Topics.POSITION, Enum.Events.Event.Action.TIMEOUT_RESERVED, message, state, result[i].payerFsp, span)
99
+ // Key position timeouts with payer account id
100
+ await Kafka.produceGeneralMessage(Config.KAFKA_CONFIG, Producer, Enum.Kafka.Topics.POSITION, Enum.Events.Event.Action.TIMEOUT_RESERVED, message, state, result[i].payerParticipantCurrencyId?.toString(), span)
100
101
  }
101
102
  } else { // individual transfer from a bulk
102
103
  if (result[i].transferStateId === Enum.Transfers.TransferInternalState.EXPIRED_PREPARED) {
@@ -108,7 +109,8 @@ const timeout = async () => {
108
109
  } else if (result[i].transferStateId === Enum.Transfers.TransferInternalState.RESERVED_TIMEOUT) {
109
110
  message.metadata.event.type = Enum.Events.Event.Type.POSITION
110
111
  message.metadata.event.action = Enum.Events.Event.Action.BULK_TIMEOUT_RESERVED
111
- await Kafka.produceGeneralMessage(Config.KAFKA_CONFIG, Producer, Enum.Kafka.Topics.POSITION, Enum.Events.Event.Action.BULK_TIMEOUT_RESERVED, message, state, result[i].payerFsp, span)
112
+ // Key position timeouts with payer account id
113
+ await Kafka.produceGeneralMessage(Config.KAFKA_CONFIG, Producer, Enum.Kafka.Topics.POSITION, Enum.Events.Event.Action.BULK_TIMEOUT_RESERVED, message, state, result[i].payerParticipantCurrencyId?.toString(), span)
112
114
  }
113
115
  }
114
116
  } catch (err) {
@@ -56,10 +56,10 @@ const Config = require('../../lib/config')
56
56
  const decodePayload = Util.StreamingProtocol.decodePayload
57
57
  const Comparators = require('@mojaloop/central-services-shared').Util.Comparators
58
58
  const ErrorHandler = require('@mojaloop/central-services-error-handling')
59
+ const Participant = require('../../domain/participant')
59
60
 
60
61
  const consumerCommit = true
61
62
  const fromSwitch = true
62
- const toDestination = true
63
63
 
64
64
  /**
65
65
  * @function TransferPrepareHandler
@@ -198,7 +198,9 @@ const prepare = async (error, messages) => {
198
198
  Logger.isInfoEnabled && Logger.info(Util.breadcrumb(location, `positionTopic1--${actionLetter}7`))
199
199
  functionality = TransferEventType.POSITION
200
200
  const eventDetail = { functionality, action }
201
- await Kafka.proceed(Config.KAFKA_CONFIG, params, { consumerCommit, eventDetail, toDestination })
201
+ // Key position prepare message with payer account id
202
+ const payerAccount = await Participant.getAccountByNameAndCurrency(payload.payerFsp, payload.amount.currency, Enum.Accounts.LedgerAccountType.POSITION)
203
+ await Kafka.proceed(Config.KAFKA_CONFIG, params, { consumerCommit, eventDetail, messageKey: payerAccount.participantCurrencyId.toString() })
202
204
  histTimerEnd({ success: true, fspId: Config.INSTRUMENTATION_METRICS_LABELS.fspId })
203
205
  return true
204
206
  } else {
@@ -372,10 +374,6 @@ const fulfil = async (error, messages) => {
372
374
 
373
375
  const apiFSPIOPError = fspiopError.toApiErrorObject(Config.ERROR_HANDLING)
374
376
 
375
- // Overriding global boolean declaration with a string value for local as we should handle notifications only to FSPs involved with this transfer
376
- const toPayerDestination = transfer.payerFsp
377
- const toPayeeDestination = transfer.payeeFsp
378
-
379
377
  // Set the event details to map to an ABORT_VALIDATION event targeted to the Position Handler
380
378
  const eventDetail = { functionality: TransferEventType.POSITION, action: TransferEventAction.ABORT_VALIDATION }
381
379
 
@@ -390,7 +388,9 @@ const fulfil = async (error, messages) => {
390
388
  */
391
389
 
392
390
  // Publish message to Position Handler
393
- await Kafka.proceed(Config.KAFKA_CONFIG, params, { consumerCommit, fspiopError: apiFSPIOPError, eventDetail, fromSwitch, toDestination: toPayerDestination })
391
+ // Key position abort with payer account id
392
+ const payerAccount = await Participant.getAccountByNameAndCurrency(transfer.payerFsp, transfer.currency, Enum.Accounts.LedgerAccountType.POSITION)
393
+ await Kafka.proceed(Config.KAFKA_CONFIG, params, { consumerCommit, fspiopError: apiFSPIOPError, eventDetail, fromSwitch, messageKey: payerAccount.participantCurrencyId.toString() })
394
394
 
395
395
  /**
396
396
  * Send patch notification callback to original payee fsp if they asked for a a patch response.
@@ -420,7 +420,7 @@ const fulfil = async (error, messages) => {
420
420
  }
421
421
  }
422
422
  message.value.content.payload = reservedAbortedPayload
423
- await Kafka.proceed(Config.KAFKA_CONFIG, params, { consumerCommit, eventDetail: reserveAbortedEventDetail, toDestination: toPayeeDestination, fromSwitch: true })
423
+ await Kafka.proceed(Config.KAFKA_CONFIG, params, { consumerCommit, eventDetail: reserveAbortedEventDetail, fromSwitch: true })
424
424
  }
425
425
 
426
426
  throw apiFSPIOPError
@@ -446,7 +446,7 @@ const fulfil = async (error, messages) => {
446
446
  Logger.isInfoEnabled && Logger.info(Util.breadcrumb(location, 'handleResend'))
447
447
 
448
448
  // This is a duplicate message for a transfer that is already in a finalized state
449
- // respond as if we recieved a GET /transfers/{ID} from the client
449
+ // respond as if we received a GET /transfers/{ID} from the client
450
450
  if (transferStateEnum === TransferState.COMMITTED || transferStateEnum === TransferState.ABORTED) {
451
451
  message.value.content.payload = TransferObjectTransform.toFulfil(transfer)
452
452
  const eventDetail = { functionality, action }
@@ -555,7 +555,9 @@ const fulfil = async (error, messages) => {
555
555
  /**
556
556
  * TODO: BulkProcessingHandler (not in scope of #967) The individual transfer is ABORTED by notification is never sent.
557
557
  */
558
- await Kafka.proceed(Config.KAFKA_CONFIG, params, { consumerCommit, fspiopError: apiFSPIOPError, eventDetail, toDestination })
558
+ // Key position validation abort with payer account id
559
+ const payerAccount = await Participant.getAccountByNameAndCurrency(transfer.payerFsp, transfer.currency, Enum.Accounts.LedgerAccountType.POSITION)
560
+ await Kafka.proceed(Config.KAFKA_CONFIG, params, { consumerCommit, fspiopError: apiFSPIOPError, eventDetail, messageKey: payerAccount.participantCurrencyId.toString() })
559
561
 
560
562
  // emit an extra message - RESERVED_ABORTED if action === TransferEventAction.RESERVE
561
563
  if (action === TransferEventAction.RESERVE) {
@@ -585,7 +587,7 @@ const fulfil = async (error, messages) => {
585
587
  }
586
588
  }
587
589
  message.value.content.payload = reservedAbortedPayload
588
- await Kafka.proceed(Config.KAFKA_CONFIG, params, { consumerCommit, eventDetail, toDestination: transfer.payeeFsp, fromSwitch: true })
590
+ await Kafka.proceed(Config.KAFKA_CONFIG, params, { consumerCommit, eventDetail, fromSwitch: true })
589
591
  }
590
592
  throw fspiopError
591
593
  }
@@ -613,7 +615,7 @@ const fulfil = async (error, messages) => {
613
615
  transferState: TransferState.ABORTED
614
616
  }
615
617
  message.value.content.payload = reservedAbortedPayload
616
- await Kafka.proceed(Config.KAFKA_CONFIG, params, { consumerCommit, eventDetail, toDestination: transfer.payeeFsp, fromSwitch: true })
618
+ await Kafka.proceed(Config.KAFKA_CONFIG, params, { consumerCommit, eventDetail, fromSwitch: true })
617
619
  }
618
620
  throw fspiopError
619
621
  }
@@ -641,7 +643,7 @@ const fulfil = async (error, messages) => {
641
643
  transferState: TransferState.ABORTED
642
644
  }
643
645
  message.value.content.payload = reservedAbortedPayload
644
- await Kafka.proceed(Config.KAFKA_CONFIG, params, { consumerCommit, eventDetail, toDestination: transfer.payeeFsp, fromSwitch: true })
646
+ await Kafka.proceed(Config.KAFKA_CONFIG, params, { consumerCommit, eventDetail, fromSwitch: true })
645
647
  }
646
648
  throw fspiopError
647
649
  }
@@ -655,7 +657,9 @@ const fulfil = async (error, messages) => {
655
657
  Logger.isInfoEnabled && Logger.info(Util.breadcrumb(location, `positionTopic2--${actionLetter}12`))
656
658
  await TransferService.handlePayeeResponse(transferId, payload, action)
657
659
  const eventDetail = { functionality: TransferEventType.POSITION, action }
658
- await Kafka.proceed(Config.KAFKA_CONFIG, params, { consumerCommit, eventDetail, toDestination })
660
+ // Key position fulfil message with payee account id
661
+ const payeeAccount = await Participant.getAccountByNameAndCurrency(transfer.payeeFsp, transfer.currency, Enum.Accounts.LedgerAccountType.POSITION)
662
+ await Kafka.proceed(Config.KAFKA_CONFIG, params, { consumerCommit, eventDetail, messageKey: payeeAccount.participantCurrencyId.toString() })
659
663
  histTimerEnd({ success: true, fspId: Config.INSTRUMENTATION_METRICS_LABELS.fspId })
660
664
  return true
661
665
  }
@@ -686,12 +690,16 @@ const fulfil = async (error, messages) => {
686
690
  fspiopError = ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.VALIDATION_ERROR, 'API specification undefined errorCode')
687
691
  await TransferService.handlePayeeResponse(transferId, payload, action, fspiopError.toApiErrorObject(Config.ERROR_HANDLING))
688
692
  const eventDetail = { functionality: TransferEventType.POSITION, action }
689
- await Kafka.proceed(Config.KAFKA_CONFIG, params, { consumerCommit, fspiopError: fspiopError.toApiErrorObject(Config.ERROR_HANDLING), eventDetail, toDestination })
693
+ // Key position abort with payer account id
694
+ const payerAccount = await Participant.getAccountByNameAndCurrency(transfer.payerFsp, transfer.currency, Enum.Accounts.LedgerAccountType.POSITION)
695
+ await Kafka.proceed(Config.KAFKA_CONFIG, params, { consumerCommit, fspiopError: fspiopError.toApiErrorObject(Config.ERROR_HANDLING), eventDetail, messageKey: payerAccount.participantCurrencyId.toString() })
690
696
  throw fspiopError
691
697
  }
692
698
  await TransferService.handlePayeeResponse(transferId, payload, action, fspiopError.toApiErrorObject(Config.ERROR_HANDLING))
693
699
  const eventDetail = { functionality: TransferEventType.POSITION, action }
694
- await Kafka.proceed(Config.KAFKA_CONFIG, params, { consumerCommit, fspiopError: fspiopError.toApiErrorObject(Config.ERROR_HANDLING), eventDetail, toDestination })
700
+ // Key position abort with payer account id
701
+ const payerAccount = await Participant.getAccountByNameAndCurrency(transfer.payerFsp, transfer.currency, Enum.Accounts.LedgerAccountType.POSITION)
702
+ await Kafka.proceed(Config.KAFKA_CONFIG, params, { consumerCommit, fspiopError: fspiopError.toApiErrorObject(Config.ERROR_HANDLING), eventDetail, messageKey: payerAccount.participantCurrencyId.toString() })
695
703
  // TODO(2556): I don't think we should emit an extra notification here
696
704
  // this is the case where the Payee sent an ABORT, so we don't need to tell them to abort
697
705
  throw fspiopError
@@ -13,8 +13,8 @@ const logRequest = function (request) {
13
13
  }
14
14
 
15
15
  const logResponse = function (request) {
16
- const traceId = request.headers.traceid
17
- if (request.response) {
16
+ if (Logger.isDebugEnabled && request.response) {
17
+ const traceId = request.headers.traceid
18
18
  let response
19
19
  try {
20
20
  response = JSON.stringify(request.response, null, 2)
@@ -715,8 +715,8 @@ const timeoutExpireReserved = async (segmentId, intervalMin, intervalMax) => {
715
715
  .leftJoin('bulkTransferAssociation AS bta', 'bta.transferId', 'tt.transferId')
716
716
 
717
717
  .where('tt.expirationDate', '<', transactionTimestamp)
718
- .select('tt.*', 'tsc.transferStateId', 'tp1.participantCurrencyId AS payerParticipantId',
719
- 'p1.name AS payerFsp', 'p2.name AS payeeFsp', 'tp2.participantCurrencyId AS payeeParticipantId',
718
+ .select('tt.*', 'tsc.transferStateId', 'tp1.participantCurrencyId AS payerParticipantCurrencyId',
719
+ 'p1.name AS payerFsp', 'p2.name AS payeeFsp', 'tp2.participantCurrencyId AS payeeParticipantCurrencyId',
720
720
  'bta.bulkTransferId')
721
721
  } catch (err) {
722
722
  throw ErrorHandler.Factory.reformatFSPIOPError(err)