@mojaloop/central-ledger 19.14.0 → 20.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/.grype.yaml +3 -0
- package/.license-scanner.json +16 -0
- package/.ncurc.yaml +19 -13
- package/.nvmrc +1 -1
- package/.nycrc.yml +14 -2
- package/CHANGELOG.md +51 -0
- package/Dockerfile +13 -10
- package/README.md +39 -89
- package/audit-ci.jsonc +1 -1
- package/config/default.json +60 -3
- package/config/deprecated.default-settlement.json +160 -0
- package/docker/ml-api-adapter/default.json +28 -0
- package/docker-compose.yml +6 -0
- package/nodemon.json +6 -0
- package/package.json +128 -64
- package/{sbom-v19.13.2.csv → sbom-v20.0.0.csv} +886 -736
- package/scripts/_wait4_all.js +5 -5
- package/scripts/transferSettlementTemp/interchangeFeeCalculation.js +51 -0
- package/src/api/index.ts +30 -0
- package/src/api/interface/swagger.json +2249 -2054
- package/src/api/participants/routes.js +1 -1
- package/src/api/root/handler.int.ts +55 -0
- package/src/api/routes.js +7 -6
- package/src/api/server.ts +27 -0
- package/src/api/server.unit.ts +16 -0
- package/src/api/settlementModels/routes.js +4 -4
- package/src/domain/participant/index.d.ts +47 -0
- package/src/domain/participant/index.int.ts +724 -0
- package/src/domain/participant/index.js +4 -5
- package/src/domain/position/fx-prepare.js +1 -1
- package/src/domain/position/fx-timeout-reserved.js +6 -0
- package/src/domain/position/prepare.js +1 -1
- package/src/handlers/admin/handler.js +1 -1
- package/src/handlers/index.js +30 -0
- package/src/handlers/positions/handler.js +0 -2
- package/src/handlers/positions/handlerBatch.js +5 -5
- package/src/handlers/register.js +44 -29
- package/src/handlers/timeouts/handler.js +1 -4
- package/src/handlers/transfers/fx-abort.int.ts +209 -0
- package/src/handlers/transfers/fx-handlers.int.ts +275 -0
- package/src/handlers/transfers/fx-timeout.int.ts +284 -0
- package/src/handlers/transfers/handler.js +1 -3
- package/src/handlers/transfers/handlers.int.ts +538 -0
- package/src/handlers/transfers/prepare.int.ts +1283 -0
- package/src/handlers/transfers/prepare.js +2 -2
- package/src/knexfile.js +19 -0
- package/src/lib/cache.js +1 -1
- package/src/lib/config/index.ts +60 -0
- package/src/lib/config/resolver.ts +231 -0
- package/src/lib/config/resolver.unit.ts +72 -0
- package/src/lib/config/types.ts +372 -0
- package/src/lib/config/util.ts +523 -0
- package/src/lib/config/util.unit.ts +825 -0
- package/src/lib/migrator.js +3 -3
- package/src/lib/proxyCache.js +3 -3
- package/{migrations → src/migrations}/100100_event.js +1 -1
- package/{migrations → src/migrations}/110100_contactType.js +1 -1
- package/{migrations → src/migrations}/110200_currency.js +1 -1
- package/{migrations → src/migrations}/110201_currency-scale.js +1 -1
- package/{migrations → src/migrations}/110300_endpointType.js +1 -1
- package/{migrations → src/migrations}/110400_ledgerEntryType.js +1 -1
- package/{migrations → src/migrations}/110450_ledgerAccountType.js +1 -1
- package/{migrations → src/migrations}/110500_participantLimitType.js +1 -1
- package/{migrations → src/migrations}/110600_transferParticipantRoleType.js +1 -1
- package/{migrations → src/migrations}/110700_transferState.js +1 -1
- package/{migrations → src/migrations}/110900_settlementState.js +1 -1
- package/{migrations → src/migrations}/112000_bulkTransferState.js +1 -1
- package/{migrations → src/migrations}/112100_bulkProcessingState.js +1 -1
- package/{migrations → src/migrations}/200100_participant.js +1 -1
- package/{migrations → src/migrations}/200200_participantContact.js +1 -1
- package/{migrations → src/migrations}/200300_participantEndpoint.js +1 -1
- package/{migrations → src/migrations}/200400_participantParty.js +1 -1
- package/{migrations → src/migrations}/200600_token.js +1 -1
- package/{migrations → src/migrations}/200601_token-indexes.js +1 -1
- package/{migrations → src/migrations}/300100_transferDuplicateCheck.js +2 -2
- package/{migrations → src/migrations}/300150_bulkTransferDuplicateCheck.js +2 -2
- package/{migrations → src/migrations}/300200_transfer.js +2 -2
- package/{migrations → src/migrations}/300202_transfer-decimal184.js +1 -1
- package/{migrations → src/migrations}/300250_bulkTransfer.js +2 -3
- package/{migrations → src/migrations}/300275_bulkTransferAssociation.js +2 -3
- package/{migrations → src/migrations}/300300_ilpPacket.js +1 -1
- package/{migrations → src/migrations}/300400_transferStateChange.js +1 -1
- package/{migrations → src/migrations}/300450_bulkTransferStateChange.js +1 -1
- package/{migrations → src/migrations}/300500_segment.js +1 -1
- package/{migrations → src/migrations}/310100_participantCurrency.js +1 -1
- package/{migrations → src/migrations}/310200_transferParticipant.js +1 -1
- package/{migrations → src/migrations}/310202_transferParticipant-decimal184.js +1 -1
- package/{migrations → src/migrations}/310204_transferParticipant-participantId.js +2 -2
- package/{migrations → src/migrations}/310300_participantPosition.js +1 -1
- package/{migrations → src/migrations}/310302_participantPosition-decimal184.js +1 -1
- package/{migrations → src/migrations}/310400_participantPositionChange.js +1 -1
- package/{migrations → src/migrations}/310402_participantPositionChange-decimal184.js +1 -1
- package/{migrations → src/migrations}/310403_participantPositionChange-participantCurrencyId.js +2 -2
- package/{migrations → src/migrations}/310404_participantPositionChange-change.js +2 -2
- package/{migrations → src/migrations}/310500_participantLimit.js +1 -1
- package/{migrations → src/migrations}/310502_participantLimit-decimal184.js +1 -1
- package/{migrations → src/migrations}/400100_settlementWindow.js +1 -1
- package/{migrations → src/migrations}/400200_settlement.js +1 -1
- package/{migrations → src/migrations}/400300_settlementSettlementWindow.js +1 -1
- package/{migrations → src/migrations}/400301_settlementSettlementWindow-indexes.js +0 -1
- package/{migrations → src/migrations}/400400_settlementWindowStateChange.js +1 -1
- package/{migrations → src/migrations}/400500_settlementTransferParticipant.js +1 -1
- package/{migrations → src/migrations}/400502_settlementTransferParticipant-decimal184.js +1 -1
- package/{migrations → src/migrations}/400600_settlementParticipantCurrency.js +1 -1
- package/{migrations → src/migrations}/400602_settlementParticipantCurrency-decimal184.js +1 -1
- package/{migrations → src/migrations}/400700_settlementParticipantCurrencyStateChange.js +1 -1
- package/{migrations → src/migrations}/400800_settlementStateChange.js +1 -1
- package/{migrations → src/migrations}/400900_settlementWindowContent.js +1 -1
- package/{migrations → src/migrations}/401000_settlementWindowContentStateChange.js +1 -1
- package/{migrations → src/migrations}/401001_settlementWindowContentStateChange-indexes.js +6 -6
- package/{migrations → src/migrations}/401200_settlementContentAggregation.js +1 -1
- package/{migrations → src/migrations}/401300_settlementModel.js +1 -1
- package/{migrations → src/migrations}/410100_transferFulfilmentDuplicateCheck.js +1 -1
- package/{migrations → src/migrations}/410102_transferFulfilmentDuplicateCheck-dropForeignTransferId.js +1 -1
- package/{migrations → src/migrations}/410103_transferFulfilmentDuplicateCheck-hashNullable.js +1 -1
- package/{migrations → src/migrations}/410200_transferFulfilment.js +1 -1
- package/{migrations → src/migrations}/410202_transferFulfilment-ilpFulfilment.js +1 -1
- package/{migrations → src/migrations}/410203_transferFulfilment-foreignTransferFulfilmentId.js +1 -1
- package/{migrations → src/migrations}/410240_bulkTransferFulfilmentDuplicateCheck.js +1 -1
- package/{migrations → src/migrations}/410250_bulkTransferFulfilment.js +1 -1
- package/{migrations → src/migrations}/410300_transferExtension.js +1 -1
- package/{migrations → src/migrations}/410302_transferExtension-transferErrorId.js +1 -1
- package/{migrations → src/migrations}/410350_bulkTransferExtension.js +1 -1
- package/{migrations → src/migrations}/410400_transferTimeout.js +1 -1
- package/{migrations → src/migrations}/410450_transferErrorDuplicateCheck.js +1 -1
- package/{migrations → src/migrations}/410500_transferError.js +1 -1
- package/{migrations → src/migrations}/410502_transferError-foreignTransferErrorDuplicateCheckId.js +1 -1
- package/{migrations → src/migrations}/410550_bulkTransferError.js +1 -1
- package/{migrations → src/migrations}/410600_expiringTransfer.js +1 -1
- package/{migrations → src/migrations}/500401_quote-hotfix-2719.js +8 -8
- package/{migrations → src/migrations}/500501_feature-fixSubIdRef.js +12 -12
- package/{migrations → src/migrations}/500601_party-2480.js +3 -3
- package/{migrations → src/migrations}/501001_quoteExtension-quote-service-174.js +1 -2
- package/{migrations → src/migrations}/501002_quoteExtension-2522.js +3 -3
- package/{migrations → src/migrations}/600010_fxTransferType.js +1 -1
- package/{migrations → src/migrations}/600012_fxParticipantCurrencyType.js +1 -1
- package/{migrations → src/migrations}/600100_fxTransferDuplicateCheck.js +2 -2
- package/{migrations → src/migrations}/600110_fxTransferErrorDuplicateCheck.js.js +1 -1
- package/{migrations → src/migrations}/600200_fxTransfer.js +2 -2
- package/{migrations → src/migrations}/600400_fxTransferStateChange.js +1 -1
- package/{migrations → src/migrations}/600501_fxWatchList.js +2 -2
- package/{migrations → src/migrations}/600600_fxTransferFulfilmentDuplicateCheck.js +1 -1
- package/{migrations → src/migrations}/600700_fxTransferFulfilment.js +1 -1
- package/{migrations → src/migrations}/600800_fxTransferExtension.js +1 -1
- package/{migrations → src/migrations}/601400_fxTransferTimeout.js +1 -1
- package/{migrations → src/migrations}/601500_fxTransferError.js +1 -1
- package/{migrations → src/migrations}/610200_fxTransferParticipant.js +1 -1
- package/{migrations → src/migrations}/610202_fxTransferParticipant-participantId.js +2 -2
- package/{migrations → src/migrations}/610403_participantPositionChange-fxTransfer.js +1 -1
- package/{migrations → src/migrations}/800100_quotePartyView.js +1 -1
- package/{migrations → src/migrations}/800101_feature-fixSubIdRef.js +1 -1
- package/{migrations → src/migrations}/800200_quoteView.js +1 -1
- package/{migrations → src/migrations}/800300_quoteResponseView.js +1 -1
- package/{migrations → src/migrations}/900100_foreign-keys.js +18 -18
- package/{migrations → src/migrations}/900101_foreign-keys.js +6 -6
- package/{migrations → src/migrations}/910100_feature904DDL.js +7 -7
- package/{migrations → src/migrations}/910101_feature904DataMigration.js +1 -1
- package/{migrations → src/migrations}/910102_feature949DataMigration.js +1 -1
- package/{migrations → src/migrations}/910103_feature1093SettlementByCurrency.js +3 -3
- package/{migrations → src/migrations}/940101_quotePartyIdInfoExtension-2522.js +25 -25
- package/{migrations → src/migrations}/950101_transferParticipantStateChange.js +2 -2
- package/{migrations → src/migrations}/950102_settlementModel-adjustPosition.js +2 -2
- package/{migrations → src/migrations}/950103_dropTransferParticipantStateChange.js +3 -3
- package/{migrations → src/migrations}/950104_settlementModel-settlementAccountTypeId.js +3 -3
- package/src/migrations/950107_settlementWindowContent_foreign_settlementModel.js +63 -0
- package/{migrations → src/migrations}/950108_participantProxy.js +1 -2
- package/{migrations → src/migrations}/950120_fxQuoteConversionTerms_sourceAmount_nullable.js +1 -1
- package/{migrations → src/migrations}/960100_create_externalParticipant.js +2 -2
- package/{migrations → src/migrations}/960110_alter_transferParticipant__addFiled_externalParticipantId.js +2 -2
- package/{migrations → src/migrations}/961001_transferForwarded.js +1 -1
- package/{migrations → src/migrations}/961002_fxTransferForwarded.js +1 -1
- package/src/models/participant/externalParticipant.int.ts +85 -0
- package/src/models/participant/facade.js +4 -2
- package/src/models/participant/participantCurrencyCached.js +1 -1
- package/src/models/position/facade.js +8 -2
- package/src/models/transfer/facade.int.ts +139 -0
- package/src/models/transfer/facade.js +8 -3
- package/src/models/transfer/transferDuplicateCheck.js +2 -2
- package/src/models/transfer/transferError.int.ts +112 -0
- package/src/models/transfer/transferExtension.int.ts +137 -0
- package/src/models/transfer/transferStateChange.int.ts +117 -0
- package/{seeds → src/seeds}/participant.js +1 -1
- package/{seeds → src/seeds}/settlementInterchange.js +1 -0
- package/src/settlement/api/handlerRoutes.js +71 -0
- package/src/settlement/api/handlers/health.js +10 -0
- package/src/settlement/api/handlers/index.js +57 -0
- package/src/settlement/api/handlers/settlementWindows/{id}.js +103 -0
- package/src/settlement/api/handlers/settlementWindows.js +77 -0
- package/src/settlement/api/handlers/settlements/{id}.js +133 -0
- package/src/settlement/api/handlers/settlements/{sid}/participants/{pid}/accounts/{aid}.js +127 -0
- package/src/settlement/api/handlers/settlements/{sid}/participants/{pid}.js +127 -0
- package/src/settlement/api/handlers/settlements.js +114 -0
- package/src/settlement/api/openapiRouting.js +87 -0
- package/src/settlement/api/routes.js +176 -0
- package/src/settlement/domain/rules/index.js +46 -0
- package/src/settlement/domain/settlement/index.js +405 -0
- package/src/settlement/domain/settlementWindow/index.js +117 -0
- package/src/settlement/domain/transactions/index.js +83 -0
- package/src/settlement/domain/transferSettlement/index.js +57 -0
- package/src/settlement/handlers/deferredSettlement/handler.js +180 -0
- package/src/settlement/handlers/grossSettlement/handler.js +180 -0
- package/src/settlement/handlers/index.js +101 -0
- package/src/settlement/handlers/register.js +92 -0
- package/src/settlement/handlers/rules/handler.js +164 -0
- package/src/settlement/interface/swagger-handler.json +34 -0
- package/src/settlement/interface/swagger.json +1560 -0
- package/src/settlement/lib/db.js +32 -0
- package/src/settlement/lib/kafka/index.js +41 -0
- package/src/settlement/lib/kafka/producer.js +142 -0
- package/src/settlement/lib/scriptEngine.js +99 -0
- package/src/settlement/lib/scriptsLoader.js +175 -0
- package/src/settlement/lib/utility.js +243 -0
- package/src/settlement/models/ilpPackets/ilpPacket.js +42 -0
- package/src/settlement/models/lib/enums.js +192 -0
- package/src/settlement/models/misc/migrationLock.js +53 -0
- package/src/settlement/models/settlement/facade.js +1652 -0
- package/src/settlement/models/settlement/index.js +55 -0
- package/src/settlement/models/settlement/participantCurrency.js +48 -0
- package/src/settlement/models/settlement/settlement.js +49 -0
- package/src/settlement/models/settlement/settlementModel.js +44 -0
- package/src/settlement/models/settlement/settlementParticipantCurrency.js +61 -0
- package/src/settlement/models/settlement/settlementStateChange.js +44 -0
- package/src/settlement/models/settlement/settlementTransferParticipant.js +46 -0
- package/src/settlement/models/settlementWindow/facade.js +345 -0
- package/src/settlement/models/settlementWindow/index.js +47 -0
- package/src/settlement/models/settlementWindow/settlementWindowStateChange.js +55 -0
- package/src/settlement/models/settlementWindowContent/facade.js +79 -0
- package/src/settlement/models/settlementWindowContent/index.js +40 -0
- package/src/settlement/models/settlementWindowContent/settlementWindowContentStateChange.js +53 -0
- package/src/settlement/models/transferSettlement/facade.js +363 -0
- package/src/settlement/models/transferSettlement/index.js +42 -0
- package/src/settlement/shared/logger/index.js +7 -0
- package/src/settlement/shared/plugins.js +88 -0
- package/src/settlement/shared/setup.js +224 -0
- package/src/settlement/utils/truthyProperty.js +37 -0
- package/src/shared/legacyUtilShim.js +20 -0
- package/src/shared/plugins.js +3 -3
- package/src/shared/results.ts +22 -0
- package/src/shared/results.unit.ts +38 -0
- package/src/shared/setup.js +14 -1
- package/src/testing/api-helpers.ts +1222 -0
- package/src/testing/exec-async.ts +67 -0
- package/src/testing/harness.snapshot.sql +3895 -0
- package/src/testing/harness.test.ts +15 -0
- package/src/testing/harness.ts +1160 -0
- package/src/testing/kafka.ts +221 -0
- package/src/testing/prng.ts +82 -0
- package/src/testing/rdkafka.test.ts +263 -0
- package/src/testing/run.ts +559 -0
- package/src/testing/snapshot.test.ts +92 -0
- package/src/testing/snapshot.ts +549 -0
- package/src/testing/tap-stream.ts +164 -0
- package/src/testing/types.ts +95 -0
- package/src/testing/util.ts +333 -0
- package/src/types/central-services-error-handling.d.ts +72 -0
- package/src/types/central-services-stream.d.ts +148 -0
- package/test-integration.Dockerfile +0 -2
- package/test.Dockerfile +0 -2
- package/tsconfig.json +40 -0
- package/config/knexfile.js +0 -19
- package/migrations/950107_settlementWindowContent_foreign_settlementModel.js +0 -63
- package/src/api/index.js +0 -16
- package/src/lib/config.js +0 -81
- /package/{migrations → src/migrations}/110101_contactType-indexes.js +0 -0
- /package/{migrations → src/migrations}/110301_endpointType-indexes.js +0 -0
- /package/{migrations → src/migrations}/110401_ledgerEntryType-indexes.js +0 -0
- /package/{migrations → src/migrations}/110451_ledgerAccountType-indexes.js +0 -0
- /package/{migrations → src/migrations}/110501_participantLimitType-indexes.js +0 -0
- /package/{migrations → src/migrations}/110601_transferParticipantRoleType-indexes.js +0 -0
- /package/{migrations → src/migrations}/110800_settlementWindowState.js +0 -0
- /package/{migrations → src/migrations}/111000_amountType.js +0 -0
- /package/{migrations → src/migrations}/111001_amountType-indexes.js +0 -0
- /package/{migrations → src/migrations}/111100_balanceOfPayments.js +0 -0
- /package/{migrations → src/migrations}/111101_balanceOfPayments-indexes.js +0 -0
- /package/{migrations → src/migrations}/111200_partyIdentifierType.js +0 -0
- /package/{migrations → src/migrations}/111201_partyIdentifierType-indexes.js +0 -0
- /package/{migrations → src/migrations}/111300_partyType.js +0 -0
- /package/{migrations → src/migrations}/111301_partyType-indexes.js +0 -0
- /package/{migrations → src/migrations}/111400_quoteDuplicateCheck.js +0 -0
- /package/{migrations → src/migrations}/111500_transactionInitiator.js +0 -0
- /package/{migrations → src/migrations}/111501_transactionInitiator-indexes.js +0 -0
- /package/{migrations → src/migrations}/111600_transactionInitiatorType.js +0 -0
- /package/{migrations → src/migrations}/111601_transactionInitiatorType-indexes.js +0 -0
- /package/{migrations → src/migrations}/111700_settlementDelay.js +0 -0
- /package/{migrations → src/migrations}/111701_settlementDelay-indexes.js +0 -0
- /package/{migrations → src/migrations}/111800_settlementInterchange.js +0 -0
- /package/{migrations → src/migrations}/111801_settlementInterchange-indexes.js +0 -0
- /package/{migrations → src/migrations}/111900_settlementGranularity.js +0 -0
- /package/{migrations → src/migrations}/111901_settlementGranularity-indexes.js +0 -0
- /package/{migrations → src/migrations}/112101_bulkProcessingState-indexes.js +0 -0
- /package/{migrations → src/migrations}/200101_participant-indexes.js +0 -0
- /package/{migrations → src/migrations}/200201_participantContact-indexes.js +0 -0
- /package/{migrations → src/migrations}/200301_participantEndpoint-indexes.js +0 -0
- /package/{migrations → src/migrations}/200401_participantParty-indexes.js +0 -0
- /package/{migrations → src/migrations}/300201_transfer-indexes.js +0 -0
- /package/{migrations → src/migrations}/300251_bulkTransfer-indexes.js +0 -0
- /package/{migrations → src/migrations}/300276_bulkTransferAssociation-indexes.js +0 -0
- /package/{migrations → src/migrations}/300401_transferStateChange-indexes.js +0 -0
- /package/{migrations → src/migrations}/300451_bulkTransferStateChange-indexes.js +0 -0
- /package/{migrations → src/migrations}/300501_segment-indexes.js +0 -0
- /package/{migrations → src/migrations}/310101_participantCurrency-indexes.js +0 -0
- /package/{migrations → src/migrations}/310201_transferParticipant-indexes.js +0 -0
- /package/{migrations → src/migrations}/310203_transferParticipant-indexes.js +0 -0
- /package/{migrations → src/migrations}/310301_participantPosition-indexes.js +0 -0
- /package/{migrations → src/migrations}/310401_participantPositionChange-indexes.js +0 -0
- /package/{migrations → src/migrations}/310405_participantPositionChange-positionChange.js +0 -0
- /package/{migrations → src/migrations}/310406_participantPositionChange-positionChange-revert.js +0 -0
- /package/{migrations → src/migrations}/310501_participantLimit-indexes.js +0 -0
- /package/{migrations → src/migrations}/310503_participantLimit-indexes-composite.js +0 -0
- /package/{migrations → src/migrations}/400401_settlmentWindowStateChange-indexes.js +0 -0
- /package/{migrations → src/migrations}/400501_settlementTransferParticipant-indexes.js +0 -0
- /package/{migrations → src/migrations}/400601_settlementParticipantCurrency-indexes.js +0 -0
- /package/{migrations → src/migrations}/400701_settlementParticipantCurrencyStateChange-indexes.js +0 -0
- /package/{migrations → src/migrations}/400801_settlementStateChange-indexes.js +0 -0
- /package/{migrations → src/migrations}/401002_settlementWindowContent-indexes.js +0 -0
- /package/{migrations → src/migrations}/401201_settlementContentAggregation-indexes.js +0 -0
- /package/{migrations → src/migrations}/401301_settlementModel-indexes.js +0 -0
- /package/{migrations → src/migrations}/410101_transferFulfilmentDuplicateCheck-indexes.js +0 -0
- /package/{migrations → src/migrations}/410201_transferFulfilment-indexes.js +0 -0
- /package/{migrations → src/migrations}/410301_transferExtension-indexes.js +0 -0
- /package/{migrations → src/migrations}/410351_bulkTransferExtension-indexes.js +0 -0
- /package/{migrations → src/migrations}/410401_transferTimeout-indexes.js +0 -0
- /package/{migrations → src/migrations}/410501_transferError-indexes.js +0 -0
- /package/{migrations → src/migrations}/410551_bulkTransferError-indexes.js +0 -0
- /package/{migrations → src/migrations}/410601_expiringTransfer-indexes.js +0 -0
- /package/{migrations → src/migrations}/500100_transactionReference.js +0 -0
- /package/{migrations → src/migrations}/500101_transactionReference-indexes.js +0 -0
- /package/{migrations → src/migrations}/500200_transactionScenario.js +0 -0
- /package/{migrations → src/migrations}/500201_transactionScenario-indexes.js +0 -0
- /package/{migrations → src/migrations}/500300_transactionSubScenario.js +0 -0
- /package/{migrations → src/migrations}/500400_quote.js +0 -0
- /package/{migrations → src/migrations}/500500_quoteParty.js +0 -0
- /package/{migrations → src/migrations}/500600_party.js +0 -0
- /package/{migrations → src/migrations}/500700_quoteResponse.js +0 -0
- /package/{migrations → src/migrations}/500800_quoteResponseIlpPacket.js +0 -0
- /package/{migrations → src/migrations}/500900_geoCode.js +0 -0
- /package/{migrations → src/migrations}/501000_quoteExtension.js +0 -0
- /package/{migrations → src/migrations}/501100_quoteResponseDuplicateCheck.js +0 -0
- /package/{migrations → src/migrations}/501200_quoteError.js +0 -0
- /package/{migrations → src/migrations}/501300_transferRules.js +0 -0
- /package/{migrations → src/migrations}/600011_fxTransferType-indexes.js +0 -0
- /package/{migrations → src/migrations}/600013_fxParticipantCurrencyType-indexes.js +0 -0
- /package/{migrations → src/migrations}/600201_fxTransfer-indexes.js +0 -0
- /package/{migrations → src/migrations}/600401_fxTransferStateChange-indexes.js +0 -0
- /package/{migrations → src/migrations}/600502_fxWatchList-indexes.js +0 -0
- /package/{migrations → src/migrations}/600601_fxTransferFulfilmentDuplicateCheck-indexes.js +0 -0
- /package/{migrations → src/migrations}/600701_fxTransferFulfilment-indexes.js +0 -0
- /package/{migrations → src/migrations}/601401_fxTransferTimeout-indexes.js +0 -0
- /package/{migrations → src/migrations}/601501_fxTransferError-indexes.js +0 -0
- /package/{migrations → src/migrations}/610201_fxTransferParticipant-indexes.js +0 -0
- /package/{migrations → src/migrations}/910102_hotfix954.js +0 -0
- /package/{migrations → src/migrations}/940100_quotePartyIdInfoExtension.js +0 -0
- /package/{migrations → src/migrations}/950100_settlementContentAggregation-decimal184.js +0 -0
- /package/{migrations → src/migrations}/950106_unique_settlement_model_ledger_account_currency.js +0 -0
- /package/{migrations → src/migrations}/950109_fxQuote.js +0 -0
- /package/{migrations → src/migrations}/950110_fxQuoteResponse.js +0 -0
- /package/{migrations → src/migrations}/950111_fxQuoteError.js +0 -0
- /package/{migrations → src/migrations}/950113_fxQuoteDuplicateCheck.js +0 -0
- /package/{migrations → src/migrations}/950114_fxQuoteResponseDuplicateCheck.js +0 -0
- /package/{migrations → src/migrations}/950115_fxQuoteConversionTerms.js +0 -0
- /package/{migrations → src/migrations}/950116_fxQuoteConversionTermsExtension.js +0 -0
- /package/{migrations → src/migrations}/950117_fxQuoteResponseConversionTerms.js +0 -0
- /package/{migrations → src/migrations}/950118_fxQuoteResponseConversionTermsExtension.js +0 -0
- /package/{migrations → src/migrations}/950119_fxCharge.js +0 -0
- /package/{migrations → src/migrations}/960111_alter_fxTransferParticipant__addFiled_externalParticipantId.js +0 -0
- /package/{migrations → src/migrations}/960112_fxTransfer-indexes2.js +0 -0
- /package/{migrations → src/migrations}/960113_fxTransferExtension-indexes.js +0 -0
- /package/{migrations → src/migrations}/960114_fxTransferTimeout-indexes2.js +0 -0
- /package/{migrations → src/migrations}/961000_participantEndpoint_unique.js +0 -0
- /package/{migrations → src/migrations}/migration.template +0 -0
- /package/{seeds → src/seeds}/amountType.js +0 -0
- /package/{seeds → src/seeds}/balanceOfPayments.js +0 -0
- /package/{seeds → src/seeds}/bulkProcessingState.js +0 -0
- /package/{seeds → src/seeds}/bulkTransferState.js +0 -0
- /package/{seeds → src/seeds}/currency.js +0 -0
- /package/{seeds → src/seeds}/endpointType.js +0 -0
- /package/{seeds → src/seeds}/fxParticipantCurrencyType.js +0 -0
- /package/{seeds → src/seeds}/fxTransferType.js +0 -0
- /package/{seeds → src/seeds}/ledgerAccountType.js +0 -0
- /package/{seeds → src/seeds}/ledgerEntryType.js +0 -0
- /package/{seeds → src/seeds}/participantLimitType.js +0 -0
- /package/{seeds → src/seeds}/partyIdentifierType.js +0 -0
- /package/{seeds → src/seeds}/partyType.js +0 -0
- /package/{seeds → src/seeds}/settlementDelay.js +0 -0
- /package/{seeds → src/seeds}/settlementGranularity.js +0 -0
- /package/{seeds → src/seeds}/settlementState.js +0 -0
- /package/{seeds → src/seeds}/settlementWindow1State.js +0 -0
- /package/{seeds → src/seeds}/settlementWindow2Open.js +0 -0
- /package/{seeds → src/seeds}/transactionInitiator.js +0 -0
- /package/{seeds → src/seeds}/transactionInitiatorType.js +0 -0
- /package/{seeds → src/seeds}/transactionScenario.js +0 -0
- /package/{seeds → src/seeds}/transferParticipantRoleType.js +0 -0
- /package/{seeds → src/seeds}/transferState.js +0 -0
- /package/{seeds → src/seeds}/z1000_settlementModel-deprecated.js- +0 -0
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
/*****
|
|
2
|
+
License
|
|
3
|
+
--------------
|
|
4
|
+
Copyright © 2020-2026 Mojaloop Foundation
|
|
5
|
+
The Mojaloop files are made available by the Mojaloop 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
|
+
|
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
|
|
9
|
+
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.
|
|
10
|
+
|
|
11
|
+
Contributors
|
|
12
|
+
--------------
|
|
13
|
+
This is the official list of the Mojaloop project contributors for this file.
|
|
14
|
+
Names of the original copyright holders (individuals or organizations)
|
|
15
|
+
should be listed with a '*' in the first column. People who have
|
|
16
|
+
contributed from an organization can be listed under the organization
|
|
17
|
+
that actually holds the copyright for their contributions (see the
|
|
18
|
+
Mojaloop Foundation for an example). Those individuals should have
|
|
19
|
+
their names indented and be marked with a '-'. Email address can be added
|
|
20
|
+
optionally within square brackets <email>.
|
|
21
|
+
|
|
22
|
+
* TigerBeetle
|
|
23
|
+
- Lewis Daly <lewis@tigerbeetle.com>
|
|
24
|
+
--------------
|
|
25
|
+
******/
|
|
26
|
+
|
|
27
|
+
import { after, before, describe, it } from "node:test"
|
|
28
|
+
import Harness from '../../testing/harness'
|
|
29
|
+
import { Snapshot } from "../../testing/snapshot"
|
|
30
|
+
import * as ApiHelpers from '../../testing/api-helpers'
|
|
31
|
+
import assert from "node:assert"
|
|
32
|
+
|
|
33
|
+
const harness = Harness.getInstance()
|
|
34
|
+
let TransferHandler: any
|
|
35
|
+
let FxTransferService: any
|
|
36
|
+
|
|
37
|
+
describe('handlers/fx', () => {
|
|
38
|
+
before(async () => {
|
|
39
|
+
await harness.up('BATCH')
|
|
40
|
+
await harness.setupGlobals()
|
|
41
|
+
|
|
42
|
+
// Import after bringing up the harness, so that global config is overriden.
|
|
43
|
+
TransferHandler = require('./handler')
|
|
44
|
+
FxTransferService = require('../../domain/fx/index')
|
|
45
|
+
await TransferHandler.registerPrepareHandler()
|
|
46
|
+
await TransferHandler.registerFulfilHandler()
|
|
47
|
+
|
|
48
|
+
// Create the hub accounts + settlement model.
|
|
49
|
+
const createHubPayload: ApiHelpers.CreateHubPayload = {
|
|
50
|
+
currencies: ['BWP', 'USD'],
|
|
51
|
+
settlementModels: [
|
|
52
|
+
{
|
|
53
|
+
name: `DEFERRED_MULTILATERAL_NET_BWP`,
|
|
54
|
+
settlementGranularity: "NET",
|
|
55
|
+
settlementInterchange: "MULTILATERAL",
|
|
56
|
+
settlementDelay: "DEFERRED",
|
|
57
|
+
currency: 'BWP',
|
|
58
|
+
requireLiquidityCheck: true,
|
|
59
|
+
ledgerAccountType: "POSITION",
|
|
60
|
+
settlementAccountType: "SETTLEMENT",
|
|
61
|
+
autoPositionReset: true
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
name: `DEFERRED_MULTILATERAL_NET_USD`,
|
|
65
|
+
settlementGranularity: "NET",
|
|
66
|
+
settlementInterchange: "MULTILATERAL",
|
|
67
|
+
settlementDelay: "DEFERRED",
|
|
68
|
+
currency: 'USD',
|
|
69
|
+
requireLiquidityCheck: true,
|
|
70
|
+
ledgerAccountType: "POSITION",
|
|
71
|
+
settlementAccountType: "SETTLEMENT",
|
|
72
|
+
autoPositionReset: true
|
|
73
|
+
}
|
|
74
|
+
]
|
|
75
|
+
}
|
|
76
|
+
await ApiHelpers.createHub(harness, createHubPayload)
|
|
77
|
+
// Create 2 test dfsps to transfer between.
|
|
78
|
+
await ApiHelpers.createDfsp(harness, {
|
|
79
|
+
name: 'dfsp_a',
|
|
80
|
+
currencies: ['BWP'],
|
|
81
|
+
isProxy: false,
|
|
82
|
+
initialPostionsAndLimits: [{ initialPosition: 0, value: 100000 }],
|
|
83
|
+
deposits: [10000]
|
|
84
|
+
})
|
|
85
|
+
await ApiHelpers.createDfsp(harness, {
|
|
86
|
+
name: 'dfsp_b',
|
|
87
|
+
currencies: ['BWP', 'USD'],
|
|
88
|
+
isProxy: false,
|
|
89
|
+
initialPostionsAndLimits: [
|
|
90
|
+
{ initialPosition: 0, value: 100000 },
|
|
91
|
+
{ initialPosition: 0, value: 100000 }
|
|
92
|
+
],
|
|
93
|
+
deposits: [10000, 10000]
|
|
94
|
+
})
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
after(async () => {
|
|
98
|
+
await harness.teardownGlobals()
|
|
99
|
+
await harness.down()
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
it(`should publish a message to send error callback if fxTransfer does not exist`, async () => {
|
|
103
|
+
const forex = ApiHelpers.buildForex()
|
|
104
|
+
.deps(harness, TransferHandler)
|
|
105
|
+
.commitRequestId('4000001')
|
|
106
|
+
.determiningTransferId('5000001')
|
|
107
|
+
.parties('dfsp_b', 'dfsp_a')
|
|
108
|
+
.amountSource('100.00', 'BWP')
|
|
109
|
+
.amountTarget('10.00', 'USD')
|
|
110
|
+
.build()
|
|
111
|
+
|
|
112
|
+
const mark = harness.redpandaMark()
|
|
113
|
+
await TransferHandler.fulfil(null, forex.buildMessageFulfil())
|
|
114
|
+
await harness.redpandaDrain(mark, 1)
|
|
115
|
+
|
|
116
|
+
Snapshot.from(`[
|
|
117
|
+
{
|
|
118
|
+
"errorInformation": {
|
|
119
|
+
"errorCode": "3208",
|
|
120
|
+
"errorDescription": "Transfer ID not found - fxTransfer not found",
|
|
121
|
+
"extensionList": {
|
|
122
|
+
"extension": [
|
|
123
|
+
{
|
|
124
|
+
"key": "cause",
|
|
125
|
+
"value": "FSPIOPError: fxTransfer not found:ignore
|
|
126
|
+
}
|
|
127
|
+
]
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
]`).checkUnwrap(harness.spoolLastPayload(1))
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
it(`should process fxFulfil message (happy path)`, async () => {
|
|
135
|
+
const forex = ApiHelpers.buildForex()
|
|
136
|
+
.deps(harness, TransferHandler)
|
|
137
|
+
.commitRequestId('4000002')
|
|
138
|
+
.determiningTransferId('5000002')
|
|
139
|
+
.parties('dfsp_a', 'dfsp_b')
|
|
140
|
+
.amountSource('100.00', 'BWP')
|
|
141
|
+
.amountTarget('10.00', 'USD')
|
|
142
|
+
.build()
|
|
143
|
+
|
|
144
|
+
await forex.prepare()
|
|
145
|
+
let fxTransfer = await FxTransferService.getByIdLight('4000002')
|
|
146
|
+
|
|
147
|
+
Snapshot.from(`{
|
|
148
|
+
"commitRequestId": "4000002",
|
|
149
|
+
"determiningTransferId": "5000002",
|
|
150
|
+
"sourceAmount": "100.0000",
|
|
151
|
+
"targetAmount": "10.0000",
|
|
152
|
+
"sourceCurrency": "BWP",
|
|
153
|
+
"targetCurrency": "USD",
|
|
154
|
+
"ilpCondition": :ignore
|
|
155
|
+
"expirationDate": :ignore
|
|
156
|
+
"createdDate": :ignore
|
|
157
|
+
"fxTransferStateChangeId": :ignore
|
|
158
|
+
"fxTransferState": "RESERVED",
|
|
159
|
+
"fxTransferStateEnumeration": "RESERVED",
|
|
160
|
+
"fxTransferStateDescription": "The switch has reserved the transfer.",
|
|
161
|
+
"reason": null,
|
|
162
|
+
"completedTimestamp": :ignore
|
|
163
|
+
"condition": :ignore
|
|
164
|
+
"fulfilment": null
|
|
165
|
+
}`).checkUnwrap(fxTransfer)
|
|
166
|
+
|
|
167
|
+
await forex.fulfil()
|
|
168
|
+
fxTransfer = await FxTransferService.getByIdLight('4000002')
|
|
169
|
+
|
|
170
|
+
Snapshot.from(`{
|
|
171
|
+
"commitRequestId": "4000002",
|
|
172
|
+
"determiningTransferId": "5000002",
|
|
173
|
+
"sourceAmount": "100.0000",
|
|
174
|
+
"targetAmount": "10.0000",
|
|
175
|
+
"sourceCurrency": "BWP",
|
|
176
|
+
"targetCurrency": "USD",
|
|
177
|
+
"ilpCondition": :ignore
|
|
178
|
+
"expirationDate": :ignore
|
|
179
|
+
"createdDate": :ignore
|
|
180
|
+
"fxTransferStateChangeId": 3,
|
|
181
|
+
"fxTransferState": "RECEIVED_FULFIL_DEPENDENT",
|
|
182
|
+
"fxTransferStateEnumeration": "RESERVED",
|
|
183
|
+
"fxTransferStateDescription": "The switch has reserved the fxTransfer fulfilment.",
|
|
184
|
+
"reason": null,
|
|
185
|
+
"completedTimestamp": :ignore
|
|
186
|
+
"condition": :ignore
|
|
187
|
+
"fulfilment": :ignore
|
|
188
|
+
}`).checkUnwrap(fxTransfer)
|
|
189
|
+
|
|
190
|
+
})
|
|
191
|
+
|
|
192
|
+
it(`should check duplicates, and detect modified request`, async () => {
|
|
193
|
+
const fxId = '4000003'
|
|
194
|
+
const forexA = ApiHelpers.buildForex()
|
|
195
|
+
.deps(harness, TransferHandler)
|
|
196
|
+
.commitRequestId(fxId)
|
|
197
|
+
.determiningTransferId('5000003')
|
|
198
|
+
.parties('dfsp_a', 'dfsp_b')
|
|
199
|
+
.amountSource('100.00', 'BWP')
|
|
200
|
+
.amountTarget('10.00', 'USD')
|
|
201
|
+
.build()
|
|
202
|
+
|
|
203
|
+
const forexB = ApiHelpers.buildForex()
|
|
204
|
+
.deps(harness, TransferHandler)
|
|
205
|
+
.commitRequestId(fxId)
|
|
206
|
+
.determiningTransferId('5000003')
|
|
207
|
+
.parties('dfsp_b', 'dfsp_a')
|
|
208
|
+
.amountSource('100.00', 'BWP')
|
|
209
|
+
.amountTarget('10.00', 'USD')
|
|
210
|
+
.build()
|
|
211
|
+
|
|
212
|
+
// Prepare the first.
|
|
213
|
+
await forexA.prepare()
|
|
214
|
+
|
|
215
|
+
// Manually prepare the 2nd.
|
|
216
|
+
const mark = harness.redpandaMark()
|
|
217
|
+
await TransferHandler.prepare(null, forexB.buildMessagePrepare())
|
|
218
|
+
await harness.redpandaDrain(mark, 1)
|
|
219
|
+
|
|
220
|
+
Snapshot.from(`[
|
|
221
|
+
{
|
|
222
|
+
"errorInformation": {
|
|
223
|
+
"errorCode": "3106",
|
|
224
|
+
"errorDescription": "Modified request",
|
|
225
|
+
"extensionList": {
|
|
226
|
+
"extension": [
|
|
227
|
+
{
|
|
228
|
+
"key": "cause",
|
|
229
|
+
"value": :ignore
|
|
230
|
+
}
|
|
231
|
+
]
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
]`).checkUnwrap(harness.spoolLastPayload(1))
|
|
236
|
+
})
|
|
237
|
+
|
|
238
|
+
it(`should detect an invalid fulfilment`, async () => {
|
|
239
|
+
const forex = ApiHelpers.buildForex()
|
|
240
|
+
.deps(harness, TransferHandler)
|
|
241
|
+
.commitRequestId('4000004')
|
|
242
|
+
.determiningTransferId('5000004')
|
|
243
|
+
.parties('dfsp_a', 'dfsp_b')
|
|
244
|
+
.amountSource('100.00', 'BWP')
|
|
245
|
+
.amountTarget('10.00', 'USD')
|
|
246
|
+
.build()
|
|
247
|
+
|
|
248
|
+
await forex.prepare()
|
|
249
|
+
|
|
250
|
+
// Manually override the fulfilment.
|
|
251
|
+
const messageFulfil = forex.buildMessageFulfil()
|
|
252
|
+
assert(messageFulfil.value.content.payload)
|
|
253
|
+
messageFulfil.value.content.payload.fulfilment = 'invalid-fulfilment'
|
|
254
|
+
const mark = harness.redpandaMark()
|
|
255
|
+
await TransferHandler.fulfil(null, messageFulfil)
|
|
256
|
+
await harness.redpandaDrain(mark, 1)
|
|
257
|
+
|
|
258
|
+
Snapshot.from(`[
|
|
259
|
+
{
|
|
260
|
+
"errorInformation": {
|
|
261
|
+
"errorCode": "3100",
|
|
262
|
+
"errorDescription": "Generic validation error - Invalid FX fulfilment",
|
|
263
|
+
"extensionList": {
|
|
264
|
+
"extension": [
|
|
265
|
+
{
|
|
266
|
+
"key": "cause",
|
|
267
|
+
"value": "FSPIOPError: Invalid FX:ignore
|
|
268
|
+
}
|
|
269
|
+
]
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
]`).checkUnwrap(harness.spoolLastPayload(1))
|
|
274
|
+
})
|
|
275
|
+
})
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
/*****
|
|
2
|
+
License
|
|
3
|
+
--------------
|
|
4
|
+
Copyright © 2020-2026 Mojaloop Foundation
|
|
5
|
+
The Mojaloop files are made available by the Mojaloop 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
|
+
|
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
|
|
9
|
+
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.
|
|
10
|
+
|
|
11
|
+
Contributors
|
|
12
|
+
--------------
|
|
13
|
+
This is the official list of the Mojaloop project contributors for this file.
|
|
14
|
+
Names of the original copyright holders (individuals or organizations)
|
|
15
|
+
should be listed with a '*' in the first column. People who have
|
|
16
|
+
contributed from an organization can be listed under the organization
|
|
17
|
+
that actually holds the copyright for their contributions (see the
|
|
18
|
+
Mojaloop Foundation for an example). Those individuals should have
|
|
19
|
+
their names indented and be marked with a '-'. Email address can be added
|
|
20
|
+
optionally within square brackets <email>.
|
|
21
|
+
|
|
22
|
+
* TigerBeetle
|
|
23
|
+
- Lewis Daly <lewis@tigerbeetle.com>
|
|
24
|
+
--------------
|
|
25
|
+
******/
|
|
26
|
+
|
|
27
|
+
import { after, before, describe, it } from "node:test"
|
|
28
|
+
import Harness from '../../testing/harness'
|
|
29
|
+
import { Snapshot } from "../../testing/snapshot"
|
|
30
|
+
import * as ApiHelpers from '../../testing/api-helpers'
|
|
31
|
+
import assert from "node:assert"
|
|
32
|
+
import { assertPositionDiff, sleepSeconds } from "../../testing/util"
|
|
33
|
+
import TimeoutHandler from '../timeouts/handler'
|
|
34
|
+
|
|
35
|
+
const harness = Harness.getInstance()
|
|
36
|
+
let PrepareHandler: any
|
|
37
|
+
let TransferHandler: any
|
|
38
|
+
let PositionBatchHandler: any
|
|
39
|
+
let ExternalParticipantCached: any
|
|
40
|
+
let TransferFacade: any
|
|
41
|
+
let FxTransferService: any
|
|
42
|
+
let proxyCache: any
|
|
43
|
+
|
|
44
|
+
describe('handlers/tx-timeout', () => {
|
|
45
|
+
before(async () => {
|
|
46
|
+
await harness.up('BATCH')
|
|
47
|
+
await harness.setupGlobals()
|
|
48
|
+
|
|
49
|
+
// Import after bringing up the harness, so that global config is overriden.
|
|
50
|
+
TransferHandler = require('./handler')
|
|
51
|
+
PrepareHandler = require('./prepare')
|
|
52
|
+
PositionBatchHandler = require('../positions/handlerBatch')
|
|
53
|
+
TransferFacade = require('../../models/transfer/facade')
|
|
54
|
+
FxTransferService = require('../../domain/fx/index')
|
|
55
|
+
ExternalParticipantCached = require('../../models/participant/externalParticipantCached')
|
|
56
|
+
proxyCache = require('../../lib/proxyCache')
|
|
57
|
+
await proxyCache.connect()
|
|
58
|
+
await TransferHandler.registerPrepareHandler()
|
|
59
|
+
await TransferHandler.registerFulfilHandler()
|
|
60
|
+
|
|
61
|
+
// Create the hub accounts + settlement model.
|
|
62
|
+
const createHubPayload: ApiHelpers.CreateHubPayload = {
|
|
63
|
+
currencies: ['BWP', 'USD'],
|
|
64
|
+
settlementModels: [
|
|
65
|
+
{
|
|
66
|
+
name: `DEFERRED_MULTILATERAL_NET_BWP`,
|
|
67
|
+
settlementGranularity: "NET",
|
|
68
|
+
settlementInterchange: "MULTILATERAL",
|
|
69
|
+
settlementDelay: "DEFERRED",
|
|
70
|
+
currency: 'BWP',
|
|
71
|
+
requireLiquidityCheck: true,
|
|
72
|
+
ledgerAccountType: "POSITION",
|
|
73
|
+
settlementAccountType: "SETTLEMENT",
|
|
74
|
+
autoPositionReset: true
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
name: `DEFERRED_MULTILATERAL_NET_USD`,
|
|
78
|
+
settlementGranularity: "NET",
|
|
79
|
+
settlementInterchange: "MULTILATERAL",
|
|
80
|
+
settlementDelay: "DEFERRED",
|
|
81
|
+
currency: 'USD',
|
|
82
|
+
requireLiquidityCheck: true,
|
|
83
|
+
ledgerAccountType: "POSITION",
|
|
84
|
+
settlementAccountType: "SETTLEMENT",
|
|
85
|
+
autoPositionReset: true
|
|
86
|
+
}
|
|
87
|
+
]
|
|
88
|
+
}
|
|
89
|
+
await ApiHelpers.createHub(harness, createHubPayload)
|
|
90
|
+
// Create 2 test dfsps to transfer between.
|
|
91
|
+
await ApiHelpers.createDfsp(harness, {
|
|
92
|
+
name: 'dfsp_a',
|
|
93
|
+
currencies: ['BWP'],
|
|
94
|
+
isProxy: false,
|
|
95
|
+
initialPostionsAndLimits: [{ initialPosition: 0, value: 100000 }],
|
|
96
|
+
deposits: [10000]
|
|
97
|
+
})
|
|
98
|
+
await ApiHelpers.createDfsp(harness, {
|
|
99
|
+
name: 'dfsp_b',
|
|
100
|
+
currencies: ['BWP', 'USD'],
|
|
101
|
+
isProxy: false,
|
|
102
|
+
initialPostionsAndLimits: [
|
|
103
|
+
{ initialPosition: 0, value: 100000 },
|
|
104
|
+
{ initialPosition: 0, value: 100000 }
|
|
105
|
+
],
|
|
106
|
+
deposits: [10000, 10000]
|
|
107
|
+
})
|
|
108
|
+
await ApiHelpers.createDfsp(harness, {
|
|
109
|
+
name: 'dfsp_a_proxy',
|
|
110
|
+
currencies: ['BWP', 'USD'],
|
|
111
|
+
isProxy: true,
|
|
112
|
+
initialPostionsAndLimits: [
|
|
113
|
+
{ initialPosition: 0, value: 100000 },
|
|
114
|
+
{ initialPosition: 0, value: 100000 }
|
|
115
|
+
],
|
|
116
|
+
deposits: [10000, 10000]
|
|
117
|
+
})
|
|
118
|
+
await ApiHelpers.createDfsp(harness, {
|
|
119
|
+
name: 'dfsp_b_proxy',
|
|
120
|
+
currencies: ['BWP', 'USD'],
|
|
121
|
+
isProxy: true,
|
|
122
|
+
initialPostionsAndLimits: [
|
|
123
|
+
{ initialPosition: 0, value: 100000 },
|
|
124
|
+
{ initialPosition: 0, value: 100000 }
|
|
125
|
+
],
|
|
126
|
+
deposits: [10000, 10000]
|
|
127
|
+
})
|
|
128
|
+
await ApiHelpers.createDfsp(harness, {
|
|
129
|
+
name: 'fxp_a',
|
|
130
|
+
currencies: ['BWP', 'USD'],
|
|
131
|
+
isProxy: false,
|
|
132
|
+
initialPostionsAndLimits: [
|
|
133
|
+
{ initialPosition: 0, value: 100000 },
|
|
134
|
+
{ initialPosition: 0, value: 100000 }
|
|
135
|
+
],
|
|
136
|
+
deposits: [10000, 10000]
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
// Set up the proxy1 currencies.
|
|
140
|
+
await proxyCache.getCache().addDfspIdToProxyMapping('external_dfsp_a', 'dfsp_a_proxy')
|
|
141
|
+
await proxyCache.getCache().addDfspIdToProxyMapping('external_dfsp_b', 'dfsp_b_proxy')
|
|
142
|
+
|
|
143
|
+
// Create payment of $100.00 USD from dfsp_a to dfsp_b with id 1000001.
|
|
144
|
+
await ApiHelpers.buildPayment()
|
|
145
|
+
.deps(harness, TransferHandler)
|
|
146
|
+
.parties('dfsp_a', 'dfsp_b')
|
|
147
|
+
.transferId('1000001')
|
|
148
|
+
.amount('1.00', 'BWP')
|
|
149
|
+
.build()
|
|
150
|
+
.prepareAndFulfil()
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
after(async () => {
|
|
154
|
+
await proxyCache.disconnect()
|
|
155
|
+
await harness.teardownGlobals()
|
|
156
|
+
await harness.down()
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
it('FX Transfer expires without dependent transfer, then resets the position', async () => {
|
|
160
|
+
const positionPayerPre = await ApiHelpers.getPositionAccount('dfsp_a', 'BWP')
|
|
161
|
+
const forex = ApiHelpers.buildForex()
|
|
162
|
+
.deps(harness, TransferHandler)
|
|
163
|
+
.commitRequestId('8000001')
|
|
164
|
+
.determiningTransferId('9000001')
|
|
165
|
+
.parties('dfsp_a', 'fxp_a')
|
|
166
|
+
.amountSource('100.00', 'BWP')
|
|
167
|
+
.amountTarget('10.00', 'USD')
|
|
168
|
+
.expiry(1)
|
|
169
|
+
.build()
|
|
170
|
+
|
|
171
|
+
await forex.prepare()
|
|
172
|
+
|
|
173
|
+
const positionPayerPostPrepare = await ApiHelpers.getPositionAccount('dfsp_a', 'BWP')
|
|
174
|
+
assertPositionDiff('payer', positionPayerPre, positionPayerPostPrepare, { posted: 100 })
|
|
175
|
+
|
|
176
|
+
let fxTransfer = await FxTransferService.getByIdLight('8000001')
|
|
177
|
+
assert.equal(fxTransfer.fxTransferState, 'RESERVED')
|
|
178
|
+
|
|
179
|
+
await sleepSeconds(10)
|
|
180
|
+
const mark = harness.redpandaMark()
|
|
181
|
+
const resultTimeout = await TimeoutHandler.timeout()
|
|
182
|
+
assert(resultTimeout)
|
|
183
|
+
// Annoyingly the timeout handler still includes aborted transfers in timeouts.
|
|
184
|
+
const fxTransfers = resultTimeout.fxTransferTimeoutList
|
|
185
|
+
.filter((transfer: any) => transfer.transferStateId === 'RESERVED_TIMEOUT')
|
|
186
|
+
Snapshot.from(`[
|
|
187
|
+
{
|
|
188
|
+
"fxTransferTimeoutId": 1,
|
|
189
|
+
"commitRequestId": "8000001",
|
|
190
|
+
"expirationDate": :ignore
|
|
191
|
+
"createdDate": :ignore
|
|
192
|
+
"transferStateId": "RESERVED_TIMEOUT",
|
|
193
|
+
"initiatingParticipantCurrencyId": null,
|
|
194
|
+
"initiatingFsp": "dfsp_a",
|
|
195
|
+
"counterPartyFsp": "fxp_a",
|
|
196
|
+
"counterPartyParticipantCurrencyId": :ignore
|
|
197
|
+
"effectedParticipantCurrencyId": :ignore
|
|
198
|
+
"externalInitiatingFspName": null,
|
|
199
|
+
"externalCounterPartyFspName": null
|
|
200
|
+
}
|
|
201
|
+
]`).checkUnwrap(fxTransfers)
|
|
202
|
+
assert(fxTransfers.length === 1)
|
|
203
|
+
await harness.redpandaDrain(mark, 2)
|
|
204
|
+
|
|
205
|
+
fxTransfer = await FxTransferService.getByIdLight('8000001')
|
|
206
|
+
assert.equal(fxTransfer.fxTransferState, 'EXPIRED_RESERVED')
|
|
207
|
+
const positionPayerPostTimeout = await ApiHelpers.getPositionAccount('dfsp_a', 'BWP')
|
|
208
|
+
assertPositionDiff('payer', positionPayerPre, positionPayerPostTimeout, { posted: 0 })
|
|
209
|
+
})
|
|
210
|
+
|
|
211
|
+
it('FX + dependent transfer timeout resets both payer and FXP target currency positions.', async () => {
|
|
212
|
+
const positionPayerPre = await ApiHelpers.getPositionAccount('dfsp_a', 'BWP')
|
|
213
|
+
const positionFxpBwpPre = await ApiHelpers.getPositionAccount('fxp_a', 'BWP')
|
|
214
|
+
const positionFxpUsdPre = await ApiHelpers.getPositionAccount('fxp_a', 'USD')
|
|
215
|
+
|
|
216
|
+
const forex = ApiHelpers.buildForex()
|
|
217
|
+
.deps(harness, TransferHandler)
|
|
218
|
+
.commitRequestId('8000002')
|
|
219
|
+
.determiningTransferId('9000002')
|
|
220
|
+
.parties('dfsp_a', 'fxp_a')
|
|
221
|
+
.amountSource('100.00', 'BWP')
|
|
222
|
+
.amountTarget('10.00', 'USD')
|
|
223
|
+
.expiry(30)
|
|
224
|
+
.build()
|
|
225
|
+
|
|
226
|
+
await forex.prepare()
|
|
227
|
+
|
|
228
|
+
const positionPayerPostFxPrepare = await ApiHelpers.getPositionAccount('dfsp_a', 'BWP')
|
|
229
|
+
assertPositionDiff('payer', positionPayerPre, positionPayerPostFxPrepare, { posted: 100 })
|
|
230
|
+
|
|
231
|
+
await forex.fulfil()
|
|
232
|
+
|
|
233
|
+
let fxTransfer = await FxTransferService.getByIdLight('8000002')
|
|
234
|
+
assert.equal(fxTransfer.fxTransferState, 'RECEIVED_FULFIL_DEPENDENT')
|
|
235
|
+
|
|
236
|
+
const payment = ApiHelpers.buildPayment()
|
|
237
|
+
.deps(harness, TransferHandler)
|
|
238
|
+
.parties('fxp_a', 'dfsp_b')
|
|
239
|
+
.transferId('9000002')
|
|
240
|
+
.amount('10.00', 'USD')
|
|
241
|
+
.expiry(1)
|
|
242
|
+
.fx()
|
|
243
|
+
.build()
|
|
244
|
+
|
|
245
|
+
await payment.prepare()
|
|
246
|
+
|
|
247
|
+
// Now time out the payment.
|
|
248
|
+
await sleepSeconds(10)
|
|
249
|
+
const mark = harness.redpandaMark()
|
|
250
|
+
const resultTimeout = await TimeoutHandler.timeout()
|
|
251
|
+
assert(resultTimeout)
|
|
252
|
+
// Annoyingly the timeout handler still includes aborted transfers in timeouts.
|
|
253
|
+
const transfers = resultTimeout.transferTimeoutList
|
|
254
|
+
.filter((transfer: any) => transfer.transferStateId === 'RESERVED_TIMEOUT')
|
|
255
|
+
Snapshot.from(`[
|
|
256
|
+
{
|
|
257
|
+
"transferTimeoutId": :ignore
|
|
258
|
+
"transferId": "9000002",
|
|
259
|
+
"expirationDate": :ignore
|
|
260
|
+
"createdDate": :ignore
|
|
261
|
+
"transferStateId": "RESERVED_TIMEOUT",
|
|
262
|
+
"payerParticipantCurrencyId": null,
|
|
263
|
+
"payerFsp": "fxp_a",
|
|
264
|
+
"payeeFsp": "dfsp_b",
|
|
265
|
+
"payeeParticipantCurrencyId": :ignore
|
|
266
|
+
"bulkTransferId": null,
|
|
267
|
+
"effectedParticipantCurrencyId": :ignore
|
|
268
|
+
"externalPayerName": null,
|
|
269
|
+
"externalPayeeName": null
|
|
270
|
+
}
|
|
271
|
+
]`).checkUnwrap(transfers)
|
|
272
|
+
assert(transfers.length === 1)
|
|
273
|
+
await harness.redpandaDrain(mark, 4)
|
|
274
|
+
|
|
275
|
+
const transfer = await TransferFacade.getById('9000002')
|
|
276
|
+
assert.equal(transfer.transferState, 'EXPIRED_RESERVED')
|
|
277
|
+
|
|
278
|
+
const positionPayerPostTimeout = await ApiHelpers.getPositionAccount('dfsp_a', 'BWP')
|
|
279
|
+
assertPositionDiff('payer', positionPayerPre, positionPayerPostTimeout, { posted: 0 })
|
|
280
|
+
|
|
281
|
+
const positionFxpUsdPostTimeout = await ApiHelpers.getPositionAccount('fxp_a', 'USD')
|
|
282
|
+
assertPositionDiff('payer', positionFxpUsdPre, positionFxpUsdPostTimeout, { posted: 0 })
|
|
283
|
+
})
|
|
284
|
+
})
|
|
@@ -970,8 +970,6 @@ const getTransfer = async (error, messages) => {
|
|
|
970
970
|
*
|
|
971
971
|
* @async
|
|
972
972
|
* @description Registers the handler for prepare topic. Gets Kafka config from default.json
|
|
973
|
-
*
|
|
974
|
-
* @returns {boolean} - Returns a boolean: true if successful, or throws and error if failed
|
|
975
973
|
*/
|
|
976
974
|
const registerPrepareHandler = async () => {
|
|
977
975
|
try {
|
|
@@ -995,7 +993,7 @@ const registerPrepareHandler = async () => {
|
|
|
995
993
|
* @async
|
|
996
994
|
* @description Registers the one handler for fulfil transfer. Gets Kafka config from default.json
|
|
997
995
|
* Calls createHandler to register the handler against the Stream Processing API
|
|
998
|
-
* @returns {boolean} - Returns a boolean: true if successful, or throws and error if failed
|
|
996
|
+
* @returns {Promise<boolean>} - Returns a boolean: true if successful, or throws and error if failed
|
|
999
997
|
*/
|
|
1000
998
|
const registerFulfilHandler = async () => {
|
|
1001
999
|
try {
|