@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.
Files changed (394) hide show
  1. package/.grype.yaml +3 -0
  2. package/.license-scanner.json +16 -0
  3. package/.ncurc.yaml +19 -13
  4. package/.nvmrc +1 -1
  5. package/.nycrc.yml +14 -2
  6. package/CHANGELOG.md +51 -0
  7. package/Dockerfile +13 -10
  8. package/README.md +39 -89
  9. package/audit-ci.jsonc +1 -1
  10. package/config/default.json +60 -3
  11. package/config/deprecated.default-settlement.json +160 -0
  12. package/docker/ml-api-adapter/default.json +28 -0
  13. package/docker-compose.yml +6 -0
  14. package/nodemon.json +6 -0
  15. package/package.json +128 -64
  16. package/{sbom-v19.13.2.csv → sbom-v20.0.0.csv} +886 -736
  17. package/scripts/_wait4_all.js +5 -5
  18. package/scripts/transferSettlementTemp/interchangeFeeCalculation.js +51 -0
  19. package/src/api/index.ts +30 -0
  20. package/src/api/interface/swagger.json +2249 -2054
  21. package/src/api/participants/routes.js +1 -1
  22. package/src/api/root/handler.int.ts +55 -0
  23. package/src/api/routes.js +7 -6
  24. package/src/api/server.ts +27 -0
  25. package/src/api/server.unit.ts +16 -0
  26. package/src/api/settlementModels/routes.js +4 -4
  27. package/src/domain/participant/index.d.ts +47 -0
  28. package/src/domain/participant/index.int.ts +724 -0
  29. package/src/domain/participant/index.js +4 -5
  30. package/src/domain/position/fx-prepare.js +1 -1
  31. package/src/domain/position/fx-timeout-reserved.js +6 -0
  32. package/src/domain/position/prepare.js +1 -1
  33. package/src/handlers/admin/handler.js +1 -1
  34. package/src/handlers/index.js +30 -0
  35. package/src/handlers/positions/handler.js +0 -2
  36. package/src/handlers/positions/handlerBatch.js +5 -5
  37. package/src/handlers/register.js +44 -29
  38. package/src/handlers/timeouts/handler.js +1 -4
  39. package/src/handlers/transfers/fx-abort.int.ts +209 -0
  40. package/src/handlers/transfers/fx-handlers.int.ts +275 -0
  41. package/src/handlers/transfers/fx-timeout.int.ts +284 -0
  42. package/src/handlers/transfers/handler.js +1 -3
  43. package/src/handlers/transfers/handlers.int.ts +538 -0
  44. package/src/handlers/transfers/prepare.int.ts +1283 -0
  45. package/src/handlers/transfers/prepare.js +2 -2
  46. package/src/knexfile.js +19 -0
  47. package/src/lib/cache.js +1 -1
  48. package/src/lib/config/index.ts +60 -0
  49. package/src/lib/config/resolver.ts +231 -0
  50. package/src/lib/config/resolver.unit.ts +72 -0
  51. package/src/lib/config/types.ts +372 -0
  52. package/src/lib/config/util.ts +523 -0
  53. package/src/lib/config/util.unit.ts +825 -0
  54. package/src/lib/migrator.js +3 -3
  55. package/src/lib/proxyCache.js +3 -3
  56. package/{migrations → src/migrations}/100100_event.js +1 -1
  57. package/{migrations → src/migrations}/110100_contactType.js +1 -1
  58. package/{migrations → src/migrations}/110200_currency.js +1 -1
  59. package/{migrations → src/migrations}/110201_currency-scale.js +1 -1
  60. package/{migrations → src/migrations}/110300_endpointType.js +1 -1
  61. package/{migrations → src/migrations}/110400_ledgerEntryType.js +1 -1
  62. package/{migrations → src/migrations}/110450_ledgerAccountType.js +1 -1
  63. package/{migrations → src/migrations}/110500_participantLimitType.js +1 -1
  64. package/{migrations → src/migrations}/110600_transferParticipantRoleType.js +1 -1
  65. package/{migrations → src/migrations}/110700_transferState.js +1 -1
  66. package/{migrations → src/migrations}/110900_settlementState.js +1 -1
  67. package/{migrations → src/migrations}/112000_bulkTransferState.js +1 -1
  68. package/{migrations → src/migrations}/112100_bulkProcessingState.js +1 -1
  69. package/{migrations → src/migrations}/200100_participant.js +1 -1
  70. package/{migrations → src/migrations}/200200_participantContact.js +1 -1
  71. package/{migrations → src/migrations}/200300_participantEndpoint.js +1 -1
  72. package/{migrations → src/migrations}/200400_participantParty.js +1 -1
  73. package/{migrations → src/migrations}/200600_token.js +1 -1
  74. package/{migrations → src/migrations}/200601_token-indexes.js +1 -1
  75. package/{migrations → src/migrations}/300100_transferDuplicateCheck.js +2 -2
  76. package/{migrations → src/migrations}/300150_bulkTransferDuplicateCheck.js +2 -2
  77. package/{migrations → src/migrations}/300200_transfer.js +2 -2
  78. package/{migrations → src/migrations}/300202_transfer-decimal184.js +1 -1
  79. package/{migrations → src/migrations}/300250_bulkTransfer.js +2 -3
  80. package/{migrations → src/migrations}/300275_bulkTransferAssociation.js +2 -3
  81. package/{migrations → src/migrations}/300300_ilpPacket.js +1 -1
  82. package/{migrations → src/migrations}/300400_transferStateChange.js +1 -1
  83. package/{migrations → src/migrations}/300450_bulkTransferStateChange.js +1 -1
  84. package/{migrations → src/migrations}/300500_segment.js +1 -1
  85. package/{migrations → src/migrations}/310100_participantCurrency.js +1 -1
  86. package/{migrations → src/migrations}/310200_transferParticipant.js +1 -1
  87. package/{migrations → src/migrations}/310202_transferParticipant-decimal184.js +1 -1
  88. package/{migrations → src/migrations}/310204_transferParticipant-participantId.js +2 -2
  89. package/{migrations → src/migrations}/310300_participantPosition.js +1 -1
  90. package/{migrations → src/migrations}/310302_participantPosition-decimal184.js +1 -1
  91. package/{migrations → src/migrations}/310400_participantPositionChange.js +1 -1
  92. package/{migrations → src/migrations}/310402_participantPositionChange-decimal184.js +1 -1
  93. package/{migrations → src/migrations}/310403_participantPositionChange-participantCurrencyId.js +2 -2
  94. package/{migrations → src/migrations}/310404_participantPositionChange-change.js +2 -2
  95. package/{migrations → src/migrations}/310500_participantLimit.js +1 -1
  96. package/{migrations → src/migrations}/310502_participantLimit-decimal184.js +1 -1
  97. package/{migrations → src/migrations}/400100_settlementWindow.js +1 -1
  98. package/{migrations → src/migrations}/400200_settlement.js +1 -1
  99. package/{migrations → src/migrations}/400300_settlementSettlementWindow.js +1 -1
  100. package/{migrations → src/migrations}/400301_settlementSettlementWindow-indexes.js +0 -1
  101. package/{migrations → src/migrations}/400400_settlementWindowStateChange.js +1 -1
  102. package/{migrations → src/migrations}/400500_settlementTransferParticipant.js +1 -1
  103. package/{migrations → src/migrations}/400502_settlementTransferParticipant-decimal184.js +1 -1
  104. package/{migrations → src/migrations}/400600_settlementParticipantCurrency.js +1 -1
  105. package/{migrations → src/migrations}/400602_settlementParticipantCurrency-decimal184.js +1 -1
  106. package/{migrations → src/migrations}/400700_settlementParticipantCurrencyStateChange.js +1 -1
  107. package/{migrations → src/migrations}/400800_settlementStateChange.js +1 -1
  108. package/{migrations → src/migrations}/400900_settlementWindowContent.js +1 -1
  109. package/{migrations → src/migrations}/401000_settlementWindowContentStateChange.js +1 -1
  110. package/{migrations → src/migrations}/401001_settlementWindowContentStateChange-indexes.js +6 -6
  111. package/{migrations → src/migrations}/401200_settlementContentAggregation.js +1 -1
  112. package/{migrations → src/migrations}/401300_settlementModel.js +1 -1
  113. package/{migrations → src/migrations}/410100_transferFulfilmentDuplicateCheck.js +1 -1
  114. package/{migrations → src/migrations}/410102_transferFulfilmentDuplicateCheck-dropForeignTransferId.js +1 -1
  115. package/{migrations → src/migrations}/410103_transferFulfilmentDuplicateCheck-hashNullable.js +1 -1
  116. package/{migrations → src/migrations}/410200_transferFulfilment.js +1 -1
  117. package/{migrations → src/migrations}/410202_transferFulfilment-ilpFulfilment.js +1 -1
  118. package/{migrations → src/migrations}/410203_transferFulfilment-foreignTransferFulfilmentId.js +1 -1
  119. package/{migrations → src/migrations}/410240_bulkTransferFulfilmentDuplicateCheck.js +1 -1
  120. package/{migrations → src/migrations}/410250_bulkTransferFulfilment.js +1 -1
  121. package/{migrations → src/migrations}/410300_transferExtension.js +1 -1
  122. package/{migrations → src/migrations}/410302_transferExtension-transferErrorId.js +1 -1
  123. package/{migrations → src/migrations}/410350_bulkTransferExtension.js +1 -1
  124. package/{migrations → src/migrations}/410400_transferTimeout.js +1 -1
  125. package/{migrations → src/migrations}/410450_transferErrorDuplicateCheck.js +1 -1
  126. package/{migrations → src/migrations}/410500_transferError.js +1 -1
  127. package/{migrations → src/migrations}/410502_transferError-foreignTransferErrorDuplicateCheckId.js +1 -1
  128. package/{migrations → src/migrations}/410550_bulkTransferError.js +1 -1
  129. package/{migrations → src/migrations}/410600_expiringTransfer.js +1 -1
  130. package/{migrations → src/migrations}/500401_quote-hotfix-2719.js +8 -8
  131. package/{migrations → src/migrations}/500501_feature-fixSubIdRef.js +12 -12
  132. package/{migrations → src/migrations}/500601_party-2480.js +3 -3
  133. package/{migrations → src/migrations}/501001_quoteExtension-quote-service-174.js +1 -2
  134. package/{migrations → src/migrations}/501002_quoteExtension-2522.js +3 -3
  135. package/{migrations → src/migrations}/600010_fxTransferType.js +1 -1
  136. package/{migrations → src/migrations}/600012_fxParticipantCurrencyType.js +1 -1
  137. package/{migrations → src/migrations}/600100_fxTransferDuplicateCheck.js +2 -2
  138. package/{migrations → src/migrations}/600110_fxTransferErrorDuplicateCheck.js.js +1 -1
  139. package/{migrations → src/migrations}/600200_fxTransfer.js +2 -2
  140. package/{migrations → src/migrations}/600400_fxTransferStateChange.js +1 -1
  141. package/{migrations → src/migrations}/600501_fxWatchList.js +2 -2
  142. package/{migrations → src/migrations}/600600_fxTransferFulfilmentDuplicateCheck.js +1 -1
  143. package/{migrations → src/migrations}/600700_fxTransferFulfilment.js +1 -1
  144. package/{migrations → src/migrations}/600800_fxTransferExtension.js +1 -1
  145. package/{migrations → src/migrations}/601400_fxTransferTimeout.js +1 -1
  146. package/{migrations → src/migrations}/601500_fxTransferError.js +1 -1
  147. package/{migrations → src/migrations}/610200_fxTransferParticipant.js +1 -1
  148. package/{migrations → src/migrations}/610202_fxTransferParticipant-participantId.js +2 -2
  149. package/{migrations → src/migrations}/610403_participantPositionChange-fxTransfer.js +1 -1
  150. package/{migrations → src/migrations}/800100_quotePartyView.js +1 -1
  151. package/{migrations → src/migrations}/800101_feature-fixSubIdRef.js +1 -1
  152. package/{migrations → src/migrations}/800200_quoteView.js +1 -1
  153. package/{migrations → src/migrations}/800300_quoteResponseView.js +1 -1
  154. package/{migrations → src/migrations}/900100_foreign-keys.js +18 -18
  155. package/{migrations → src/migrations}/900101_foreign-keys.js +6 -6
  156. package/{migrations → src/migrations}/910100_feature904DDL.js +7 -7
  157. package/{migrations → src/migrations}/910101_feature904DataMigration.js +1 -1
  158. package/{migrations → src/migrations}/910102_feature949DataMigration.js +1 -1
  159. package/{migrations → src/migrations}/910103_feature1093SettlementByCurrency.js +3 -3
  160. package/{migrations → src/migrations}/940101_quotePartyIdInfoExtension-2522.js +25 -25
  161. package/{migrations → src/migrations}/950101_transferParticipantStateChange.js +2 -2
  162. package/{migrations → src/migrations}/950102_settlementModel-adjustPosition.js +2 -2
  163. package/{migrations → src/migrations}/950103_dropTransferParticipantStateChange.js +3 -3
  164. package/{migrations → src/migrations}/950104_settlementModel-settlementAccountTypeId.js +3 -3
  165. package/src/migrations/950107_settlementWindowContent_foreign_settlementModel.js +63 -0
  166. package/{migrations → src/migrations}/950108_participantProxy.js +1 -2
  167. package/{migrations → src/migrations}/950120_fxQuoteConversionTerms_sourceAmount_nullable.js +1 -1
  168. package/{migrations → src/migrations}/960100_create_externalParticipant.js +2 -2
  169. package/{migrations → src/migrations}/960110_alter_transferParticipant__addFiled_externalParticipantId.js +2 -2
  170. package/{migrations → src/migrations}/961001_transferForwarded.js +1 -1
  171. package/{migrations → src/migrations}/961002_fxTransferForwarded.js +1 -1
  172. package/src/models/participant/externalParticipant.int.ts +85 -0
  173. package/src/models/participant/facade.js +4 -2
  174. package/src/models/participant/participantCurrencyCached.js +1 -1
  175. package/src/models/position/facade.js +8 -2
  176. package/src/models/transfer/facade.int.ts +139 -0
  177. package/src/models/transfer/facade.js +8 -3
  178. package/src/models/transfer/transferDuplicateCheck.js +2 -2
  179. package/src/models/transfer/transferError.int.ts +112 -0
  180. package/src/models/transfer/transferExtension.int.ts +137 -0
  181. package/src/models/transfer/transferStateChange.int.ts +117 -0
  182. package/{seeds → src/seeds}/participant.js +1 -1
  183. package/{seeds → src/seeds}/settlementInterchange.js +1 -0
  184. package/src/settlement/api/handlerRoutes.js +71 -0
  185. package/src/settlement/api/handlers/health.js +10 -0
  186. package/src/settlement/api/handlers/index.js +57 -0
  187. package/src/settlement/api/handlers/settlementWindows/{id}.js +103 -0
  188. package/src/settlement/api/handlers/settlementWindows.js +77 -0
  189. package/src/settlement/api/handlers/settlements/{id}.js +133 -0
  190. package/src/settlement/api/handlers/settlements/{sid}/participants/{pid}/accounts/{aid}.js +127 -0
  191. package/src/settlement/api/handlers/settlements/{sid}/participants/{pid}.js +127 -0
  192. package/src/settlement/api/handlers/settlements.js +114 -0
  193. package/src/settlement/api/openapiRouting.js +87 -0
  194. package/src/settlement/api/routes.js +176 -0
  195. package/src/settlement/domain/rules/index.js +46 -0
  196. package/src/settlement/domain/settlement/index.js +405 -0
  197. package/src/settlement/domain/settlementWindow/index.js +117 -0
  198. package/src/settlement/domain/transactions/index.js +83 -0
  199. package/src/settlement/domain/transferSettlement/index.js +57 -0
  200. package/src/settlement/handlers/deferredSettlement/handler.js +180 -0
  201. package/src/settlement/handlers/grossSettlement/handler.js +180 -0
  202. package/src/settlement/handlers/index.js +101 -0
  203. package/src/settlement/handlers/register.js +92 -0
  204. package/src/settlement/handlers/rules/handler.js +164 -0
  205. package/src/settlement/interface/swagger-handler.json +34 -0
  206. package/src/settlement/interface/swagger.json +1560 -0
  207. package/src/settlement/lib/db.js +32 -0
  208. package/src/settlement/lib/kafka/index.js +41 -0
  209. package/src/settlement/lib/kafka/producer.js +142 -0
  210. package/src/settlement/lib/scriptEngine.js +99 -0
  211. package/src/settlement/lib/scriptsLoader.js +175 -0
  212. package/src/settlement/lib/utility.js +243 -0
  213. package/src/settlement/models/ilpPackets/ilpPacket.js +42 -0
  214. package/src/settlement/models/lib/enums.js +192 -0
  215. package/src/settlement/models/misc/migrationLock.js +53 -0
  216. package/src/settlement/models/settlement/facade.js +1652 -0
  217. package/src/settlement/models/settlement/index.js +55 -0
  218. package/src/settlement/models/settlement/participantCurrency.js +48 -0
  219. package/src/settlement/models/settlement/settlement.js +49 -0
  220. package/src/settlement/models/settlement/settlementModel.js +44 -0
  221. package/src/settlement/models/settlement/settlementParticipantCurrency.js +61 -0
  222. package/src/settlement/models/settlement/settlementStateChange.js +44 -0
  223. package/src/settlement/models/settlement/settlementTransferParticipant.js +46 -0
  224. package/src/settlement/models/settlementWindow/facade.js +345 -0
  225. package/src/settlement/models/settlementWindow/index.js +47 -0
  226. package/src/settlement/models/settlementWindow/settlementWindowStateChange.js +55 -0
  227. package/src/settlement/models/settlementWindowContent/facade.js +79 -0
  228. package/src/settlement/models/settlementWindowContent/index.js +40 -0
  229. package/src/settlement/models/settlementWindowContent/settlementWindowContentStateChange.js +53 -0
  230. package/src/settlement/models/transferSettlement/facade.js +363 -0
  231. package/src/settlement/models/transferSettlement/index.js +42 -0
  232. package/src/settlement/shared/logger/index.js +7 -0
  233. package/src/settlement/shared/plugins.js +88 -0
  234. package/src/settlement/shared/setup.js +224 -0
  235. package/src/settlement/utils/truthyProperty.js +37 -0
  236. package/src/shared/legacyUtilShim.js +20 -0
  237. package/src/shared/plugins.js +3 -3
  238. package/src/shared/results.ts +22 -0
  239. package/src/shared/results.unit.ts +38 -0
  240. package/src/shared/setup.js +14 -1
  241. package/src/testing/api-helpers.ts +1222 -0
  242. package/src/testing/exec-async.ts +67 -0
  243. package/src/testing/harness.snapshot.sql +3895 -0
  244. package/src/testing/harness.test.ts +15 -0
  245. package/src/testing/harness.ts +1160 -0
  246. package/src/testing/kafka.ts +221 -0
  247. package/src/testing/prng.ts +82 -0
  248. package/src/testing/rdkafka.test.ts +263 -0
  249. package/src/testing/run.ts +559 -0
  250. package/src/testing/snapshot.test.ts +92 -0
  251. package/src/testing/snapshot.ts +549 -0
  252. package/src/testing/tap-stream.ts +164 -0
  253. package/src/testing/types.ts +95 -0
  254. package/src/testing/util.ts +333 -0
  255. package/src/types/central-services-error-handling.d.ts +72 -0
  256. package/src/types/central-services-stream.d.ts +148 -0
  257. package/test-integration.Dockerfile +0 -2
  258. package/test.Dockerfile +0 -2
  259. package/tsconfig.json +40 -0
  260. package/config/knexfile.js +0 -19
  261. package/migrations/950107_settlementWindowContent_foreign_settlementModel.js +0 -63
  262. package/src/api/index.js +0 -16
  263. package/src/lib/config.js +0 -81
  264. /package/{migrations → src/migrations}/110101_contactType-indexes.js +0 -0
  265. /package/{migrations → src/migrations}/110301_endpointType-indexes.js +0 -0
  266. /package/{migrations → src/migrations}/110401_ledgerEntryType-indexes.js +0 -0
  267. /package/{migrations → src/migrations}/110451_ledgerAccountType-indexes.js +0 -0
  268. /package/{migrations → src/migrations}/110501_participantLimitType-indexes.js +0 -0
  269. /package/{migrations → src/migrations}/110601_transferParticipantRoleType-indexes.js +0 -0
  270. /package/{migrations → src/migrations}/110800_settlementWindowState.js +0 -0
  271. /package/{migrations → src/migrations}/111000_amountType.js +0 -0
  272. /package/{migrations → src/migrations}/111001_amountType-indexes.js +0 -0
  273. /package/{migrations → src/migrations}/111100_balanceOfPayments.js +0 -0
  274. /package/{migrations → src/migrations}/111101_balanceOfPayments-indexes.js +0 -0
  275. /package/{migrations → src/migrations}/111200_partyIdentifierType.js +0 -0
  276. /package/{migrations → src/migrations}/111201_partyIdentifierType-indexes.js +0 -0
  277. /package/{migrations → src/migrations}/111300_partyType.js +0 -0
  278. /package/{migrations → src/migrations}/111301_partyType-indexes.js +0 -0
  279. /package/{migrations → src/migrations}/111400_quoteDuplicateCheck.js +0 -0
  280. /package/{migrations → src/migrations}/111500_transactionInitiator.js +0 -0
  281. /package/{migrations → src/migrations}/111501_transactionInitiator-indexes.js +0 -0
  282. /package/{migrations → src/migrations}/111600_transactionInitiatorType.js +0 -0
  283. /package/{migrations → src/migrations}/111601_transactionInitiatorType-indexes.js +0 -0
  284. /package/{migrations → src/migrations}/111700_settlementDelay.js +0 -0
  285. /package/{migrations → src/migrations}/111701_settlementDelay-indexes.js +0 -0
  286. /package/{migrations → src/migrations}/111800_settlementInterchange.js +0 -0
  287. /package/{migrations → src/migrations}/111801_settlementInterchange-indexes.js +0 -0
  288. /package/{migrations → src/migrations}/111900_settlementGranularity.js +0 -0
  289. /package/{migrations → src/migrations}/111901_settlementGranularity-indexes.js +0 -0
  290. /package/{migrations → src/migrations}/112101_bulkProcessingState-indexes.js +0 -0
  291. /package/{migrations → src/migrations}/200101_participant-indexes.js +0 -0
  292. /package/{migrations → src/migrations}/200201_participantContact-indexes.js +0 -0
  293. /package/{migrations → src/migrations}/200301_participantEndpoint-indexes.js +0 -0
  294. /package/{migrations → src/migrations}/200401_participantParty-indexes.js +0 -0
  295. /package/{migrations → src/migrations}/300201_transfer-indexes.js +0 -0
  296. /package/{migrations → src/migrations}/300251_bulkTransfer-indexes.js +0 -0
  297. /package/{migrations → src/migrations}/300276_bulkTransferAssociation-indexes.js +0 -0
  298. /package/{migrations → src/migrations}/300401_transferStateChange-indexes.js +0 -0
  299. /package/{migrations → src/migrations}/300451_bulkTransferStateChange-indexes.js +0 -0
  300. /package/{migrations → src/migrations}/300501_segment-indexes.js +0 -0
  301. /package/{migrations → src/migrations}/310101_participantCurrency-indexes.js +0 -0
  302. /package/{migrations → src/migrations}/310201_transferParticipant-indexes.js +0 -0
  303. /package/{migrations → src/migrations}/310203_transferParticipant-indexes.js +0 -0
  304. /package/{migrations → src/migrations}/310301_participantPosition-indexes.js +0 -0
  305. /package/{migrations → src/migrations}/310401_participantPositionChange-indexes.js +0 -0
  306. /package/{migrations → src/migrations}/310405_participantPositionChange-positionChange.js +0 -0
  307. /package/{migrations → src/migrations}/310406_participantPositionChange-positionChange-revert.js +0 -0
  308. /package/{migrations → src/migrations}/310501_participantLimit-indexes.js +0 -0
  309. /package/{migrations → src/migrations}/310503_participantLimit-indexes-composite.js +0 -0
  310. /package/{migrations → src/migrations}/400401_settlmentWindowStateChange-indexes.js +0 -0
  311. /package/{migrations → src/migrations}/400501_settlementTransferParticipant-indexes.js +0 -0
  312. /package/{migrations → src/migrations}/400601_settlementParticipantCurrency-indexes.js +0 -0
  313. /package/{migrations → src/migrations}/400701_settlementParticipantCurrencyStateChange-indexes.js +0 -0
  314. /package/{migrations → src/migrations}/400801_settlementStateChange-indexes.js +0 -0
  315. /package/{migrations → src/migrations}/401002_settlementWindowContent-indexes.js +0 -0
  316. /package/{migrations → src/migrations}/401201_settlementContentAggregation-indexes.js +0 -0
  317. /package/{migrations → src/migrations}/401301_settlementModel-indexes.js +0 -0
  318. /package/{migrations → src/migrations}/410101_transferFulfilmentDuplicateCheck-indexes.js +0 -0
  319. /package/{migrations → src/migrations}/410201_transferFulfilment-indexes.js +0 -0
  320. /package/{migrations → src/migrations}/410301_transferExtension-indexes.js +0 -0
  321. /package/{migrations → src/migrations}/410351_bulkTransferExtension-indexes.js +0 -0
  322. /package/{migrations → src/migrations}/410401_transferTimeout-indexes.js +0 -0
  323. /package/{migrations → src/migrations}/410501_transferError-indexes.js +0 -0
  324. /package/{migrations → src/migrations}/410551_bulkTransferError-indexes.js +0 -0
  325. /package/{migrations → src/migrations}/410601_expiringTransfer-indexes.js +0 -0
  326. /package/{migrations → src/migrations}/500100_transactionReference.js +0 -0
  327. /package/{migrations → src/migrations}/500101_transactionReference-indexes.js +0 -0
  328. /package/{migrations → src/migrations}/500200_transactionScenario.js +0 -0
  329. /package/{migrations → src/migrations}/500201_transactionScenario-indexes.js +0 -0
  330. /package/{migrations → src/migrations}/500300_transactionSubScenario.js +0 -0
  331. /package/{migrations → src/migrations}/500400_quote.js +0 -0
  332. /package/{migrations → src/migrations}/500500_quoteParty.js +0 -0
  333. /package/{migrations → src/migrations}/500600_party.js +0 -0
  334. /package/{migrations → src/migrations}/500700_quoteResponse.js +0 -0
  335. /package/{migrations → src/migrations}/500800_quoteResponseIlpPacket.js +0 -0
  336. /package/{migrations → src/migrations}/500900_geoCode.js +0 -0
  337. /package/{migrations → src/migrations}/501000_quoteExtension.js +0 -0
  338. /package/{migrations → src/migrations}/501100_quoteResponseDuplicateCheck.js +0 -0
  339. /package/{migrations → src/migrations}/501200_quoteError.js +0 -0
  340. /package/{migrations → src/migrations}/501300_transferRules.js +0 -0
  341. /package/{migrations → src/migrations}/600011_fxTransferType-indexes.js +0 -0
  342. /package/{migrations → src/migrations}/600013_fxParticipantCurrencyType-indexes.js +0 -0
  343. /package/{migrations → src/migrations}/600201_fxTransfer-indexes.js +0 -0
  344. /package/{migrations → src/migrations}/600401_fxTransferStateChange-indexes.js +0 -0
  345. /package/{migrations → src/migrations}/600502_fxWatchList-indexes.js +0 -0
  346. /package/{migrations → src/migrations}/600601_fxTransferFulfilmentDuplicateCheck-indexes.js +0 -0
  347. /package/{migrations → src/migrations}/600701_fxTransferFulfilment-indexes.js +0 -0
  348. /package/{migrations → src/migrations}/601401_fxTransferTimeout-indexes.js +0 -0
  349. /package/{migrations → src/migrations}/601501_fxTransferError-indexes.js +0 -0
  350. /package/{migrations → src/migrations}/610201_fxTransferParticipant-indexes.js +0 -0
  351. /package/{migrations → src/migrations}/910102_hotfix954.js +0 -0
  352. /package/{migrations → src/migrations}/940100_quotePartyIdInfoExtension.js +0 -0
  353. /package/{migrations → src/migrations}/950100_settlementContentAggregation-decimal184.js +0 -0
  354. /package/{migrations → src/migrations}/950106_unique_settlement_model_ledger_account_currency.js +0 -0
  355. /package/{migrations → src/migrations}/950109_fxQuote.js +0 -0
  356. /package/{migrations → src/migrations}/950110_fxQuoteResponse.js +0 -0
  357. /package/{migrations → src/migrations}/950111_fxQuoteError.js +0 -0
  358. /package/{migrations → src/migrations}/950113_fxQuoteDuplicateCheck.js +0 -0
  359. /package/{migrations → src/migrations}/950114_fxQuoteResponseDuplicateCheck.js +0 -0
  360. /package/{migrations → src/migrations}/950115_fxQuoteConversionTerms.js +0 -0
  361. /package/{migrations → src/migrations}/950116_fxQuoteConversionTermsExtension.js +0 -0
  362. /package/{migrations → src/migrations}/950117_fxQuoteResponseConversionTerms.js +0 -0
  363. /package/{migrations → src/migrations}/950118_fxQuoteResponseConversionTermsExtension.js +0 -0
  364. /package/{migrations → src/migrations}/950119_fxCharge.js +0 -0
  365. /package/{migrations → src/migrations}/960111_alter_fxTransferParticipant__addFiled_externalParticipantId.js +0 -0
  366. /package/{migrations → src/migrations}/960112_fxTransfer-indexes2.js +0 -0
  367. /package/{migrations → src/migrations}/960113_fxTransferExtension-indexes.js +0 -0
  368. /package/{migrations → src/migrations}/960114_fxTransferTimeout-indexes2.js +0 -0
  369. /package/{migrations → src/migrations}/961000_participantEndpoint_unique.js +0 -0
  370. /package/{migrations → src/migrations}/migration.template +0 -0
  371. /package/{seeds → src/seeds}/amountType.js +0 -0
  372. /package/{seeds → src/seeds}/balanceOfPayments.js +0 -0
  373. /package/{seeds → src/seeds}/bulkProcessingState.js +0 -0
  374. /package/{seeds → src/seeds}/bulkTransferState.js +0 -0
  375. /package/{seeds → src/seeds}/currency.js +0 -0
  376. /package/{seeds → src/seeds}/endpointType.js +0 -0
  377. /package/{seeds → src/seeds}/fxParticipantCurrencyType.js +0 -0
  378. /package/{seeds → src/seeds}/fxTransferType.js +0 -0
  379. /package/{seeds → src/seeds}/ledgerAccountType.js +0 -0
  380. /package/{seeds → src/seeds}/ledgerEntryType.js +0 -0
  381. /package/{seeds → src/seeds}/participantLimitType.js +0 -0
  382. /package/{seeds → src/seeds}/partyIdentifierType.js +0 -0
  383. /package/{seeds → src/seeds}/partyType.js +0 -0
  384. /package/{seeds → src/seeds}/settlementDelay.js +0 -0
  385. /package/{seeds → src/seeds}/settlementGranularity.js +0 -0
  386. /package/{seeds → src/seeds}/settlementState.js +0 -0
  387. /package/{seeds → src/seeds}/settlementWindow1State.js +0 -0
  388. /package/{seeds → src/seeds}/settlementWindow2Open.js +0 -0
  389. /package/{seeds → src/seeds}/transactionInitiator.js +0 -0
  390. /package/{seeds → src/seeds}/transactionInitiatorType.js +0 -0
  391. /package/{seeds → src/seeds}/transactionScenario.js +0 -0
  392. /package/{seeds → src/seeds}/transferParticipantRoleType.js +0 -0
  393. /package/{seeds → src/seeds}/transferState.js +0 -0
  394. /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 {