@mojaloop/central-ledger 17.7.8 → 17.8.0-orb.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.
- package/.ncurc.yaml +3 -1
- package/.nvmrc +1 -1
- package/.nycrc.yml +16 -1
- package/Dockerfile +9 -10
- package/README.md +39 -9
- package/audit-ci.jsonc +15 -2
- package/config/default.json +17 -1
- package/docker/central-ledger/default.json +9 -0
- package/docker/config-modifier/configs/central-ledger.js +25 -0
- package/docker/env.sh +15 -0
- package/docker/kafka/scripts/provision.sh +4 -1
- package/docker/ml-api-adapter/default.json +4 -1
- package/docker-compose.yml +90 -2
- package/documentation/db/erd-transfer-timeout.png +0 -0
- package/documentation/db/erd-transfer-timeout.txt +81 -0
- package/documentation/fx-implementation/README.md +48 -0
- package/documentation/fx-implementation/assets/fx-position-movements.drawio.svg +4 -0
- package/documentation/fx-implementation/assets/test-scenario.drawio.svg +4 -0
- package/documentation/sequence-diagrams/Handler - FX timeout.plantuml +123 -0
- package/documentation/sequence-diagrams/Handler - FX timeout.png +0 -0
- package/documentation/sequence-diagrams/Handler - timeout.plantuml +81 -0
- package/documentation/sequence-diagrams/Handler - timeout.png +0 -0
- package/documentation/state-diagrams/transfer-ML-spec-states-diagram.png +0 -0
- package/documentation/state-diagrams/transfer-internal-states-diagram.png +0 -0
- package/documentation/state-diagrams/transfer-internal-states.plantuml +75 -0
- package/documentation/state-diagrams/transfer-states.plantuml +13 -0
- package/migrations/310204_transferParticipant-participantId.js +52 -0
- package/migrations/310403_participantPositionChange-participantCurrencyId.js +47 -0
- package/migrations/310404_participantPositionChange-change.js +46 -0
- package/migrations/600010_fxTransferType.js +43 -0
- package/migrations/600011_fxTransferType-indexes.js +38 -0
- package/migrations/600012_fxParticipantCurrencyType.js +43 -0
- package/migrations/600013_fxParticipantCurrencyType-indexes.js +38 -0
- package/migrations/600100_fxTransferDuplicateCheck.js +42 -0
- package/migrations/600110_fxTransferErrorDuplicateCheck.js.js +17 -0
- package/migrations/600200_fxTransfer.js +51 -0
- package/migrations/600201_fxTransfer-indexes.js +40 -0
- package/migrations/600400_fxTransferStateChange.js +46 -0
- package/migrations/600401_fxTransferStateChange-indexes.js +40 -0
- package/migrations/600501_fxWatchList.js +46 -0
- package/migrations/600502_fxWatchList-indexes.js +40 -0
- package/migrations/600600_fxTransferFulfilmentDuplicateCheck.js +43 -0
- package/migrations/600601_fxTransferFulfilmentDuplicateCheck-indexes.js +38 -0
- package/migrations/600700_fxTransferFulfilment.js +47 -0
- package/migrations/600701_fxTransferFulfilment-indexes.js +43 -0
- package/migrations/600800_fxTransferExtension.js +47 -0
- package/migrations/601400_fxTransferTimeout.js +43 -0
- package/migrations/601401_fxTransferTimeout-indexes.js +37 -0
- package/migrations/601500_fxTransferError.js +44 -0
- package/migrations/601501_fxTransferError-indexes.js +37 -0
- package/migrations/610200_fxTransferParticipant.js +52 -0
- package/migrations/610201_fxTransferParticipant-indexes.js +44 -0
- package/migrations/610202_fxTransferParticipant-participantId.js +52 -0
- package/migrations/610403_participantPositionChange-fxTransfer.js +46 -0
- package/migrations/910101_feature904DataMigration.js +46 -52
- package/migrations/910102_feature949DataMigration.js +219 -225
- package/migrations/950104_settlementModel-settlementAccountTypeId.js +15 -20
- package/migrations/950108_participantProxy.js +18 -0
- package/migrations/950109_fxQuote.js +19 -0
- package/migrations/950110_fxQuoteResponse.js +25 -0
- package/migrations/950111_fxQuoteError.js +23 -0
- package/migrations/950113_fxQuoteDuplicateCheck.js +18 -0
- package/migrations/950114_fxQuoteResponseDuplicateCheck.js +21 -0
- package/migrations/950115_fxQuoteConversionTerms.js +36 -0
- package/migrations/950116_fxQuoteConversionTermsExtension.js +21 -0
- package/migrations/950117_fxQuoteResponseConversionTerms.js +39 -0
- package/migrations/950118_fxQuoteResponseConversionTermsExtension.js +21 -0
- package/migrations/950119_fxCharge.js +27 -0
- package/migrations/960100_create_externalParticipant.js +47 -0
- package/migrations/960110_alter_transferParticipant__addFiled_externalParticipantId.js +50 -0
- package/migrations/960111_alter_fxTransferParticipant__addFiled_externalParticipantId.js +50 -0
- package/package.json +27 -20
- package/seeds/endpointType.js +18 -0
- package/seeds/fxParticipantCurrencyType.js +45 -0
- package/seeds/fxTransferType.js +45 -0
- package/seeds/participant.js +2 -1
- package/seeds/transferParticipantRoleType.js +9 -0
- package/seeds/transferState.js +10 -0
- package/src/api/interface/swagger.json +23 -30
- package/src/api/participants/handler.js +6 -2
- package/src/api/participants/routes.js +8 -7
- package/src/api/root/handler.js +15 -5
- package/src/domain/fx/cyril.js +466 -0
- package/src/domain/fx/index.js +107 -0
- package/src/domain/participant/index.js +108 -1
- package/src/domain/position/abort.js +215 -0
- package/src/domain/position/binProcessor.js +361 -99
- package/src/domain/position/fulfil.js +252 -111
- package/src/domain/position/fx-fulfil.js +138 -0
- package/src/domain/position/fx-prepare.js +280 -0
- package/src/domain/position/fx-timeout-reserved.js +159 -0
- package/src/domain/position/index.js +1 -0
- package/src/domain/position/prepare.js +69 -49
- package/src/domain/position/timeout-reserved.js +162 -0
- package/src/domain/timeout/index.js +26 -2
- package/src/domain/transfer/index.js +22 -5
- package/src/domain/transfer/transform.js +19 -6
- package/src/handlers/admin/handler.js +0 -2
- package/src/handlers/bulk/fulfil/handler.js +5 -5
- package/src/handlers/bulk/get/handler.js +5 -5
- package/src/handlers/bulk/prepare/handler.js +9 -9
- package/src/handlers/bulk/processing/handler.js +8 -7
- package/src/handlers/bulk/shared/validator.js +1 -1
- package/src/handlers/positions/handler.js +23 -10
- package/src/handlers/positions/handlerBatch.js +54 -26
- package/src/handlers/register.js +2 -1
- package/src/handlers/timeouts/handler.js +212 -68
- package/src/handlers/transfers/FxFulfilService.js +387 -0
- package/src/handlers/transfers/createRemittanceEntity.js +106 -0
- package/src/handlers/transfers/dto.js +53 -0
- package/src/handlers/transfers/handler.js +609 -571
- package/src/handlers/transfers/prepare.js +572 -0
- package/src/handlers/transfers/validator.js +75 -14
- package/src/lib/cache.js +1 -1
- package/src/lib/config.js +6 -3
- package/src/lib/healthCheck/subServiceHealth.js +12 -2
- package/src/lib/proxyCache.js +131 -0
- package/src/models/bulkTransfer/facade.js +58 -82
- package/src/models/fxTransfer/duplicateCheck.js +153 -0
- package/src/models/fxTransfer/fxTransfer.js +578 -0
- package/src/models/fxTransfer/fxTransferError.js +53 -0
- package/src/models/fxTransfer/fxTransferExtension.js +41 -0
- package/src/models/fxTransfer/fxTransferTimeout.js +68 -0
- package/src/models/fxTransfer/index.js +15 -0
- package/src/models/fxTransfer/stateChange.js +47 -0
- package/src/models/fxTransfer/watchList.js +49 -0
- package/src/models/ledgerAccountType/ledgerAccountType.js +8 -32
- package/src/models/misc/segment.js +0 -1
- package/src/models/participant/externalParticipant.js +96 -0
- package/src/models/participant/externalParticipantCached.js +148 -0
- package/src/models/participant/facade.js +192 -123
- package/src/models/participant/participant.js +2 -1
- package/src/models/participant/participantCurrency.js +1 -1
- package/src/models/participant/participantPosition.js +2 -8
- package/src/models/position/batch.js +90 -1
- package/src/models/position/facade.js +5 -5
- package/src/models/position/participantPositionChanges.js +68 -0
- package/src/models/settlement/settlementModel.js +5 -23
- package/src/models/transfer/facade.js +806 -447
- package/src/shared/constants.js +52 -0
- package/src/shared/fspiopErrorFactory.js +131 -0
- package/src/shared/logger/index.js +8 -0
- package/src/shared/loggingPlugin.js +43 -0
- package/src/shared/plugins.js +6 -0
- package/src/shared/setup.js +10 -0
- package/test-integration.Dockerfile +1 -1
- package/test.Dockerfile +1 -1
|
@@ -0,0 +1,578 @@
|
|
|
1
|
+
const Metrics = require('@mojaloop/central-services-metrics')
|
|
2
|
+
const ErrorHandler = require('@mojaloop/central-services-error-handling')
|
|
3
|
+
const { Enum, Util } = require('@mojaloop/central-services-shared')
|
|
4
|
+
const Time = require('@mojaloop/central-services-shared').Util.Time
|
|
5
|
+
const TransferEventAction = Enum.Events.Event.Action
|
|
6
|
+
|
|
7
|
+
const { logger } = require('../../shared/logger')
|
|
8
|
+
const { TABLE_NAMES } = require('../../shared/constants')
|
|
9
|
+
const Db = require('../../lib/db')
|
|
10
|
+
const participant = require('../participant/facade')
|
|
11
|
+
const ParticipantCachedModel = require('../participant/participantCached')
|
|
12
|
+
const TransferExtensionModel = require('./fxTransferExtension')
|
|
13
|
+
|
|
14
|
+
const { TransferInternalState } = Enum.Transfers
|
|
15
|
+
|
|
16
|
+
const UnsupportedActionText = 'Unsupported action'
|
|
17
|
+
|
|
18
|
+
const getByCommitRequestId = async (commitRequestId) => {
|
|
19
|
+
logger.debug('get fxTransfer by commitRequestId:', { commitRequestId })
|
|
20
|
+
return Db.from(TABLE_NAMES.fxTransfer).findOne({ commitRequestId })
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const getByDeterminingTransferId = async (determiningTransferId) => {
|
|
24
|
+
logger.debug('get fxTransfers by determiningTransferId:', { determiningTransferId })
|
|
25
|
+
return Db.from(TABLE_NAMES.fxTransfer).find({ determiningTransferId })
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const saveFxTransfer = async (record) => {
|
|
29
|
+
logger.debug('save fxTransfer record:', { record })
|
|
30
|
+
return Db.from(TABLE_NAMES.fxTransfer).insert(record)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const getByIdLight = async (id) => {
|
|
34
|
+
try {
|
|
35
|
+
/** @namespace Db.fxTransfer **/
|
|
36
|
+
return await Db.from(TABLE_NAMES.fxTransfer).query(async (builder) => {
|
|
37
|
+
return builder
|
|
38
|
+
.where({ 'fxTransfer.commitRequestId': id })
|
|
39
|
+
.leftJoin('fxTransferStateChange AS tsc', 'tsc.commitRequestId', 'fxTransfer.commitRequestId')
|
|
40
|
+
.leftJoin('transferState AS ts', 'ts.transferStateId', 'tsc.transferStateId')
|
|
41
|
+
.leftJoin('fxTransferFulfilment AS tf', 'tf.commitRequestId', 'fxTransfer.commitRequestId')
|
|
42
|
+
.select(
|
|
43
|
+
'fxTransfer.*',
|
|
44
|
+
'tsc.fxTransferStateChangeId',
|
|
45
|
+
'tsc.transferStateId AS fxTransferState',
|
|
46
|
+
'ts.enumeration AS fxTransferStateEnumeration',
|
|
47
|
+
'ts.description as fxTransferStateDescription',
|
|
48
|
+
'tsc.reason AS reason',
|
|
49
|
+
'tsc.createdDate AS completedTimestamp',
|
|
50
|
+
'fxTransfer.ilpCondition AS condition',
|
|
51
|
+
'tf.ilpFulfilment AS fulfilment'
|
|
52
|
+
)
|
|
53
|
+
.orderBy('tsc.fxTransferStateChangeId', 'desc')
|
|
54
|
+
.first()
|
|
55
|
+
})
|
|
56
|
+
} catch (err) {
|
|
57
|
+
throw ErrorHandler.Factory.reformatFSPIOPError(err)
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const getAllDetailsByCommitRequestId = async (commitRequestId) => {
|
|
62
|
+
try {
|
|
63
|
+
/** @namespace Db.fxTransfer **/
|
|
64
|
+
return await Db.from('fxTransfer').query(async (builder) => {
|
|
65
|
+
const transferResult = await builder
|
|
66
|
+
.where({
|
|
67
|
+
'fxTransfer.commitRequestId': commitRequestId,
|
|
68
|
+
'tprt1.name': 'INITIATING_FSP',
|
|
69
|
+
'tprt2.name': 'COUNTER_PARTY_FSP',
|
|
70
|
+
'tprt3.name': 'COUNTER_PARTY_FSP',
|
|
71
|
+
'fpct1.name': 'SOURCE',
|
|
72
|
+
'fpct2.name': 'TARGET'
|
|
73
|
+
})
|
|
74
|
+
// INITIATING_FSP
|
|
75
|
+
.innerJoin('fxTransferParticipant AS tp1', 'tp1.commitRequestId', 'fxTransfer.commitRequestId')
|
|
76
|
+
.innerJoin('transferParticipantRoleType AS tprt1', 'tprt1.transferParticipantRoleTypeId', 'tp1.transferParticipantRoleTypeId')
|
|
77
|
+
.innerJoin('participant AS da', 'da.participantId', 'tp1.participantId')
|
|
78
|
+
// COUNTER_PARTY_FSP SOURCE currency
|
|
79
|
+
.innerJoin('fxTransferParticipant AS tp21', 'tp21.commitRequestId', 'fxTransfer.commitRequestId')
|
|
80
|
+
.innerJoin('transferParticipantRoleType AS tprt2', 'tprt2.transferParticipantRoleTypeId', 'tp21.transferParticipantRoleTypeId')
|
|
81
|
+
.innerJoin('fxParticipantCurrencyType AS fpct1', 'fpct1.fxParticipantCurrencyTypeId', 'tp21.fxParticipantCurrencyTypeId')
|
|
82
|
+
.innerJoin('participant AS ca', 'ca.participantId', 'tp21.participantId')
|
|
83
|
+
.leftJoin('participantCurrency AS pc21', 'pc21.participantCurrencyId', 'tp21.participantCurrencyId')
|
|
84
|
+
// COUNTER_PARTY_FSP TARGET currency
|
|
85
|
+
.innerJoin('fxTransferParticipant AS tp22', 'tp22.commitRequestId', 'fxTransfer.commitRequestId')
|
|
86
|
+
.innerJoin('transferParticipantRoleType AS tprt3', 'tprt3.transferParticipantRoleTypeId', 'tp22.transferParticipantRoleTypeId')
|
|
87
|
+
.innerJoin('fxParticipantCurrencyType AS fpct2', 'fpct2.fxParticipantCurrencyTypeId', 'tp22.fxParticipantCurrencyTypeId')
|
|
88
|
+
// .innerJoin('participantCurrency AS pc22', 'pc22.participantCurrencyId', 'tp22.participantCurrencyId')
|
|
89
|
+
// OTHER JOINS
|
|
90
|
+
.leftJoin('fxTransferStateChange AS tsc', 'tsc.commitRequestId', 'fxTransfer.commitRequestId')
|
|
91
|
+
.leftJoin('transferState AS ts', 'ts.transferStateId', 'tsc.transferStateId')
|
|
92
|
+
.leftJoin('fxTransferFulfilment AS tf', 'tf.commitRequestId', 'fxTransfer.commitRequestId')
|
|
93
|
+
// .leftJoin('transferError as te', 'te.commitRequestId', 'transfer.commitRequestId') // currently transferError.transferId is PK ensuring one error per transferId
|
|
94
|
+
.select(
|
|
95
|
+
'fxTransfer.*',
|
|
96
|
+
'da.participantId AS initiatingFspParticipantId',
|
|
97
|
+
'da.name AS initiatingFspName',
|
|
98
|
+
'da.isProxy AS initiatingFspIsProxy',
|
|
99
|
+
// 'pc21.participantCurrencyId AS counterPartyFspSourceParticipantCurrencyId',
|
|
100
|
+
// 'pc22.participantCurrencyId AS counterPartyFspTargetParticipantCurrencyId',
|
|
101
|
+
'tp21.participantCurrencyId AS counterPartyFspSourceParticipantCurrencyId',
|
|
102
|
+
'tp22.participantCurrencyId AS counterPartyFspTargetParticipantCurrencyId',
|
|
103
|
+
'ca.participantId AS counterPartyFspParticipantId',
|
|
104
|
+
'ca.name AS counterPartyFspName',
|
|
105
|
+
'ca.isProxy AS counterPartyFspIsProxy',
|
|
106
|
+
'tsc.fxTransferStateChangeId',
|
|
107
|
+
'tsc.transferStateId AS transferState',
|
|
108
|
+
'tsc.reason AS reason',
|
|
109
|
+
'tsc.createdDate AS completedTimestamp',
|
|
110
|
+
'ts.enumeration as transferStateEnumeration',
|
|
111
|
+
'ts.description as transferStateDescription',
|
|
112
|
+
'tf.ilpFulfilment AS fulfilment'
|
|
113
|
+
)
|
|
114
|
+
.orderBy('tsc.fxTransferStateChangeId', 'desc')
|
|
115
|
+
.first()
|
|
116
|
+
if (transferResult) {
|
|
117
|
+
transferResult.extensionList = await TransferExtensionModel.getByCommitRequestId(commitRequestId)
|
|
118
|
+
if (transferResult.errorCode && transferResult.transferStateEnumeration === Enum.Transfers.TransferState.ABORTED) {
|
|
119
|
+
if (!transferResult.extensionList) transferResult.extensionList = []
|
|
120
|
+
transferResult.extensionList.push({
|
|
121
|
+
key: 'cause',
|
|
122
|
+
value: `${transferResult.errorCode}: ${transferResult.errorDescription}`.substr(0, 128)
|
|
123
|
+
})
|
|
124
|
+
}
|
|
125
|
+
transferResult.isTransferReadModel = true
|
|
126
|
+
}
|
|
127
|
+
return transferResult
|
|
128
|
+
})
|
|
129
|
+
} catch (err) {
|
|
130
|
+
logger.warn('error in getAllDetailsByCommitRequestId', err)
|
|
131
|
+
throw ErrorHandler.Factory.reformatFSPIOPError(err)
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// For proxied fxTransfers and transfers in a regional and jurisdictional scenario, proxy participants
|
|
136
|
+
// are not expected to have a target currency account, so we need a slightly altered version of the above function.
|
|
137
|
+
const getAllDetailsByCommitRequestIdForProxiedFxTransfer = async (commitRequestId) => {
|
|
138
|
+
try {
|
|
139
|
+
/** @namespace Db.fxTransfer **/
|
|
140
|
+
return await Db.from('fxTransfer').query(async (builder) => {
|
|
141
|
+
const transferResult = await builder
|
|
142
|
+
.where({
|
|
143
|
+
'fxTransfer.commitRequestId': commitRequestId,
|
|
144
|
+
'tprt1.name': 'INITIATING_FSP',
|
|
145
|
+
'tprt2.name': 'COUNTER_PARTY_FSP',
|
|
146
|
+
'fpct1.name': 'SOURCE'
|
|
147
|
+
})
|
|
148
|
+
// INITIATING_FSP
|
|
149
|
+
.innerJoin('fxTransferParticipant AS tp1', 'tp1.commitRequestId', 'fxTransfer.commitRequestId')
|
|
150
|
+
.leftJoin('externalParticipant AS ep1', 'ep1.externalParticipantId', 'tp1.externalParticipantId')
|
|
151
|
+
.innerJoin('transferParticipantRoleType AS tprt1', 'tprt1.transferParticipantRoleTypeId', 'tp1.transferParticipantRoleTypeId')
|
|
152
|
+
.innerJoin('participant AS da', 'da.participantId', 'tp1.participantId')
|
|
153
|
+
// COUNTER_PARTY_FSP SOURCE currency
|
|
154
|
+
.innerJoin('fxTransferParticipant AS tp21', 'tp21.commitRequestId', 'fxTransfer.commitRequestId')
|
|
155
|
+
.leftJoin('externalParticipant AS ep2', 'ep2.externalParticipantId', 'tp21.externalParticipantId')
|
|
156
|
+
.innerJoin('transferParticipantRoleType AS tprt2', 'tprt2.transferParticipantRoleTypeId', 'tp21.transferParticipantRoleTypeId')
|
|
157
|
+
.innerJoin('fxParticipantCurrencyType AS fpct1', 'fpct1.fxParticipantCurrencyTypeId', 'tp21.fxParticipantCurrencyTypeId')
|
|
158
|
+
.innerJoin('participant AS ca', 'ca.participantId', 'tp21.participantId')
|
|
159
|
+
.leftJoin('participantCurrency AS pc21', 'pc21.participantCurrencyId', 'tp21.participantCurrencyId')
|
|
160
|
+
// .innerJoin('participantCurrency AS pc22', 'pc22.participantCurrencyId', 'tp22.participantCurrencyId')
|
|
161
|
+
// OTHER JOINS
|
|
162
|
+
.leftJoin('fxTransferStateChange AS tsc', 'tsc.commitRequestId', 'fxTransfer.commitRequestId')
|
|
163
|
+
.leftJoin('transferState AS ts', 'ts.transferStateId', 'tsc.transferStateId')
|
|
164
|
+
.leftJoin('fxTransferFulfilment AS tf', 'tf.commitRequestId', 'fxTransfer.commitRequestId')
|
|
165
|
+
// .leftJoin('transferError as te', 'te.commitRequestId', 'transfer.commitRequestId') // currently transferError.transferId is PK ensuring one error per transferId
|
|
166
|
+
.select(
|
|
167
|
+
'fxTransfer.*',
|
|
168
|
+
'da.participantId AS initiatingFspParticipantId',
|
|
169
|
+
'da.name AS initiatingFspName',
|
|
170
|
+
'da.isProxy AS initiatingFspIsProxy',
|
|
171
|
+
// 'pc21.participantCurrencyId AS counterPartyFspSourceParticipantCurrencyId',
|
|
172
|
+
// 'pc22.participantCurrencyId AS counterPartyFspTargetParticipantCurrencyId',
|
|
173
|
+
'tp21.participantCurrencyId AS counterPartyFspSourceParticipantCurrencyId',
|
|
174
|
+
'ca.participantId AS counterPartyFspParticipantId',
|
|
175
|
+
'ca.name AS counterPartyFspName',
|
|
176
|
+
'ca.isProxy AS counterPartyFspIsProxy',
|
|
177
|
+
'tsc.fxTransferStateChangeId',
|
|
178
|
+
'tsc.transferStateId AS transferState',
|
|
179
|
+
'tsc.reason AS reason',
|
|
180
|
+
'tsc.createdDate AS completedTimestamp',
|
|
181
|
+
'ts.enumeration as transferStateEnumeration',
|
|
182
|
+
'ts.description as transferStateDescription',
|
|
183
|
+
'tf.ilpFulfilment AS fulfilment',
|
|
184
|
+
'ep1.name AS externalInitiatingFspName',
|
|
185
|
+
'ep2.name AS externalCounterPartyFspName'
|
|
186
|
+
)
|
|
187
|
+
.orderBy('tsc.fxTransferStateChangeId', 'desc')
|
|
188
|
+
.first()
|
|
189
|
+
|
|
190
|
+
if (transferResult) {
|
|
191
|
+
transferResult.extensionList = await TransferExtensionModel.getByCommitRequestId(commitRequestId)
|
|
192
|
+
if (transferResult.errorCode && transferResult.transferStateEnumeration === Enum.Transfers.TransferState.ABORTED) {
|
|
193
|
+
if (!transferResult.extensionList) transferResult.extensionList = []
|
|
194
|
+
transferResult.extensionList.push({
|
|
195
|
+
key: 'cause',
|
|
196
|
+
value: `${transferResult.errorCode}: ${transferResult.errorDescription}`.substr(0, 128)
|
|
197
|
+
})
|
|
198
|
+
}
|
|
199
|
+
transferResult.isTransferReadModel = true
|
|
200
|
+
}
|
|
201
|
+
return transferResult
|
|
202
|
+
})
|
|
203
|
+
} catch (err) {
|
|
204
|
+
logger.warn('error in getAllDetailsByCommitRequestIdForProxiedFxTransfer', err)
|
|
205
|
+
throw ErrorHandler.Factory.reformatFSPIOPError(err)
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const getParticipant = async (name, currency) =>
|
|
210
|
+
participant.getByNameAndCurrency(name, currency, Enum.Accounts.LedgerAccountType.POSITION)
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Saves prepare fxTransfer details to DB.
|
|
214
|
+
*
|
|
215
|
+
* @param {Object} payload - Message payload.
|
|
216
|
+
* @param {string | null} stateReason - Validation failure reasons.
|
|
217
|
+
* @param {Boolean} hasPassedValidation - Is fxTransfer prepare validation passed.
|
|
218
|
+
* @param {DeterminingTransferCheckResult} determiningTransferCheckResult - Determining transfer check result.
|
|
219
|
+
* @param {ProxyObligation} proxyObligation - The proxy obligation
|
|
220
|
+
* @returns {Promise<void>}
|
|
221
|
+
*/
|
|
222
|
+
const savePreparedRequest = async (
|
|
223
|
+
payload,
|
|
224
|
+
stateReason,
|
|
225
|
+
hasPassedValidation,
|
|
226
|
+
determiningTransferCheckResult,
|
|
227
|
+
proxyObligation
|
|
228
|
+
) => {
|
|
229
|
+
const histTimerSaveFxTransferEnd = Metrics.getHistogram(
|
|
230
|
+
'model_fx_transfer',
|
|
231
|
+
'facade_saveFxTransferPrepared - Metrics for transfer model',
|
|
232
|
+
['success', 'queryName']
|
|
233
|
+
).startTimer()
|
|
234
|
+
|
|
235
|
+
// Substitute out of scheme participants with their proxy representatives
|
|
236
|
+
const initiatingFsp = proxyObligation.isInitiatingFspProxy
|
|
237
|
+
? proxyObligation.initiatingFspProxyOrParticipantId.proxyId
|
|
238
|
+
: payload.initiatingFsp
|
|
239
|
+
const counterPartyFsp = proxyObligation.isCounterPartyFspProxy
|
|
240
|
+
? proxyObligation.counterPartyFspProxyOrParticipantId.proxyId
|
|
241
|
+
: payload.counterPartyFsp
|
|
242
|
+
|
|
243
|
+
// If creditor(counterPartyFsp) is a proxy in a jurisdictional scenario,
|
|
244
|
+
// they would not hold a position account for the target currency,
|
|
245
|
+
// so we skip adding records of the target currency for the creditor.
|
|
246
|
+
try {
|
|
247
|
+
const [initiatingParticipant, counterParticipant1, counterParticipant2] = await Promise.all([
|
|
248
|
+
ParticipantCachedModel.getByName(initiatingFsp),
|
|
249
|
+
getParticipant(counterPartyFsp, payload.sourceAmount.currency),
|
|
250
|
+
!proxyObligation.isCounterPartyFspProxy ? getParticipant(counterPartyFsp, payload.targetAmount.currency) : null
|
|
251
|
+
])
|
|
252
|
+
// todo: clarify, what we should do if no initiatingParticipant or counterParticipant found?
|
|
253
|
+
|
|
254
|
+
const fxTransferRecord = {
|
|
255
|
+
commitRequestId: payload.commitRequestId,
|
|
256
|
+
determiningTransferId: payload.determiningTransferId,
|
|
257
|
+
sourceAmount: payload.sourceAmount.amount,
|
|
258
|
+
sourceCurrency: payload.sourceAmount.currency,
|
|
259
|
+
targetAmount: payload.targetAmount.amount,
|
|
260
|
+
targetCurrency: payload.targetAmount.currency,
|
|
261
|
+
ilpCondition: payload.condition,
|
|
262
|
+
expirationDate: Util.Time.getUTCString(new Date(payload.expiration))
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
const fxTransferStateChangeRecord = {
|
|
266
|
+
commitRequestId: payload.commitRequestId,
|
|
267
|
+
transferStateId: hasPassedValidation ? TransferInternalState.RECEIVED_PREPARE : TransferInternalState.INVALID,
|
|
268
|
+
reason: stateReason,
|
|
269
|
+
createdDate: Util.Time.getUTCString(new Date())
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
const initiatingParticipantRecord = {
|
|
273
|
+
commitRequestId: payload.commitRequestId,
|
|
274
|
+
participantId: initiatingParticipant.participantId,
|
|
275
|
+
participantCurrencyId: null,
|
|
276
|
+
amount: payload.sourceAmount.amount,
|
|
277
|
+
transferParticipantRoleTypeId: Enum.Accounts.TransferParticipantRoleType.INITIATING_FSP,
|
|
278
|
+
ledgerEntryTypeId: Enum.Accounts.LedgerEntryType.PRINCIPLE_VALUE
|
|
279
|
+
}
|
|
280
|
+
if (proxyObligation.isInitiatingFspProxy) {
|
|
281
|
+
initiatingParticipantRecord.externalParticipantId = await participant
|
|
282
|
+
.getExternalParticipantIdByNameOrCreate(proxyObligation.initiatingFspProxyOrParticipantId)
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
const counterPartyParticipantRecord1 = {
|
|
286
|
+
commitRequestId: payload.commitRequestId,
|
|
287
|
+
participantId: counterParticipant1.participantId,
|
|
288
|
+
participantCurrencyId: counterParticipant1.participantCurrencyId,
|
|
289
|
+
amount: -payload.sourceAmount.amount,
|
|
290
|
+
transferParticipantRoleTypeId: Enum.Accounts.TransferParticipantRoleType.COUNTER_PARTY_FSP,
|
|
291
|
+
fxParticipantCurrencyTypeId: Enum.Fx.FxParticipantCurrencyType.SOURCE,
|
|
292
|
+
ledgerEntryTypeId: Enum.Accounts.LedgerEntryType.PRINCIPLE_VALUE
|
|
293
|
+
}
|
|
294
|
+
if (proxyObligation.isCounterPartyFspProxy) {
|
|
295
|
+
counterPartyParticipantRecord1.externalParticipantId = await participant
|
|
296
|
+
.getExternalParticipantIdByNameOrCreate(proxyObligation.counterPartyFspProxyOrParticipantId)
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
let counterPartyParticipantRecord2 = null
|
|
300
|
+
if (!proxyObligation.isCounterPartyFspProxy) {
|
|
301
|
+
counterPartyParticipantRecord2 = {
|
|
302
|
+
commitRequestId: payload.commitRequestId,
|
|
303
|
+
participantId: counterParticipant2.participantId,
|
|
304
|
+
participantCurrencyId: counterParticipant2.participantCurrencyId,
|
|
305
|
+
amount: -payload.targetAmount.amount,
|
|
306
|
+
transferParticipantRoleTypeId: Enum.Accounts.TransferParticipantRoleType.COUNTER_PARTY_FSP,
|
|
307
|
+
fxParticipantCurrencyTypeId: Enum.Fx.FxParticipantCurrencyType.TARGET,
|
|
308
|
+
ledgerEntryTypeId: Enum.Accounts.LedgerEntryType.PRINCIPLE_VALUE
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
const knex = await Db.getKnex()
|
|
313
|
+
if (hasPassedValidation) {
|
|
314
|
+
const histTimerSaveTranferTransactionValidationPassedEnd = Metrics.getHistogram(
|
|
315
|
+
'model_fx_transfer',
|
|
316
|
+
'facade_saveFxTransferPrepared_transaction - Metrics for transfer model',
|
|
317
|
+
['success', 'queryName']
|
|
318
|
+
).startTimer()
|
|
319
|
+
return await knex.transaction(async (trx) => {
|
|
320
|
+
try {
|
|
321
|
+
await knex(TABLE_NAMES.fxTransfer).transacting(trx).insert(fxTransferRecord)
|
|
322
|
+
await knex(TABLE_NAMES.fxTransferParticipant).transacting(trx).insert(initiatingParticipantRecord)
|
|
323
|
+
await knex(TABLE_NAMES.fxTransferParticipant).transacting(trx).insert(counterPartyParticipantRecord1)
|
|
324
|
+
if (!proxyObligation.isCounterPartyFspProxy) {
|
|
325
|
+
await knex(TABLE_NAMES.fxTransferParticipant).transacting(trx).insert(counterPartyParticipantRecord2)
|
|
326
|
+
}
|
|
327
|
+
initiatingParticipantRecord.name = payload.initiatingFsp
|
|
328
|
+
counterPartyParticipantRecord1.name = payload.counterPartyFsp
|
|
329
|
+
if (!proxyObligation.isCounterPartyFspProxy) {
|
|
330
|
+
counterPartyParticipantRecord2.name = payload.counterPartyFsp
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
await knex(TABLE_NAMES.fxTransferStateChange).transacting(trx).insert(fxTransferStateChangeRecord)
|
|
334
|
+
histTimerSaveTranferTransactionValidationPassedEnd({ success: true, queryName: 'facade_saveFxTransferPrepared_transaction' })
|
|
335
|
+
} catch (err) {
|
|
336
|
+
histTimerSaveTranferTransactionValidationPassedEnd({ success: false, queryName: 'facade_saveFxTransferPrepared_transaction' })
|
|
337
|
+
throw err
|
|
338
|
+
}
|
|
339
|
+
})
|
|
340
|
+
} else {
|
|
341
|
+
const queryName = 'facade_saveFxTransferPrepared_no_validation'
|
|
342
|
+
const histTimerNoValidationEnd = Metrics.getHistogram(
|
|
343
|
+
'model_fx_transfer',
|
|
344
|
+
`${queryName} - Metrics for fxTransfer model`,
|
|
345
|
+
['success', 'queryName']
|
|
346
|
+
).startTimer()
|
|
347
|
+
await knex(TABLE_NAMES.fxTransfer).insert(fxTransferRecord)
|
|
348
|
+
|
|
349
|
+
try {
|
|
350
|
+
await knex(TABLE_NAMES.fxTransferParticipant).insert(initiatingParticipantRecord)
|
|
351
|
+
} catch (err) {
|
|
352
|
+
logger.warn(`Payer fxTransferParticipant insert error: ${err.message}`)
|
|
353
|
+
histTimerNoValidationEnd({ success: false, queryName })
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
try {
|
|
357
|
+
await knex(TABLE_NAMES.fxTransferParticipant).insert(counterPartyParticipantRecord1)
|
|
358
|
+
if (!proxyObligation.isCounterPartyFspProxy) {
|
|
359
|
+
await knex(TABLE_NAMES.fxTransferParticipant).insert(counterPartyParticipantRecord2)
|
|
360
|
+
}
|
|
361
|
+
} catch (err) {
|
|
362
|
+
histTimerNoValidationEnd({ success: false, queryName })
|
|
363
|
+
logger.warn(`Payee fxTransferParticipant insert error: ${err.message}`)
|
|
364
|
+
}
|
|
365
|
+
initiatingParticipantRecord.name = payload.initiatingFsp
|
|
366
|
+
counterPartyParticipantRecord1.name = payload.counterPartyFsp
|
|
367
|
+
if (!proxyObligation.isCounterPartyFspProxy) {
|
|
368
|
+
counterPartyParticipantRecord2.name = payload.counterPartyFsp
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
try {
|
|
372
|
+
await knex(TABLE_NAMES.fxTransferStateChange).insert(fxTransferStateChangeRecord)
|
|
373
|
+
histTimerNoValidationEnd({ success: true, queryName })
|
|
374
|
+
} catch (err) {
|
|
375
|
+
logger.warn(`fxTransferStateChange insert error: ${err.message}`)
|
|
376
|
+
histTimerNoValidationEnd({ success: false, queryName })
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
histTimerSaveFxTransferEnd({ success: true, queryName: 'transfer_model_facade_saveTransferPrepared' })
|
|
380
|
+
} catch (err) {
|
|
381
|
+
logger.warn('error in savePreparedRequest', err)
|
|
382
|
+
histTimerSaveFxTransferEnd({ success: false, queryName: 'transfer_model_facade_saveTransferPrepared' })
|
|
383
|
+
throw ErrorHandler.Factory.reformatFSPIOPError(err)
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
const saveFxFulfilResponse = async (commitRequestId, payload, action, fspiopError) => {
|
|
388
|
+
const histTimerSaveFulfilResponseEnd = Metrics.getHistogram(
|
|
389
|
+
'fx_model_transfer',
|
|
390
|
+
'facade_saveFxFulfilResponse - Metrics for fxTransfer model',
|
|
391
|
+
['success', 'queryName']
|
|
392
|
+
).startTimer()
|
|
393
|
+
|
|
394
|
+
let state
|
|
395
|
+
let isFulfilment = false
|
|
396
|
+
let isError = false
|
|
397
|
+
// const errorCode = fspiopError && fspiopError.errorInformation && fspiopError.errorInformation.errorCode
|
|
398
|
+
const errorDescription = fspiopError && fspiopError.errorInformation && fspiopError.errorInformation.errorDescription
|
|
399
|
+
let extensionList
|
|
400
|
+
switch (action) {
|
|
401
|
+
case TransferEventAction.FX_COMMIT:
|
|
402
|
+
case TransferEventAction.FX_RESERVE:
|
|
403
|
+
case TransferEventAction.FX_FORWARDED:
|
|
404
|
+
state = TransferInternalState.RECEIVED_FULFIL_DEPENDENT
|
|
405
|
+
extensionList = payload && payload.extensionList
|
|
406
|
+
isFulfilment = true
|
|
407
|
+
break
|
|
408
|
+
case TransferEventAction.FX_REJECT:
|
|
409
|
+
state = TransferInternalState.RECEIVED_REJECT
|
|
410
|
+
extensionList = payload && payload.extensionList
|
|
411
|
+
isFulfilment = true
|
|
412
|
+
break
|
|
413
|
+
|
|
414
|
+
case TransferEventAction.FX_ABORT_VALIDATION:
|
|
415
|
+
case TransferEventAction.FX_ABORT:
|
|
416
|
+
state = TransferInternalState.RECEIVED_ERROR
|
|
417
|
+
extensionList = payload && payload.errorInformation && payload.errorInformation.extensionList
|
|
418
|
+
isError = true
|
|
419
|
+
break
|
|
420
|
+
default:
|
|
421
|
+
throw ErrorHandler.Factory.createInternalServerFSPIOPError(UnsupportedActionText)
|
|
422
|
+
}
|
|
423
|
+
const completedTimestamp = Time.getUTCString((payload.completedTimestamp && new Date(payload.completedTimestamp)) || new Date())
|
|
424
|
+
const transactionTimestamp = Time.getUTCString(new Date())
|
|
425
|
+
const result = {
|
|
426
|
+
savePayeeTransferResponseExecuted: false
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
const fxTransferFulfilmentRecord = {
|
|
430
|
+
commitRequestId,
|
|
431
|
+
ilpFulfilment: payload.fulfilment || null,
|
|
432
|
+
completedDate: completedTimestamp,
|
|
433
|
+
isValid: !fspiopError,
|
|
434
|
+
settlementWindowId: null,
|
|
435
|
+
createdDate: transactionTimestamp
|
|
436
|
+
}
|
|
437
|
+
let fxTransferExtensionRecordsList = []
|
|
438
|
+
if (extensionList && extensionList.extension) {
|
|
439
|
+
fxTransferExtensionRecordsList = extensionList.extension.map(ext => {
|
|
440
|
+
return {
|
|
441
|
+
commitRequestId,
|
|
442
|
+
key: ext.key,
|
|
443
|
+
value: ext.value,
|
|
444
|
+
isFulfilment,
|
|
445
|
+
isError
|
|
446
|
+
}
|
|
447
|
+
})
|
|
448
|
+
}
|
|
449
|
+
const fxTransferStateChangeRecord = {
|
|
450
|
+
commitRequestId,
|
|
451
|
+
transferStateId: state,
|
|
452
|
+
reason: errorDescription,
|
|
453
|
+
createdDate: transactionTimestamp
|
|
454
|
+
}
|
|
455
|
+
// const fxTransferErrorRecord = {
|
|
456
|
+
// commitRequestId,
|
|
457
|
+
// fxTransferStateChangeId: null,
|
|
458
|
+
// errorCode,
|
|
459
|
+
// errorDescription,
|
|
460
|
+
// createdDate: transactionTimestamp
|
|
461
|
+
// }
|
|
462
|
+
|
|
463
|
+
try {
|
|
464
|
+
/** @namespace Db.getKnex **/
|
|
465
|
+
const knex = await Db.getKnex()
|
|
466
|
+
const histTFxFulfilResponseValidationPassedEnd = Metrics.getHistogram(
|
|
467
|
+
'model_transfer',
|
|
468
|
+
'facade_saveTransferPrepared_transaction - Metrics for transfer model',
|
|
469
|
+
['success', 'queryName']
|
|
470
|
+
).startTimer()
|
|
471
|
+
|
|
472
|
+
await knex.transaction(async (trx) => {
|
|
473
|
+
try {
|
|
474
|
+
if (!fspiopError && [TransferEventAction.FX_COMMIT, TransferEventAction.FX_RESERVE].includes(action)) {
|
|
475
|
+
const res = await Db.from('settlementWindow').query(builder => {
|
|
476
|
+
return builder
|
|
477
|
+
.leftJoin('settlementWindowStateChange AS swsc', 'swsc.settlementWindowStateChangeId', 'settlementWindow.currentStateChangeId')
|
|
478
|
+
.select(
|
|
479
|
+
'settlementWindow.settlementWindowId',
|
|
480
|
+
'swsc.settlementWindowStateId as state',
|
|
481
|
+
'swsc.reason as reason',
|
|
482
|
+
'settlementWindow.createdDate as createdDate',
|
|
483
|
+
'swsc.createdDate as changedDate'
|
|
484
|
+
)
|
|
485
|
+
.where('swsc.settlementWindowStateId', 'OPEN')
|
|
486
|
+
.orderBy('changedDate', 'desc')
|
|
487
|
+
})
|
|
488
|
+
fxTransferFulfilmentRecord.settlementWindowId = res[0].settlementWindowId
|
|
489
|
+
logger.debug('saveFxFulfilResponse::settlementWindowId')
|
|
490
|
+
}
|
|
491
|
+
if (isFulfilment) {
|
|
492
|
+
await knex('fxTransferFulfilment').transacting(trx).insert(fxTransferFulfilmentRecord)
|
|
493
|
+
result.fxTransferFulfilmentRecord = fxTransferFulfilmentRecord
|
|
494
|
+
logger.debug('saveFxFulfilResponse::fxTransferFulfilment')
|
|
495
|
+
}
|
|
496
|
+
if (fxTransferExtensionRecordsList.length > 0) {
|
|
497
|
+
await knex('fxTransferExtension').transacting(trx).insert(fxTransferExtensionRecordsList)
|
|
498
|
+
result.fxTransferExtensionRecordsList = fxTransferExtensionRecordsList
|
|
499
|
+
logger.debug('saveFxFulfilResponse::transferExtensionRecordsList')
|
|
500
|
+
}
|
|
501
|
+
await knex('fxTransferStateChange').transacting(trx).insert(fxTransferStateChangeRecord)
|
|
502
|
+
result.fxTransferStateChangeRecord = fxTransferStateChangeRecord
|
|
503
|
+
logger.debug('saveFxFulfilResponse::fxTransferStateChange')
|
|
504
|
+
// TODO: Need to handle the following incase of error
|
|
505
|
+
// if (fspiopError) {
|
|
506
|
+
// const insertedTransferStateChange = await knex('fxTransferStateChange').transacting(trx)
|
|
507
|
+
// .where({ commitRequestId })
|
|
508
|
+
// .forUpdate().first().orderBy('fxTransferStateChangeId', 'desc')
|
|
509
|
+
// fxTransferStateChangeRecord.fxTransferStateChangeId = insertedTransferStateChange.fxTransferStateChangeId
|
|
510
|
+
// fxTransferErrorRecord.fxTransferStateChangeId = insertedTransferStateChange.fxTransferStateChangeId
|
|
511
|
+
// await knex('transferError').transacting(trx).insert(fxTransferErrorRecord)
|
|
512
|
+
// result.fxTransferErrorRecord = fxTransferErrorRecord
|
|
513
|
+
// logger.debug('saveFxFulfilResponse::transferError')
|
|
514
|
+
// }
|
|
515
|
+
histTFxFulfilResponseValidationPassedEnd({ success: true, queryName: 'facade_saveFxFulfilResponse_transaction' })
|
|
516
|
+
result.savePayeeTransferResponseExecuted = true
|
|
517
|
+
logger.debug('saveFxFulfilResponse::success')
|
|
518
|
+
} catch (err) {
|
|
519
|
+
histTFxFulfilResponseValidationPassedEnd({ success: false, queryName: 'facade_saveFxFulfilResponse_transaction' })
|
|
520
|
+
logger.error('saveFxFulfilResponse::failure')
|
|
521
|
+
throw err
|
|
522
|
+
}
|
|
523
|
+
})
|
|
524
|
+
histTimerSaveFulfilResponseEnd({ success: true, queryName: 'facade_saveFulfilResponse' })
|
|
525
|
+
return result
|
|
526
|
+
} catch (err) {
|
|
527
|
+
logger.warn('error in saveFxFulfilResponse', err)
|
|
528
|
+
histTimerSaveFulfilResponseEnd({ success: false, queryName: 'facade_saveFulfilResponse' })
|
|
529
|
+
throw ErrorHandler.Factory.reformatFSPIOPError(err)
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
const updateFxPrepareReservedForwarded = async function (commitRequestId) {
|
|
534
|
+
try {
|
|
535
|
+
const knex = await Db.getKnex()
|
|
536
|
+
return await knex('fxTransferStateChange')
|
|
537
|
+
.insert({
|
|
538
|
+
commitRequestId,
|
|
539
|
+
transferStateId: TransferInternalState.RESERVED_FORWARDED,
|
|
540
|
+
reason: null,
|
|
541
|
+
createdDate: Time.getUTCString(new Date())
|
|
542
|
+
})
|
|
543
|
+
} catch (err) {
|
|
544
|
+
throw ErrorHandler.Factory.reformatFSPIOPError(err)
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
const getFxTransferParticipant = async (participantName, commitRequestId) => {
|
|
549
|
+
try {
|
|
550
|
+
return Db.from('participant').query(async (builder) => {
|
|
551
|
+
return builder
|
|
552
|
+
.where({
|
|
553
|
+
'ftp.commitRequestId': commitRequestId,
|
|
554
|
+
'participant.name': participantName,
|
|
555
|
+
'participant.isActive': 1
|
|
556
|
+
})
|
|
557
|
+
.innerJoin('fxTransferParticipant AS ftp', 'ftp.participantId', 'participant.participantId')
|
|
558
|
+
.select(
|
|
559
|
+
'ftp.*'
|
|
560
|
+
)
|
|
561
|
+
})
|
|
562
|
+
} catch (err) {
|
|
563
|
+
throw ErrorHandler.Factory.reformatFSPIOPError(err)
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
module.exports = {
|
|
568
|
+
getByCommitRequestId,
|
|
569
|
+
getByDeterminingTransferId,
|
|
570
|
+
getByIdLight,
|
|
571
|
+
getAllDetailsByCommitRequestId,
|
|
572
|
+
getAllDetailsByCommitRequestIdForProxiedFxTransfer,
|
|
573
|
+
getFxTransferParticipant,
|
|
574
|
+
savePreparedRequest,
|
|
575
|
+
saveFxFulfilResponse,
|
|
576
|
+
saveFxTransfer,
|
|
577
|
+
updateFxPrepareReservedForwarded
|
|
578
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/*****
|
|
2
|
+
License
|
|
3
|
+
--------------
|
|
4
|
+
Copyright © 2017 Bill & Melinda Gates Foundation
|
|
5
|
+
The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at
|
|
6
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
+
Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
|
8
|
+
Contributors
|
|
9
|
+
--------------
|
|
10
|
+
This is the official list of the Mojaloop project contributors for this file.
|
|
11
|
+
Names of the original copyright holders (individuals or organizations)
|
|
12
|
+
should be listed with a '*' in the first column. People who have
|
|
13
|
+
contributed from an organization can be listed under the organization
|
|
14
|
+
that actually holds the copyright for their contributions (see the
|
|
15
|
+
Gates Foundation organization for an example). Those individuals should have
|
|
16
|
+
their names indented and be marked with a '-'. Email address can be added
|
|
17
|
+
optionally within square brackets <email>.
|
|
18
|
+
* Gates Foundation
|
|
19
|
+
- Name Surname <name.surname@gatesfoundation.com>
|
|
20
|
+
|
|
21
|
+
* Vijaya Kumar Guthi <vijaya.guthi@infitx.com>
|
|
22
|
+
--------------
|
|
23
|
+
******/
|
|
24
|
+
|
|
25
|
+
'use strict'
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @module src/models/transfer/transferError/
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
const Db = require('../../lib/db')
|
|
32
|
+
const Logger = require('@mojaloop/central-services-logger')
|
|
33
|
+
|
|
34
|
+
const getByCommitRequestId = async (id) => {
|
|
35
|
+
try {
|
|
36
|
+
const fxTransferError = await Db.from('fxTransferError').query(async (builder) => {
|
|
37
|
+
const result = builder
|
|
38
|
+
.where({ commitRequestId: id })
|
|
39
|
+
.select('*')
|
|
40
|
+
.first()
|
|
41
|
+
return result
|
|
42
|
+
})
|
|
43
|
+
fxTransferError.errorCode = fxTransferError.errorCode.toString()
|
|
44
|
+
return fxTransferError
|
|
45
|
+
} catch (err) {
|
|
46
|
+
Logger.isErrorEnabled && Logger.error(err)
|
|
47
|
+
throw err
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
module.exports = {
|
|
52
|
+
getByCommitRequestId
|
|
53
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/*****
|
|
2
|
+
License
|
|
3
|
+
--------------
|
|
4
|
+
Copyright © 2017 Bill & Melinda Gates Foundation
|
|
5
|
+
The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at
|
|
6
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
+
Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
|
8
|
+
Contributors
|
|
9
|
+
--------------
|
|
10
|
+
This is the official list of the Mojaloop project contributors for this file.
|
|
11
|
+
Names of the original copyright holders (individuals or organizations)
|
|
12
|
+
should be listed with a '*' in the first column. People who have
|
|
13
|
+
contributed from an organization can be listed under the organization
|
|
14
|
+
that actually holds the copyright for their contributions (see the
|
|
15
|
+
Gates Foundation organization for an example). Those individuals should have
|
|
16
|
+
their names indented and be marked with a '-'. Email address can be added
|
|
17
|
+
optionally within square brackets <email>.
|
|
18
|
+
* Gates Foundation
|
|
19
|
+
- Name Surname <name.surname@gatesfoundation.com>
|
|
20
|
+
|
|
21
|
+
* Infitx
|
|
22
|
+
- Kalin Krustev <kalin.krustev@infitx.com>
|
|
23
|
+
--------------
|
|
24
|
+
******/
|
|
25
|
+
|
|
26
|
+
'use strict'
|
|
27
|
+
|
|
28
|
+
const Db = require('../../lib/db')
|
|
29
|
+
const ErrorHandler = require('@mojaloop/central-services-error-handling')
|
|
30
|
+
|
|
31
|
+
const getByCommitRequestId = async (commitRequestId, isFulfilment = false, isError = false) => {
|
|
32
|
+
try {
|
|
33
|
+
return await Db.from('fxTransferExtension').find({ commitRequestId, isFulfilment, isError })
|
|
34
|
+
} catch (err) {
|
|
35
|
+
throw ErrorHandler.Factory.reformatFSPIOPError(err)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
module.exports = {
|
|
40
|
+
getByCommitRequestId
|
|
41
|
+
}
|