ml-testing-toolkit 18.13.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 (319) hide show
  1. package/.dockerignore +10 -0
  2. package/.grype.yaml +16 -0
  3. package/.ncurc.yaml +9 -0
  4. package/.nvmrc +1 -0
  5. package/.versionrc.js +16 -0
  6. package/CHANGELOG.md +504 -0
  7. package/CODEOWNERS +30 -0
  8. package/Dockerfile +42 -0
  9. package/Dockerfile-newman +13 -0
  10. package/LICENSE.md +9 -0
  11. package/README.md +119 -0
  12. package/assets/diagrams/architectural/architectural-diagram.svg +3 -0
  13. package/assets/diagrams/flow/flow-diagram.svg +3 -0
  14. package/assets/images/Sample-Response-Failure.png +0 -0
  15. package/assets/images/Screenshot 2020-04-16 at 22.58.04.png +0 -0
  16. package/assets/images/TLS-Enabled-on-Environment.png +0 -0
  17. package/assets/images/adapter-mutual-tls-enabled.png +0 -0
  18. package/assets/images/add-additional-input-values.png +0 -0
  19. package/assets/images/add-condition-button.png +0 -0
  20. package/assets/images/add-new-assertion.png +0 -0
  21. package/assets/images/add-new-input-value.png +0 -0
  22. package/assets/images/add-new-input-variable.png +0 -0
  23. package/assets/images/additional-transfers.png +0 -0
  24. package/assets/images/api-provisioning-add-new-api-confirmation.png +0 -0
  25. package/assets/images/api-provisioning-file-input-window.png +0 -0
  26. package/assets/images/api-provisioning-list-apis-view.png +0 -0
  27. package/assets/images/api-provisioning-menu-item.png +0 -0
  28. package/assets/images/apply_and_restart.jpg +0 -0
  29. package/assets/images/assess-request-or-response.png +0 -0
  30. package/assets/images/assess-response-equation-save.png +0 -0
  31. package/assets/images/assess-response-equation.png +0 -0
  32. package/assets/images/assess-response-status.png +0 -0
  33. package/assets/images/building-new-rules-file.png +0 -0
  34. package/assets/images/callback-rules-screen.png +0 -0
  35. package/assets/images/configurable-parameter-assertion.png +0 -0
  36. package/assets/images/configurable-parameter-currency.png +0 -0
  37. package/assets/images/configurable-parameter.png +0 -0
  38. package/assets/images/connection-manager-ui-opening.png +0 -0
  39. package/assets/images/create-inbound-user-simulator.png +0 -0
  40. package/assets/images/creating-new-rule-file.png +0 -0
  41. package/assets/images/dfsp-client-cacert.png +0 -0
  42. package/assets/images/dfsp-client-submit.png +0 -0
  43. package/assets/images/dfsp-client.png +0 -0
  44. package/assets/images/dfsp-p2p-happy-path.png +0 -0
  45. package/assets/images/dfsp-server-cacert.png +0 -0
  46. package/assets/images/dfsp-server-cert.png +0 -0
  47. package/assets/images/download-report.png +0 -0
  48. package/assets/images/drive_have_not_been_shared.jpg +0 -0
  49. package/assets/images/event-response-options.png +0 -0
  50. package/assets/images/expand-monitoring-messages.png +0 -0
  51. package/assets/images/fixed-response-sample.png +0 -0
  52. package/assets/images/header-selection.png +0 -0
  53. package/assets/images/heap_error_windows.jpg +0 -0
  54. package/assets/images/hosted-mode-docker-compose-intro.png +0 -0
  55. package/assets/images/hub-client-cert.png +0 -0
  56. package/assets/images/import-template.png +0 -0
  57. package/assets/images/inbound-requests-environment.png +0 -0
  58. package/assets/images/inbound-requests-scripts.png +0 -0
  59. package/assets/images/jws-certificate-submit.png +0 -0
  60. package/assets/images/jws-certificate.png +0 -0
  61. package/assets/images/jws-certs-keys.png +0 -0
  62. package/assets/images/jws-hub-certs-keys.png +0 -0
  63. package/assets/images/local-enable-jws-publickey.png +0 -0
  64. package/assets/images/local-mutual-tls-enabled.png +0 -0
  65. package/assets/images/local_drives_to_be_available.jpg +0 -0
  66. package/assets/images/mcm-environment-opening.png +0 -0
  67. package/assets/images/menu-items.png +0 -0
  68. package/assets/images/mock-response-sample.png +0 -0
  69. package/assets/images/monitoring-initial-state.png +0 -0
  70. package/assets/images/monitoring-messages.png +0 -0
  71. package/assets/images/new-empty-assertion.png +0 -0
  72. package/assets/images/opened-imported-template.png +0 -0
  73. package/assets/images/opening-default-settings.png +0 -0
  74. package/assets/images/opening-sync-response-rules.png +0 -0
  75. package/assets/images/opening-view.png +0 -0
  76. package/assets/images/outbound-display-opening-hub.png +0 -0
  77. package/assets/images/outbound-display-opening.png +0 -0
  78. package/assets/images/override-with-environment-variable.png +0 -0
  79. package/assets/images/populate-with-sample-body.png +0 -0
  80. package/assets/images/resource-selection.png +0 -0
  81. package/assets/images/rule-builder-select-api.png +0 -0
  82. package/assets/images/sample-condition-add-configurable-params.png +0 -0
  83. package/assets/images/sample-condition.png +0 -0
  84. package/assets/images/sample-editor.png +0 -0
  85. package/assets/images/sample-request.png +0 -0
  86. package/assets/images/sample-test-assertion.png +0 -0
  87. package/assets/images/send-transfer.png +0 -0
  88. package/assets/images/sending-single-test-case-1.png +0 -0
  89. package/assets/images/sending-single-test-case-2.png +0 -0
  90. package/assets/images/sending-test-cases.png +0 -0
  91. package/assets/images/server-certificates-submitted.png +0 -0
  92. package/assets/images/simulator-response.png +0 -0
  93. package/assets/images/simulator-scheme-adapter-endpoint.png +0 -0
  94. package/assets/images/summarized-view-of-rule.png +0 -0
  95. package/assets/images/template-window.png +0 -0
  96. package/assets/images/test-case-editor-console-log.png +0 -0
  97. package/assets/images/test-case-editor-environment-state.png +0 -0
  98. package/assets/images/test-case-editor-scripts.png +0 -0
  99. package/assets/images/test-case-editor.png +0 -0
  100. package/assets/images/testcase-definition-download.png +0 -0
  101. package/assets/images/testcase-definition-edit-meta-info.png +0 -0
  102. package/assets/images/testing-toolkit-mojaloop-testing-toolkit-endpoint.png +0 -0
  103. package/assets/images/tls-hub-certs-keys.png +0 -0
  104. package/assets/images/tls-jws-enabled-on-environment.png +0 -0
  105. package/assets/images/updated-sample-body-data.png +0 -0
  106. package/assets/images/using-configurable-parameter.png +0 -0
  107. package/assets/images/validation-rules-screen.png +0 -0
  108. package/assets/images/view-response.png +0 -0
  109. package/audit-ci.jsonc +7 -0
  110. package/connection-manager/docker-compose.yml +55 -0
  111. package/database/docker-compose.yml +16 -0
  112. package/docker/hosted-mode/docker-compose.yaml +107 -0
  113. package/docker/hosted-mode/keycloak/keycloak-realm.json +2298 -0
  114. package/docker/hosted-mode/mongo-init.sh +1 -0
  115. package/docker/hosted-mode-tls/docker-compose.yaml +171 -0
  116. package/docker/hosted-mode-tls/keycloak/keycloak-realm.json +2298 -0
  117. package/docker/hosted-mode-tls/mongo-init.sh +1 -0
  118. package/docker-compose.yml +62 -0
  119. package/documents/Mojaloop-Testing-Toolkit.md +296 -0
  120. package/documents/RULES_ENGINE.md +403 -0
  121. package/documents/User-Guide-API-Provisioning.md +121 -0
  122. package/documents/User-Guide-CLI.md +218 -0
  123. package/documents/User-Guide-Connection-Manager.md +282 -0
  124. package/documents/User-Guide-Frequently-Asked-Questions.md +39 -0
  125. package/documents/User-Guide-Hosted-Mode-Docker-Compose.md +110 -0
  126. package/documents/User-Guide-Installation.md +163 -0
  127. package/documents/User-Guide-Mojaloop-Testing-Toolkit.md +642 -0
  128. package/documents/User-Guide-OAuth-Server-Deployment.md +283 -0
  129. package/documents/User-Guide-Onboarding-DFSP.md +197 -0
  130. package/documents/User-Guide-Onboarding-HUB.md +191 -0
  131. package/documents/User-Guide.md +53 -0
  132. package/examples/collections/dfsp/p2p_failed_tests.json +7161 -0
  133. package/examples/collections/dfsp/p2p_fx_happy_path.json +502 -0
  134. package/examples/collections/dfsp/p2p_happy_path.json +350 -0
  135. package/examples/collections/dfsp/p2p_happy_path_extended.json +6106 -0
  136. package/examples/collections/dfsp/p2p_happy_path_jws.json +511 -0
  137. package/examples/collections/dfsp/p2p_payee_assertions_websocket.json +441 -0
  138. package/examples/collections/dfsp/sample.json +5029 -0
  139. package/examples/collections/dfsp/transaction_request_service.json +240 -0
  140. package/examples/collections/fxp/FXP.json +264 -0
  141. package/examples/collections/fxp/SDK_backend.json +98 -0
  142. package/examples/collections/fxp/SDK_outbound.json +163 -0
  143. package/examples/collections/hub/hub_01_p2p_happy_path/hub_p2p_receive_quote.json +400 -0
  144. package/examples/collections/hub/hub_01_p2p_happy_path/hub_p2p_send_quote.json +395 -0
  145. package/examples/collections/hub/hub_02_block_transfer/hub_block_transfer.json +393 -0
  146. package/examples/collections/hub/hub_03_funds_in_out/hub_funds_in.json +224 -0
  147. package/examples/collections/hub/hub_03_funds_in_out/hub_funds_out.json +780 -0
  148. package/examples/collections/hub/hub_04_settlements/hub_settlements.json +3138 -0
  149. package/examples/collections/hub/hub_05_transfer_negative_scenarios/hub_transfer_negative_payee_abort.json +475 -0
  150. package/examples/collections/hub/hub_05_transfer_negative_scenarios/hub_transfer_negative_payee_invalid_fulfillment.json +370 -0
  151. package/examples/collections/hub/hub_05_transfer_negative_scenarios/hub_transfer_negative_transfer_timeout.json +262 -0
  152. package/examples/collections/hub/hub_06_transaction_requests_service/hub_trs_authorizations.json +117 -0
  153. package/examples/collections/hub/hub_06_transaction_requests_service/hub_trs_error_framework.json +591 -0
  154. package/examples/collections/hub/hub_06_transaction_requests_service/hub_trs_received_state.json +379 -0
  155. package/examples/collections/hub/hub_06_transaction_requests_service/hub_trs_reject_state.json +361 -0
  156. package/examples/collections/hub/hub_07_quoting_service.json +525 -0
  157. package/examples/collections/hub/hub_08_participant_inactive_stop_transfers.json +706 -0
  158. package/examples/collections/hub/hub_09_duplicate_handling_transfers.json +1377 -0
  159. package/examples/collections/hub/hub_10_on_us_transfers.json +245 -0
  160. package/examples/collections/hub/hub_11_accented_and_spl_chars.json +629 -0
  161. package/examples/collections/hub/hub_12_fspiop_version_1.1.json +646 -0
  162. package/examples/collections/hub/hub_13_bulk_transfers.json +1857 -0
  163. package/examples/collections/iso20022/self_referencing_iso20022.json +926 -0
  164. package/examples/collections/provisioning/testingtoolkitdfsp.json +904 -0
  165. package/examples/environments/dfsp_local_environment.json +46 -0
  166. package/examples/environments/hub_local_environment.json +57 -0
  167. package/jest.config.js +17 -0
  168. package/package.json +199 -0
  169. package/sbom-v18.12.4.csv +1553 -0
  170. package/secrets/keygen.sh +5 -0
  171. package/secrets/privatekey.pem +27 -0
  172. package/secrets/publickey.cer +21 -0
  173. package/secrets/tls/01.pem +132 -0
  174. package/secrets/tls/createSecrets.sh +20 -0
  175. package/secrets/tls/hub_client.csr +32 -0
  176. package/secrets/tls/hub_client_cacert.pem +35 -0
  177. package/secrets/tls/hub_client_cakey.pem +52 -0
  178. package/secrets/tls/hub_client_key.key +52 -0
  179. package/secrets/tls/hub_server.csr +31 -0
  180. package/secrets/tls/hub_server_cacert.pem +35 -0
  181. package/secrets/tls/hub_server_cakey.pem +52 -0
  182. package/secrets/tls/hub_server_cert.pem +132 -0
  183. package/secrets/tls/hub_server_key.key +52 -0
  184. package/secrets/tls/index.txt +1 -0
  185. package/secrets/tls/index.txt.attr +1 -0
  186. package/secrets/tls/openssl-client.cnf +36 -0
  187. package/secrets/tls/openssl-clientca.cnf +71 -0
  188. package/secrets/tls/openssl-server.cnf +39 -0
  189. package/secrets/tls/openssl-serverca.cnf +71 -0
  190. package/secrets/tls/serial.txt +1 -0
  191. package/spec_files/api_definitions/als_admin_1.1/api_spec.yaml +804 -0
  192. package/spec_files/api_definitions/central_admin_1.0/api_spec.yaml +1850 -0
  193. package/spec_files/api_definitions/central_admin_1.0/response_map.json +96 -0
  194. package/spec_files/api_definitions/central_admin_old_9.3/api_spec.yaml +2467 -0
  195. package/spec_files/api_definitions/central_admin_old_9.3/response_map.json +96 -0
  196. package/spec_files/api_definitions/fspiop_1.0/api_spec.yaml +4187 -0
  197. package/spec_files/api_definitions/fspiop_1.0/callback_map.json +568 -0
  198. package/spec_files/api_definitions/fspiop_1.0/mockRef.json +79 -0
  199. package/spec_files/api_definitions/fspiop_1.0/trigger_templates/transaction_request_followup.json +126 -0
  200. package/spec_files/api_definitions/fspiop_1.0/trigger_templates/transaction_request_followup_quotes_only.json +97 -0
  201. package/spec_files/api_definitions/fspiop_1.1/api_spec.yaml +3778 -0
  202. package/spec_files/api_definitions/fspiop_1.1/callback_map.json +568 -0
  203. package/spec_files/api_definitions/fspiop_1.1/mockRef.json +79 -0
  204. package/spec_files/api_definitions/fspiop_1.1/trigger_templates/transaction_request_followup.json +125 -0
  205. package/spec_files/api_definitions/fspiop_2.0/api_spec.yaml +4839 -0
  206. package/spec_files/api_definitions/fspiop_2.0/callback_map.json +716 -0
  207. package/spec_files/api_definitions/fspiop_2.0/mockRef.json +79 -0
  208. package/spec_files/api_definitions/fspiop_2.0/trigger_templates/transaction_request_followup.json +125 -0
  209. package/spec_files/api_definitions/fspiop_2.0_iso20022/api_spec.yaml +8331 -0
  210. package/spec_files/api_definitions/fspiop_2.0_iso20022/callback_map.json +508 -0
  211. package/spec_files/api_definitions/fspiop_2.0_iso20022/mockRef.json +66 -0
  212. package/spec_files/api_definitions/fx-api_2.0/api_spec.yaml +1768 -0
  213. package/spec_files/api_definitions/fx-api_2.0/callback_map.json +188 -0
  214. package/spec_files/api_definitions/fx-api_2.0/mockRef.json +83 -0
  215. package/spec_files/api_definitions/mojaloop_sdk_outbound_scheme_adapter_1.0/api_spec.yaml +2612 -0
  216. package/spec_files/api_definitions/mojaloop_sdk_outbound_scheme_adapter_1.0/mockRef.json +22 -0
  217. package/spec_files/api_definitions/mojaloop_sdk_outbound_scheme_adapter_1.0/response_map.json +35 -0
  218. package/spec_files/api_definitions/mojaloop_simulator_0.1/api_spec.yaml +225 -0
  219. package/spec_files/api_definitions/mojaloop_simulator_sim_1.4/api_spec.yaml +1087 -0
  220. package/spec_files/api_definitions/mojaloop_simulator_sim_1.4/mockRef.json +75 -0
  221. package/spec_files/api_definitions/mojaloop_simulator_sim_1.4/response_map.json +55 -0
  222. package/spec_files/api_definitions/payment_manager_1.4/api_spec.yaml +1389 -0
  223. package/spec_files/api_definitions/sdk-scheme-adapter-backend-v2_1_0-openapi3-snippets_2.1/api_spec.yaml +2834 -0
  224. package/spec_files/api_definitions/sdk-scheme-adapter-outbound-v2_1_0-openapi3-snippets_2.1/api_spec.yaml +3449 -0
  225. package/spec_files/api_definitions/settlements_1.0/api_spec.yaml +983 -0
  226. package/spec_files/api_definitions/settlements_1.0/mockRef.json +38 -0
  227. package/spec_files/api_definitions/settlements_1.0/response_map.json +34 -0
  228. package/spec_files/api_definitions/settlements_2.0/api_spec.yaml +1001 -0
  229. package/spec_files/api_definitions/settlements_2.0/mockRef.json +38 -0
  230. package/spec_files/api_definitions/settlements_2.0/response_map.json +34 -0
  231. package/spec_files/api_definitions/thirdparty_sdk_outbound_0.1/api_spec.yaml +2139 -0
  232. package/spec_files/reports/templates/newman/html_template.html +1202 -0
  233. package/spec_files/reports/templates/newman/pdf_template.html +790 -0
  234. package/spec_files/reports/templates/testcase_definition/table_view.html +1602 -0
  235. package/spec_files/rules_callback/config.json +3 -0
  236. package/spec_files/rules_callback/default.json +2698 -0
  237. package/spec_files/rules_callback/p2p-limit.json +129 -0
  238. package/spec_files/rules_forward/config.json +3 -0
  239. package/spec_files/rules_forward/default.json +482 -0
  240. package/spec_files/rules_response/config.json +3 -0
  241. package/spec_files/rules_response/default.json +295 -0
  242. package/spec_files/rules_validation/config.json +3 -0
  243. package/spec_files/rules_validation/default.json +1 -0
  244. package/spec_files/rules_validation/p2p-limit.json +55 -0
  245. package/spec_files/system_config.json +175 -0
  246. package/spec_files/user_config.json +109 -0
  247. package/src/index.js +67 -0
  248. package/src/lib/MyEventEmitter.js +54 -0
  249. package/src/lib/api-management.js +143 -0
  250. package/src/lib/api-routes/config.js +83 -0
  251. package/src/lib/api-routes/history.js +139 -0
  252. package/src/lib/api-routes/keycloak.js +54 -0
  253. package/src/lib/api-routes/longpolling.js +70 -0
  254. package/src/lib/api-routes/oauth2.js +149 -0
  255. package/src/lib/api-routes/objectstore.js +53 -0
  256. package/src/lib/api-routes/openapi.js +224 -0
  257. package/src/lib/api-routes/outbound.js +134 -0
  258. package/src/lib/api-routes/reports.js +72 -0
  259. package/src/lib/api-routes/rules.js +356 -0
  260. package/src/lib/api-routes/samples.js +92 -0
  261. package/src/lib/api-routes/server-logs.js +44 -0
  262. package/src/lib/api-routes/settings.js +71 -0
  263. package/src/lib/api-server.js +135 -0
  264. package/src/lib/arrayStore.js +101 -0
  265. package/src/lib/callbackHandler.js +201 -0
  266. package/src/lib/config.js +177 -0
  267. package/src/lib/configuration-providers/mb-connection-manager.js +625 -0
  268. package/src/lib/db/adapters/dbAdapter.js +184 -0
  269. package/src/lib/db/dfspMockUsers.js +64 -0
  270. package/src/lib/db/models/mongoDBWrapper.js +78 -0
  271. package/src/lib/eventListenerClient/inboundEventListener.js +176 -0
  272. package/src/lib/fileAdapter.js +57 -0
  273. package/src/lib/httpAgentStore.js +135 -0
  274. package/src/lib/importExport.js +186 -0
  275. package/src/lib/jws/JwsSigning.js +141 -0
  276. package/src/lib/loadSamples.js +128 -0
  277. package/src/lib/logger.js +20 -0
  278. package/src/lib/longpollingEmitter.js +56 -0
  279. package/src/lib/metrics.js +51 -0
  280. package/src/lib/mocking/custom-functions/generic.js +57 -0
  281. package/src/lib/mocking/middleware-functions/ilpModel.js +238 -0
  282. package/src/lib/mocking/middleware-functions/quotesAssociation.js +75 -0
  283. package/src/lib/mocking/middleware-functions/transactionRequestsService.js +78 -0
  284. package/src/lib/mocking/openApiDefinitionsModel.js +64 -0
  285. package/src/lib/mocking/openApiMockHandler.js +466 -0
  286. package/src/lib/mocking/openApiRulesEngine.js +492 -0
  287. package/src/lib/mocking/openApiVersionTools.js +136 -0
  288. package/src/lib/mocking/transformers/fspiopToISO20022.js +230 -0
  289. package/src/lib/mocking/transformers/index.js +41 -0
  290. package/src/lib/notificationEmitter.js +64 -0
  291. package/src/lib/oauth/KeycloakHelper.js +220 -0
  292. package/src/lib/oauth/LoginService.js +133 -0
  293. package/src/lib/oauth/OAuthHelper.js +181 -0
  294. package/src/lib/oauth/OAuthValidator.js +118 -0
  295. package/src/lib/oauth/Wso2Client.js +64 -0
  296. package/src/lib/objectStore/inMemoryImpl.js +50 -0
  297. package/src/lib/objectStore/objectStoreInterface.js +51 -0
  298. package/src/lib/objectStore.js +122 -0
  299. package/src/lib/report-generator/generator.js +126 -0
  300. package/src/lib/report-generator/helpers.js +154 -0
  301. package/src/lib/requestLogger.js +190 -0
  302. package/src/lib/resources/wso2carbon-publickey.cert +20 -0
  303. package/src/lib/rulesEngine.js +95 -0
  304. package/src/lib/rulesEngineModel.js +463 -0
  305. package/src/lib/scripting-engines/postman-sandbox.js +142 -0
  306. package/src/lib/scripting-engines/vm-javascript-sandbox.js +294 -0
  307. package/src/lib/server-logs/adapters/elastic-search.js +102 -0
  308. package/src/lib/server-logs/adapters/grafana.js +0 -0
  309. package/src/lib/server-logs/index.js +75 -0
  310. package/src/lib/socket-server.js +55 -0
  311. package/src/lib/storageAdapter.js +109 -0
  312. package/src/lib/test-outbound/TestCaseRunner.js +173 -0
  313. package/src/lib/test-outbound/getTracing.js +19 -0
  314. package/src/lib/test-outbound/outbound-initiator.js +1107 -0
  315. package/src/lib/uniqueIdGenerator.js +35 -0
  316. package/src/lib/utils.js +89 -0
  317. package/src/lib/utilsInternal.js +56 -0
  318. package/src/lib/webSocketClient/WebSocketClientManager.js +197 -0
  319. package/src/server.js +218 -0
@@ -0,0 +1,238 @@
1
+ /*****
2
+ License
3
+ --------------
4
+ Copyright © 2020-2025 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
+ * Mojaloop Foundation
23
+ - Name Surname <name.surname@mojaloop.io>
24
+
25
+ * ModusBox
26
+ * Vijaya Kumar Guthi <vijaya.guthi@modusbox.com> (Original Author)
27
+ --------------
28
+ ******/
29
+
30
+ const { ilpFactory, ILP_VERSIONS } = require('@mojaloop/sdk-standard-components').Ilp
31
+ const customLogger = require('../../requestLogger')
32
+ const { logger } = require('../../logger')
33
+
34
+ let ilpObj = null
35
+ let ilpV4Obj = null
36
+
37
+ const init = (secret) => {
38
+ ilpObj = ilpFactory(ILP_VERSIONS.v1, { secret, logger })
39
+ ilpV4Obj = ilpFactory(ILP_VERSIONS.v4, { secret, logger })
40
+ }
41
+
42
+ // ILP Packet inclusion functions
43
+ const handleQuoteIlp = (context, response) => {
44
+ // Check whether the request is POST /quotes
45
+ const pathMatch = /\/quotes\/([^/]+)$/
46
+ if (context.request.method === 'post' && response.method === 'put' && pathMatch.test(response.path)) {
47
+ if (response.eventInfo && response.eventInfo.params && response.eventInfo.params.body &&
48
+ (response.eventInfo.params.body.ilpPacket || response.eventInfo.params.body.condition)
49
+ ) {
50
+ return null
51
+ }
52
+ // const transactionObject = {
53
+ // mockData: 'This is a test data from self testing toolkit'
54
+ // }
55
+ let transactionObject
56
+ if (!_isIso20022(context.request)) {
57
+ transactionObject = {
58
+ transactionId: context.request.body.transactionId,
59
+ quoteId: context.request.body.quoteId,
60
+ payee: context.request.body.payee,
61
+ payer: context.request.body.payer,
62
+ amount: response.body.transferAmount,
63
+ transactionType: context.request.body.transactionType,
64
+ expiration: response.body.expiration,
65
+ note: response.body.note
66
+ }
67
+ } else {
68
+ const payeePartyIdType = context.request.body.CdtTrfTxInf.Cdtr.Id.OrgId?.Othr.Id ||
69
+ context.request.body.CdtTrfTxInf.Cdtr.Id.PrvtId?.Othr.Id
70
+ const payeePartyIdentifier = context.request.body.CdtTrfTxInf.Cdtr.Id.OrgId?.Othr.SchmeNm.Prtry ||
71
+ context.request.body.CdtTrfTxInf.Cdtr.Id.PrvtId?.Othr.SchmeNm.Prtry
72
+ const payerPartyIdType = context.request.body.CdtTrfTxInf.Dbtr.Id.OrgId?.Othr.Id ||
73
+ context.request.body.CdtTrfTxInf.Dbtr.Id.PrvtId?.Othr.Id
74
+ const payerPartyIdentifier = context.request.body.CdtTrfTxInf.Dbtr.Id.OrgId?.Othr.SchmeNm.Prtry ||
75
+ context.request.body.CdtTrfTxInf.Dbtr.Id.PrvtId?.Othr.SchmeNm.Prtry
76
+ transactionObject = {
77
+ transactionId: context.request.body.CdtTrfTxInf.PmtId.EndToEndId,
78
+ quoteId: context.request.body.CdtTrfTxInf.PmtId.TxId,
79
+ payee: {
80
+ partyIdInfo: {
81
+ partyIdType: payeePartyIdType,
82
+ partyIdentifier: payeePartyIdentifier,
83
+ fspId: context.request.body.CdtTrfTxInf.CdtrAgt.FinInstnId.Othr.Id
84
+ }
85
+ },
86
+ payer: {
87
+ partyIdInfo: {
88
+ partyIdType: payerPartyIdType,
89
+ partyIdentifier: payerPartyIdentifier,
90
+ fspId: context.request.body.CdtTrfTxInf.DbtrAgt.FinInstnId.Othr.Id
91
+ }
92
+ },
93
+ amount: {
94
+ currency: context.request.body.CdtTrfTxInf.IntrBkSttlmAmt.Ccy,
95
+ amount: context.request.body.CdtTrfTxInf.IntrBkSttlmAmt.ActiveCurrencyAndAmount
96
+ },
97
+ transactionType: context.request.body.GrpHdr?.CdtTrfTxInf?.Purp?.Prtry || null,
98
+ expiration: response.body.GrpHdr?.PmtInstrXpryDtTm,
99
+ note: context.request.body.CdtTrfTxInf?.InstrForNxtAgt?.InstrInf || null
100
+ }
101
+ }
102
+
103
+ let fulfilment
104
+ if (!_isIso20022(response)) {
105
+ const ilpResult = ilpObj.getResponseIlp(transactionObject)
106
+ fulfilment = ilpResult.fulfilment
107
+ response.body.ilpPacket = ilpResult.ilpPacket
108
+ response.body.condition = ilpResult.condition
109
+ } else {
110
+ const ilpResult = ilpV4Obj.getResponseIlp(transactionObject)
111
+ fulfilment = ilpResult.fulfilment
112
+ response.body.CdtTrfTxInf.VrfctnOfTerms = {
113
+ IlpV4PrepPacket: ilpResult.ilpPacket
114
+ }
115
+ }
116
+ return fulfilment
117
+ }
118
+ return null
119
+ }
120
+
121
+ const handleTransferIlp = (context, response) => {
122
+ // Check whether the request is POST /transfers
123
+ const pathMatch = /\/transfers\/([^/]+)$/
124
+ if (context.request.method === 'post' && response.method === 'put' && pathMatch.test(response.path)) {
125
+ if (
126
+ response.eventInfo && response.eventInfo.params && response.eventInfo.params.body &&
127
+ (
128
+ response.eventInfo.params.body.fulfilment ||
129
+ (response.eventInfo.params.body.TxInfAndSts && response.eventInfo.params.body.TxInfAndSts.ExctnConf)
130
+ )
131
+ ) {
132
+ return null
133
+ }
134
+ if (context.request.body.ilpPacket) {
135
+ const generatedFulfilment = ilpObj.calculateFulfil(context.request.body.ilpPacket).replace('"', '')
136
+ response.body.fulfilment = generatedFulfilment
137
+ }
138
+ if (context.request.body.CdtTrfTxInf?.VrfctnOfTerms?.IlpV4PrepPacket) {
139
+ const generatedFulfilment = ilpV4Obj.calculateFulfil(context.request.body.CdtTrfTxInf.VrfctnOfTerms.IlpV4PrepPacket).replace('"', '')
140
+ response.body.TxInfAndSts.ExctnConf = generatedFulfilment
141
+ }
142
+ }
143
+ if (context.request.method === 'get' && response.method === 'put' && pathMatch.test(response.path)) {
144
+ delete response.body.fulfilment
145
+ }
146
+ }
147
+
148
+ // Validation Functions
149
+
150
+ // Check the contents of ILP Packet against the values from body
151
+ const validateTransferIlpPacket = (context, request) => {
152
+ if (request.method === 'post' && request.path === '/transfers') {
153
+ customLogger.logMessage('info', 'Validating Ilp packet against the transfer request', { request })
154
+ try {
155
+ let validationBody
156
+ if (!_isIso20022(request)) {
157
+ validationBody = request.payload
158
+ return ilpObj.validateIlpAgainstTransferRequest(validationBody)
159
+ } else {
160
+ validationBody = {
161
+ payeeFsp: request.payload.CdtTrfTxInf.CdtrAgt.FinInstnId.Othr.Id,
162
+ payerFsp: request.payload.CdtTrfTxInf.DbtrAgt.FinInstnId.Othr.Id,
163
+ amount: {
164
+ currency: request.payload.CdtTrfTxInf.IntrBkSttlmAmt.Ccy,
165
+ amount: request.payload.CdtTrfTxInf.IntrBkSttlmAmt.ActiveCurrencyAndAmount
166
+ },
167
+ ilpPacket: request.payload.CdtTrfTxInf.VrfctnOfTerms.IlpV4PrepPacket
168
+ }
169
+ return ilpV4Obj.validateIlpAgainstTransferRequest(validationBody)
170
+ }
171
+ } catch (err) {
172
+ customLogger.logMessage('error', 'Failed to validate the Ilp packet. Error: ' + err.message, { request })
173
+ return false
174
+ }
175
+ }
176
+ return true
177
+ }
178
+
179
+ // Check the condition is matched with fulfilment stored
180
+ const validateTransferCondition = (context, request) => {
181
+ if (request.method === 'post' && request.path === '/transfers') {
182
+ let fulfilment = null
183
+ if (request.customInfo.storedTransaction && request.customInfo.storedTransaction.fulfilment) {
184
+ fulfilment = request.customInfo.storedTransaction.fulfilment
185
+ customLogger.logMessage('info', 'Validating condition with the stored fulfilment', { request })
186
+ } else {
187
+ try {
188
+ if (request.payload.ilpPacket) {
189
+ fulfilment = ilpObj.calculateFulfil(request.payload.ilpPacket).replace('"', '')
190
+ } else if (request.payload.CdtTrfTxInf) {
191
+ fulfilment = ilpV4Obj.calculateFulfil(request.payload.CdtTrfTxInf.VrfctnOfTerms.IlpV4PrepPacket).replace('"', '')
192
+ }
193
+ customLogger.logMessage('info', 'Validating condition with the generated fulfilment', { request })
194
+ } catch (err) {
195
+ customLogger.logMessage('error', 'Failed to calculate the fulfilment. Error: ' + err.message, { request })
196
+ return false
197
+ }
198
+ }
199
+ let condition
200
+ if (!_isIso20022(request)) {
201
+ condition = request.payload?.condition
202
+ } else {
203
+ // Construct the ILP object from the request payload
204
+ // since ISO20022 expect the condition in the ilpPacket
205
+ condition = ilpV4Obj.getResponseIlp(ilpV4Obj.getTransactionObject(request.payload.CdtTrfTxInf.VrfctnOfTerms.IlpV4PrepPacket)).condition
206
+ }
207
+ try {
208
+ if (!_isIso20022(request)) {
209
+ return ilpObj.validateFulfil(fulfilment, condition)
210
+ } else {
211
+ return ilpV4Obj.validateFulfil(fulfilment, condition)
212
+ }
213
+ } catch (err) {
214
+ customLogger.logMessage('error', 'Failed to validate the fulfilment. Error: ' + err.message, { request })
215
+ return false
216
+ }
217
+ }
218
+ return true
219
+ }
220
+
221
+ // Decoding functions
222
+
223
+ const getIlpTransactionObject = (ilpPacket, isIso20022) => {
224
+ return isIso20022 ? ilpV4Obj.getTransactionObject(ilpPacket) : ilpObj.getTransactionObject(ilpPacket)
225
+ }
226
+
227
+ const _isIso20022 = (requestOrResponse) => {
228
+ return requestOrResponse.body?.CdtTrfTxInf || requestOrResponse.payload?.CdtTrfTxInf
229
+ }
230
+
231
+ module.exports = {
232
+ init,
233
+ handleQuoteIlp,
234
+ handleTransferIlp,
235
+ validateTransferIlpPacket,
236
+ validateTransferCondition,
237
+ getIlpTransactionObject
238
+ }
@@ -0,0 +1,75 @@
1
+ /*****
2
+ License
3
+ --------------
4
+ Copyright © 2020-2025 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
+ * Mojaloop Foundation
23
+ - Name Surname <name.surname@mojaloop.io>
24
+
25
+ * ModusBox
26
+ * Vijaya Kumar Guthi <vijaya.guthi@modusbox.com> (Original Author)
27
+ --------------
28
+ ******/
29
+
30
+ const ObjectStore = require('../../objectStore')
31
+ const IlpModel = require('./ilpModel')
32
+
33
+ const handleQuotes = (context, request, fulfilment = null) => {
34
+ // Check whether the request is POST /quotes
35
+ if (request.method === 'post' && request.path === '/quotes') {
36
+ // Save the Transaction ID in object store
37
+ if (request.payload.CdtTrfTxInf?.PmtId?.EndToEndId) {
38
+ ObjectStore.push('transactions', request.payload.CdtTrfTxInf.PmtId.EndToEndId, { fulfilment })
39
+ }
40
+ if (request.payload.transactionId) {
41
+ ObjectStore.push('transactions', request.payload.transactionId, { fulfilment })
42
+ }
43
+ }
44
+ }
45
+
46
+ const handleTransfers = (context, request) => {
47
+ // Check whether the request is POST /transfers
48
+ if (request.method === 'post' && request.path === '/transfers') {
49
+ let ilpTransactionObject
50
+ try {
51
+ ilpTransactionObject = IlpModel.getIlpTransactionObject(
52
+ request.payload.ilpPacket ||
53
+ request.payload.CdtTrfTxInf?.VrfctnOfTerms?.IlpV4PrepPacket,
54
+ !!request.payload.CdtTrfTxInf?.VrfctnOfTerms?.IlpV4PrepPacket
55
+ )
56
+ } catch (err) {
57
+ return false
58
+ }
59
+ // Search for the Transaction ID in object store - delete it if found
60
+ const storedTransaction = ObjectStore.popObject('transactions', ilpTransactionObject.transactionId)
61
+ if (storedTransaction) {
62
+ request.customInfo.storedTransaction = storedTransaction
63
+ } else {
64
+ // Transaction not found, throw error callback
65
+ return false
66
+ }
67
+ }
68
+
69
+ return true
70
+ }
71
+
72
+ module.exports = {
73
+ handleQuotes,
74
+ handleTransfers
75
+ }
@@ -0,0 +1,78 @@
1
+ /*****
2
+ License
3
+ --------------
4
+ Copyright © 2020-2025 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
+ * Mojaloop Foundation
23
+ - Name Surname <name.surname@mojaloop.io>
24
+
25
+ * ModusBox
26
+ * Vijaya Kumar Guthi <vijaya.guthi@modusbox.com> (Original Author)
27
+ --------------
28
+ ******/
29
+
30
+ const fs = require('fs')
31
+ const { promisify } = require('util')
32
+ const readFileAsync = promisify(fs.readFile)
33
+ const outbound = require('../../test-outbound/outbound-initiator')
34
+ const { TraceHeaderUtils } = require('@mojaloop/ml-testing-toolkit-shared-lib')
35
+ const customLogger = require('../../requestLogger')
36
+
37
+ const handleRequest = async (context, request, callback, triggerFolder) => {
38
+ // Check whether the request is POST /transactionRequests
39
+ if (request.method === 'post' && request.path === '/transactionRequests') {
40
+ if (callback.body.transactionRequestState === 'RECEIVED') {
41
+ const transactionRequest = request.payload
42
+ try {
43
+ const contents = await readFileAsync(triggerFolder + '/transaction_request_followup.json')
44
+ const outboundTemplate = JSON.parse(contents)
45
+ // Replace the input values in the template with inbound transactionRequest params
46
+ outboundTemplate.inputValues.TrsNote = transactionRequest.note
47
+ outboundTemplate.inputValues.TrsCurrency = transactionRequest.amount.currency
48
+ outboundTemplate.inputValues.TrsAmount = transactionRequest.amount.amount
49
+ outboundTemplate.inputValues.TrsPayerIdType = transactionRequest.payer.partyIdType
50
+ outboundTemplate.inputValues.TrsPayerIdValue = transactionRequest.payer.partyIdentifier
51
+ outboundTemplate.inputValues.TrsPayerFspId = transactionRequest.payer.fspId
52
+ outboundTemplate.inputValues.TrsPayeeIdType = transactionRequest.payee.partyIdInfo.partyIdType
53
+ outboundTemplate.inputValues.TrsPayeeIdValue = transactionRequest.payee.partyIdInfo.partyIdentifier
54
+ outboundTemplate.inputValues.TrsPayeeFspId = transactionRequest.payee.partyIdInfo.fspId
55
+ outboundTemplate.inputValues.TrsScenario = transactionRequest.transactionType.scenario
56
+ outboundTemplate.inputValues.TrsInitiator = transactionRequest.transactionType.initiator
57
+ outboundTemplate.inputValues.TrsInitiatorType = transactionRequest.transactionType.initiatorType
58
+ outboundTemplate.inputValues.TrsTransactionRequestId = transactionRequest.transactionRequestId
59
+
60
+ // Replace the transaction ID from the generated callback
61
+ outboundTemplate.inputValues.transactionId = callback.body.transactionId
62
+ if (request.customInfo.sessionID) {
63
+ outbound.OutboundSend(outboundTemplate, TraceHeaderUtils.getTraceIdPrefix() + request.customInfo.sessionID + '0000', callback.fspId)
64
+ } else {
65
+ outbound.OutboundSend(outboundTemplate, null, callback.fspId)
66
+ }
67
+ } catch (err) {
68
+ customLogger.logMessage('error', err.message, err, { notification: false })
69
+ }
70
+ }
71
+ }
72
+
73
+ return true
74
+ }
75
+
76
+ module.exports = {
77
+ handleRequest
78
+ }
@@ -0,0 +1,64 @@
1
+ /*****
2
+ License
3
+ --------------
4
+ Copyright © 2020-2025 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
+ * Mojaloop Foundation
23
+ - Name Surname <name.surname@mojaloop.io>
24
+
25
+ * ModusBox
26
+ * Vijaya Kumar Guthi <vijaya.guthi@modusbox.com> (Original Author)
27
+ --------------
28
+ ******/
29
+
30
+ const Config = require('../config')
31
+ let apiDefinitions = null
32
+ const specFilePrefix = require('../utils').resolve('spec_files/api_definitions') + '/'
33
+
34
+ const getApiDefinitions = async () => {
35
+ if (!apiDefinitions) {
36
+ refreshApiDefinitions()
37
+ }
38
+ return apiDefinitions
39
+ }
40
+
41
+ const refreshApiDefinitions = async () => {
42
+ apiDefinitions = Config.getSystemConfig().API_DEFINITIONS.map(item => {
43
+ return {
44
+ minorVersion: +item.version.split('.')[1],
45
+ majorVersion: +item.version.split('.')[0],
46
+ type: item.type,
47
+ caption: item.caption,
48
+ asynchronous: item.asynchronous,
49
+ prefix: item.prefix,
50
+ hostnames: item.hostnames,
51
+ additionalApi: item.additionalApi,
52
+ specFile: specFilePrefix + item.folderPath + '/api_spec.yaml',
53
+ callbackMapFile: specFilePrefix + item.folderPath + '/callback_map.json',
54
+ responseMapFile: specFilePrefix + item.folderPath + '/response_map.json',
55
+ jsfRefFile: specFilePrefix + item.folderPath + '/mockRef.json',
56
+ triggerTemplatesFolder: specFilePrefix + item.folderPath + '/trigger_templates'
57
+ }
58
+ })
59
+ }
60
+
61
+ module.exports = {
62
+ getApiDefinitions,
63
+ refreshApiDefinitions
64
+ }