From 39352905e1b89ad42ee25dc2d3e163de409512e0 Mon Sep 17 00:00:00 2001 From: Kevin Leyow Date: Thu, 3 Sep 2020 22:45:28 -0500 Subject: [PATCH] refactor: update pisp/master (#781) * fix for python error in CI (#733) Co-authored-by: Shashi * Ensure 'timeout-reserved' notification action passes through and not converted to 'abort' action (#736) * Update CS shared (#737) * Feature/1332 enable on-us transfers (#738) * Added ENABLE_ON_US_TRANSFERS * Bumped up the version * Feature/otc 525 implement get transaction object by transfer (#735) * OTC-525 Implement GET transaction Object by transferId Changes: Updated swagger def to include new endpoints for: - Get transaction by transfer id - Post ledger entry Added new method for: - Get transaction by transfer id Added unit tests for Get transaction by transfer id * OTC-525 Implement GET transaction Object by transferId Bumput up versions * OTC-525 Implement GET transaction Object by transferId Resolved dependency updates * OTC-525 Implement GET transaction Object by transferId * OTC-525 Implement GET transaction Object by transferId Changes: Updated swagger def to include new endpoints for: - Get transaction by transfer id Added new method for: - Get transaction by transfer id Added unit tests for Get transaction by transfer id * changed docker dependency in circle CI image scan from python-dev to python3-dev (#741) * Updated python in some other places in circle CI (#742) * Fix the image scan step in circle CI * Resolved audit checks * Feature/#1335 aborted on put (#740) * added error log if action REJECT comes into fulfil handler Co-authored-by: Valentin * Bugfix/deadlock on adjust limits (#745) * added unique index on participantLimit and logging * added unique index on participantLimit and logging * resolve audit issues * fixed coverage tests Co-authored-by: Shashi * Updated dependencies and product version for issue: https://github.com/mojaloop/project/issues/1378 (#747) * Update error message (#749) * Update error message when Payer FSP and Payee FSP are the same and on-us is not enabled.. (Added text "FSP" to specify) * Updated unit test * #1423: Bulk transfers error processing in Central Ledger (#743) * Updates for bulk error processing * Bump version * Updates for bulk transfer error processing * Updates for bulk transfer error processing * More updates for bulk error processing * changes to cater for bulk_abort * updated central-services-shared * Updates for bulk error processing * Add unit test for BULK_ABORT branch in transfer fulfil handler * Add unit test for BULK_ABORT branch in transfer facade * Small fix for position handler test for BULK_ABORT branch Co-authored-by: Rajiv Mothilal * Bump version for release (#750) * Feature/#1334 patch request notif (#751) * added handling of request for notification by payee functionality * improved coverage and added missing action letter Co-authored-by: Valentin * Feature/1468 bulk quotes endpoints (#761) * version change * Added FSPIOP_CALLBACK_URL_BULK_QUOTES endpoint to seeds and updated population scripts and created one for local legacy simulator updated dependencies * updated dependencies to resolve audit issues * Feature/#1375: GET bulk transfer implementation (#760) * Add bulk get topic and handler * Implement GET bulk transfer logic * Restore default config * Add unit tests * Bump version * More bug fixes * Fix unit test * ensure error code is returned as string and not number for bulk get * Add bulk get to handlers list for cli startup (#765) * Reset package-lock.json to fix bug with version update for AJV (#766) * SemVar fix (#767) * Fix error callback for bulk transfers REJECTED scenario (#768) * Correct FSPIOP API version for admin API (#769) * #1547: Ignore "RESERVED" transferState from v1.0 clients on fulfill callback (#770) * Ignore RESERVE transferState from v1.0 clients on fulfil callback * Update package.json Co-authored-by: Sam <10507686+elnyry-sam-k@users.noreply.github.com> Co-authored-by: Sam <10507686+elnyry-sam-k@users.noreply.github.com> * Bump version to v111.1.2 to fix broken release (#771) * #1547: Fail transfer fulfill with "RESERVED" state and v1.0 content-type (#773) * Update dependencies * Bump version * Fix integration tests * #1547: Update dependencies (central-object-store etc.) (#774) * Update dependencies * Bump version * fix: package.json & package-lock.json to reduce vulnerabilities (#775) The following vulnerabilities are fixed with an upgrade: - https://snyk.io/vuln/SNYK-JS-LODASH-590103 * Fix bug in volumes of temp_curl service (#778) * Edited CI to build PISP docker image. (#734) * Edited CI to build PISP docker image. * Addressed comments. * Updated ci to python 3. (#744) * Update pisp/master (#755) * fix for python error in CI (#733) Co-authored-by: Shashi * Ensure 'timeout-reserved' notification action passes through and not converted to 'abort' action (#736) * Update CS shared (#737) * Feature/1332 enable on-us transfers (#738) * Added ENABLE_ON_US_TRANSFERS * Bumped up the version * Feature/otc 525 implement get transaction object by transfer (#735) * OTC-525 Implement GET transaction Object by transferId Changes: Updated swagger def to include new endpoints for: - Get transaction by transfer id - Post ledger entry Added new method for: - Get transaction by transfer id Added unit tests for Get transaction by transfer id * OTC-525 Implement GET transaction Object by transferId Bumput up versions * OTC-525 Implement GET transaction Object by transferId Resolved dependency updates * OTC-525 Implement GET transaction Object by transferId * OTC-525 Implement GET transaction Object by transferId Changes: Updated swagger def to include new endpoints for: - Get transaction by transfer id Added new method for: - Get transaction by transfer id Added unit tests for Get transaction by transfer id * changed docker dependency in circle CI image scan from python-dev to python3-dev (#741) * Updated python in some other places in circle CI (#742) * Fix the image scan step in circle CI * Resolved audit checks * Feature/#1335 aborted on put (#740) * added error log if action REJECT comes into fulfil handler Co-authored-by: Valentin * Bugfix/deadlock on adjust limits (#745) * added unique index on participantLimit and logging * added unique index on participantLimit and logging * resolve audit issues * fixed coverage tests Co-authored-by: Shashi * Updated dependencies and product version for issue: https://github.com/mojaloop/project/issues/1378 (#747) * Update error message (#749) * Update error message when Payer FSP and Payee FSP are the same and on-us is not enabled.. (Added text "FSP" to specify) * Updated unit test * #1423: Bulk transfers error processing in Central Ledger (#743) * Updates for bulk error processing * Bump version * Updates for bulk transfer error processing * Updates for bulk transfer error processing * More updates for bulk error processing * changes to cater for bulk_abort * updated central-services-shared * Updates for bulk error processing * Add unit test for BULK_ABORT branch in transfer fulfil handler * Add unit test for BULK_ABORT branch in transfer facade * Small fix for position handler test for BULK_ABORT branch Co-authored-by: Rajiv Mothilal * Bump version for release (#750) * Feature/#1334 patch request notif (#751) * added handling of request for notification by payee functionality * improved coverage and added missing action letter Co-authored-by: Valentin * chore(package): update contributors list & deps * chore: audit & deps update Co-authored-by: shashi165 <33355509+shashi165@users.noreply.github.com> Co-authored-by: Shashi Co-authored-by: Steven Oderayi Co-authored-by: vijayg10 <33152110+vijayg10@users.noreply.github.com> Co-authored-by: lazolalucas Co-authored-by: Valentin Genev Co-authored-by: Valentin Co-authored-by: Adrian Enns Co-authored-by: Sam <10507686+elnyry-sam-k@users.noreply.github.com> Co-authored-by: Rajiv Mothilal * chore: add thirdparty endpoints to database seeds (#779) * chore: add thirdparty endpoints to database seeds * chore: update dependencies for vulnerabilities * refactor: change name length to accomodate new endpoints * chore: sync package-lock * chore: remove migrations and shorten endpoint names * chore: fix find and replace error * chore: fix spelling * chore: update packages * chore: sync package-lock Co-authored-by: shashi165 <33355509+shashi165@users.noreply.github.com> Co-authored-by: Shashi Co-authored-by: Steven Oderayi Co-authored-by: vijayg10 <33152110+vijayg10@users.noreply.github.com> Co-authored-by: lazolalucas Co-authored-by: Valentin Genev Co-authored-by: Valentin Co-authored-by: Adrian Enns Co-authored-by: Sam <10507686+elnyry-sam-k@users.noreply.github.com> Co-authored-by: Rajiv Mothilal Co-authored-by: Snyk bot Co-authored-by: Ali Behnamfard Co-authored-by: eoln <2881004+eoln@users.noreply.github.com> --- .ncurc.json | 1 + audit-resolve.json | 166 -------- config/default.json | 23 + docker-compose.yml | 4 +- docker/central-ledger/default.json | 23 + package-lock.json | 186 ++++---- package.json | 10 +- seeds/endpointType.js | 4 + src/api/interface/swagger.json | 2 +- src/domain/bulkTransfer/index.js | 6 +- src/handlers/bulk/get/handler.js | 203 +++++++++ src/handlers/bulk/index.js | 3 + src/handlers/bulk/processing/handler.js | 33 +- src/handlers/bulk/shared/validator.js | 14 +- src/handlers/index.js | 9 + src/handlers/register.js | 3 +- src/handlers/transfers/handler.js | 12 + src/shared/setup.js | 4 + test/integration/handlers/handlers.test.js | 6 +- test/unit/handlers/bulk/get/handler.test.js | 401 ++++++++++++++++++ test/unit/handlers/transfers/handler.test.js | 22 +- test/util/scripts/populateTestData.sh | 10 + .../populateTestDataForLegacySimulator.sh | 261 ++++++++++++ 23 files changed, 1115 insertions(+), 291 deletions(-) create mode 100644 src/handlers/bulk/get/handler.js create mode 100644 test/unit/handlers/bulk/get/handler.test.js create mode 100755 test/util/scripts/populateTestDataForLegacySimulator.sh diff --git a/.ncurc.json b/.ncurc.json index eb3c8d246..4bee8b77e 100644 --- a/.ncurc.json +++ b/.ncurc.json @@ -1,5 +1,6 @@ { "reject": [ + "hapi-swagger", "tape", "ilp-packet" ] diff --git a/audit-resolve.json b/audit-resolve.json index c62f63680..e69de29bb 100644 --- a/audit-resolve.json +++ b/audit-resolve.json @@ -1,166 +0,0 @@ -{ - "decisions": { - "1523|@mojaloop/central-object-store>@mojaloop/central-services-logger>winston>async>lodash": { - "decision": "ignore", - "madeAt": 1594103543707, - "expiresAt": 1596695532690 - }, - "1523|@mojaloop/central-services-health>@mojaloop/central-services-logger>winston>async>lodash": { - "decision": "ignore", - "madeAt": 1594103543707, - "expiresAt": 1596695532690 - }, - "1523|@mojaloop/central-services-health>@mojaloop/central-services-shared>@mojaloop/central-services-logger>winston>async>lodash": { - "decision": "ignore", - "madeAt": 1594103543707, - "expiresAt": 1596695532690 - }, - "1523|@mojaloop/central-services-health>@mojaloop/central-services-shared>@mojaloop/event-sdk>@mojaloop/central-services-logger>winston>async>lodash": { - "decision": "ignore", - "madeAt": 1594103543707, - "expiresAt": 1596695532690 - }, - "1523|@mojaloop/central-services-shared>@mojaloop/event-sdk>@mojaloop/central-services-logger>winston>async>lodash": { - "decision": "ignore", - "madeAt": 1594103543707, - "expiresAt": 1596695532690 - }, - "1523|@mojaloop/event-sdk>@mojaloop/central-services-logger>winston>async>lodash": { - "decision": "ignore", - "madeAt": 1594103543707, - "expiresAt": 1596695532690 - }, - "1523|@mojaloop/central-services-logger>winston>async>lodash": { - "decision": "ignore", - "madeAt": 1594103543707, - "expiresAt": 1596695532690 - }, - "1523|@mojaloop/central-services-shared>@mojaloop/central-services-logger>winston>async>lodash": { - "decision": "ignore", - "madeAt": 1594103543707, - "expiresAt": 1596695532690 - }, - "1523|@mojaloop/central-services-health>@mojaloop/central-services-shared>@mojaloop/event-sdk>winston>async>lodash": { - "decision": "ignore", - "madeAt": 1594103543708, - "expiresAt": 1596695532690 - }, - "1523|@mojaloop/central-services-shared>@mojaloop/event-sdk>winston>async>lodash": { - "decision": "ignore", - "madeAt": 1594103543708, - "expiresAt": 1596695532690 - }, - "1523|@mojaloop/event-sdk>winston>async>lodash": { - "decision": "ignore", - "madeAt": 1594103543708, - "expiresAt": 1596695532690 - }, - "1523|@mojaloop/central-services-stream>@mojaloop/central-services-logger>winston>async>lodash": { - "decision": "ignore", - "madeAt": 1594103543708, - "expiresAt": 1596695532690 - }, - "1523|@mojaloop/forensic-logging-client>@mojaloop/central-services-logger>winston>async>lodash": { - "decision": "ignore", - "madeAt": 1594103543708, - "expiresAt": 1596695532690 - }, - "1523|@mojaloop/central-services-database>knex>lodash": { - "decision": "ignore", - "madeAt": 1594103543708, - "expiresAt": 1596695532690 - }, - "1523|@mojaloop/central-services-database>lodash": { - "decision": "ignore", - "madeAt": 1594103543708, - "expiresAt": 1596695532690 - }, - "1523|@mojaloop/central-services-error-handling>lodash": { - "decision": "ignore", - "madeAt": 1594103543708, - "expiresAt": 1596695532690 - }, - "1523|@mojaloop/central-services-health>@mojaloop/central-services-error-handling>lodash": { - "decision": "ignore", - "madeAt": 1594103543708, - "expiresAt": 1596695532690 - }, - "1523|@mojaloop/central-services-health>@mojaloop/central-services-shared>@mojaloop/central-services-error-handling>lodash": { - "decision": "ignore", - "madeAt": 1594103543708, - "expiresAt": 1596695532690 - }, - "1523|@mojaloop/central-services-shared>@mojaloop/central-services-error-handling>lodash": { - "decision": "ignore", - "madeAt": 1594103543708, - "expiresAt": 1596695532690 - }, - "1523|@mojaloop/central-services-health>@mojaloop/central-services-shared>@mojaloop/event-sdk>lodash": { - "decision": "ignore", - "madeAt": 1594103543708, - "expiresAt": 1596695532690 - }, - "1523|@mojaloop/central-services-shared>@mojaloop/event-sdk>lodash": { - "decision": "ignore", - "madeAt": 1594103543708, - "expiresAt": 1596695532690 - }, - "1523|@mojaloop/event-sdk>lodash": { - "decision": "ignore", - "madeAt": 1594103543708, - "expiresAt": 1596695532690 - }, - "1523|@mojaloop/central-services-health>@mojaloop/central-services-shared>lodash": { - "decision": "ignore", - "madeAt": 1594103543708, - "expiresAt": 1596695532690 - }, - "1523|@mojaloop/central-services-health>@mojaloop/central-services-shared>openapi-backend>lodash": { - "decision": "ignore", - "madeAt": 1594103543708, - "expiresAt": 1596695532690 - }, - "1523|@mojaloop/central-services-health>@mojaloop/central-services-shared>openapi-backend>mock-json-schema>lodash": { - "decision": "ignore", - "madeAt": 1594103543708, - "expiresAt": 1596695532690 - }, - "1523|@mojaloop/central-services-shared>openapi-backend>mock-json-schema>lodash": { - "decision": "ignore", - "madeAt": 1594103543708, - "expiresAt": 1596695532690 - }, - "1523|@mojaloop/central-services-shared>lodash": { - "decision": "ignore", - "madeAt": 1594103543708, - "expiresAt": 1596695532690 - }, - "1523|@mojaloop/central-services-shared>openapi-backend>lodash": { - "decision": "ignore", - "madeAt": 1594103543708, - "expiresAt": 1596695532690 - }, - "1523|@mojaloop/central-services-stream>@mojaloop/central-services-error-handling>@mojaloop/sdk-standard-components>request-promise-native>request-promise-core>lodash": { - "decision": "ignore", - "madeAt": 1594103543708, - "expiresAt": 1596695532690 - }, - "1523|@mojaloop/central-services-stream>@mojaloop/central-services-error-handling>lodash": { - "decision": "ignore", - "madeAt": 1594103543708, - "expiresAt": 1596695532690 - }, - "1523|knex>lodash": { - "decision": "ignore", - "madeAt": 1594103543708, - "expiresAt": 1596695532690 - }, - "1523|lodash": { - "decision": "ignore", - "madeAt": 1594103543708, - "expiresAt": 1596695532690 - } - }, - "rules": {}, - "version": 1 -} \ No newline at end of file diff --git a/config/default.json b/config/default.json index 7f502d3ad..52822273e 100644 --- a/config/default.json +++ b/config/default.json @@ -170,6 +170,29 @@ "auto.offset.reset": "earliest" } } + }, + "GET": { + "config": { + "options": { + "mode": 2, + "batchSize": 1, + "pollFrequency": 10, + "recursiveTimeout": 100, + "messageCharset": "utf8", + "messageAsJSON": true, + "sync": true, + "consumeTimeout": 1000 + }, + "rdkafkaConf": { + "client.id": "cl-con-bulk-get", + "group.id": "cl-group-bulk-get", + "metadata.broker.list": "localhost:9092", + "socket.keepalive.enable": true + }, + "topicConf": { + "auto.offset.reset": "earliest" + } + } } }, "TRANSFER": { diff --git a/docker-compose.yml b/docker-compose.yml index b313c5c15..5456a0b19 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -101,10 +101,10 @@ services: links: - mockserver volumes: - - ./docker/wait-for/wait-for-mockserver.sh:/opt/wait-for/wait-for-mockserver.sh + - ./docker/wait-for:/opt/wait-for entrypoint: [ "sh", "-c" ] command: - - /opt/wait-for-mockserver.sh + - /opt/wait-for/wait-for-mockserver.sh environment: [] networks: - cl-mojaloop-net diff --git a/docker/central-ledger/default.json b/docker/central-ledger/default.json index 0536ddb08..199a8b452 100644 --- a/docker/central-ledger/default.json +++ b/docker/central-ledger/default.json @@ -170,6 +170,29 @@ "auto.offset.reset": "earliest" } } + }, + "GET": { + "config": { + "options": { + "mode": 2, + "batchSize": 1, + "pollFrequency": 10, + "recursiveTimeout": 100, + "messageCharset": "utf8", + "messageAsJSON": true, + "sync": true, + "consumeTimeout": 1000 + }, + "rdkafkaConf": { + "client.id": "cl-con-bulk-get", + "group.id": "cl-group-bulk-get", + "metadata.broker.list": "localhost:29092", + "socket.keepalive.enable": true + }, + "topicConf": { + "auto.offset.reset": "earliest" + } + } } }, "TRANSFER": { diff --git a/package-lock.json b/package-lock.json index 6a5a017f6..b47b1c43e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@mojaloop/central-ledger", - "version": "10.5.2", + "version": "11.1.4", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -48,19 +48,19 @@ } }, "@babel/core": { - "version": "7.11.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.11.5.tgz", - "integrity": "sha512-fsEANVOcZHzrsV6dMVWqpSeXClq3lNbYrfFGme6DE25FQWe7pyeYpXyx9guqUnpy466JLzZ8z4uwSr2iv60V5Q==", + "version": "7.11.1", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.11.1.tgz", + "integrity": "sha512-XqF7F6FWQdKGGWAzGELL+aCO1p+lRY5Tj5/tbT3St1G8NaH70jhhDIKknIZaDans0OQBG5wRAldROLHSt44BgQ==", "dev": true, "requires": { "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.11.5", + "@babel/generator": "^7.11.0", "@babel/helper-module-transforms": "^7.11.0", "@babel/helpers": "^7.10.4", - "@babel/parser": "^7.11.5", + "@babel/parser": "^7.11.1", "@babel/template": "^7.10.4", - "@babel/traverse": "^7.11.5", - "@babel/types": "^7.11.5", + "@babel/traverse": "^7.11.0", + "@babel/types": "^7.11.0", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.1", @@ -68,7 +68,7 @@ "lodash": "^4.17.19", "resolve": "^1.3.2", "semver": "^5.4.1", - "source-map": "^0.6.1" + "source-map": "^0.5.0" }, "dependencies": { "debug": { @@ -79,32 +79,18 @@ "requires": { "ms": "^2.1.1" } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true } } }, "@babel/generator": { - "version": "7.11.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.5.tgz", - "integrity": "sha512-9UqHWJ4IwRTy4l0o8gq2ef8ws8UPzvtMkVKjTLAiRmza9p9V6Z+OfuNd9fB1j5Q67F+dVJtPC2sZXI8NM9br4g==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.0.tgz", + "integrity": "sha512-fEm3Uzw7Mc9Xi//qU20cBKatTfs2aOtKqmvy/Vm7RkJEGFQ4xc9myCfbXxqK//ZS8MR/ciOHw6meGASJuKmDfQ==", "dev": true, "requires": { - "@babel/types": "^7.11.5", + "@babel/types": "^7.11.0", "jsesc": "^2.5.1", - "source-map": "^0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } + "source-map": "^0.5.0" } }, "@babel/helper-function-name": { @@ -229,9 +215,9 @@ } }, "@babel/parser": { - "version": "7.11.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz", - "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==", + "version": "7.11.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.3.tgz", + "integrity": "sha512-REo8xv7+sDxkKvoxEywIdsNFiZLybwdI7hcT5uEPyQrSMB4YQ973BfC9OOrD/81MaIjh6UxdulIQXkjmiH3PcA==", "dev": true }, "@babel/template": { @@ -246,17 +232,17 @@ } }, "@babel/traverse": { - "version": "7.11.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.5.tgz", - "integrity": "sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.0.tgz", + "integrity": "sha512-ZB2V+LskoWKNpMq6E5UUCrjtDUh5IOTAyIl0dTjIEoXum/iKWkoIEKIRDnUucO6f+2FzNkE0oD4RLKoPIufDtg==", "dev": true, "requires": { "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.11.5", + "@babel/generator": "^7.11.0", "@babel/helper-function-name": "^7.10.4", "@babel/helper-split-export-declaration": "^7.11.0", - "@babel/parser": "^7.11.5", - "@babel/types": "^7.11.5", + "@babel/parser": "^7.11.0", + "@babel/types": "^7.11.0", "debug": "^4.1.0", "globals": "^11.1.0", "lodash": "^4.17.19" @@ -274,9 +260,9 @@ } }, "@babel/types": { - "version": "7.11.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", - "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz", + "integrity": "sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.10.4", @@ -555,9 +541,9 @@ } }, "@hapi/shot": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@hapi/shot/-/shot-5.0.3.tgz", - "integrity": "sha512-qbccs8KL4YSL9x0J/17Z6Udmtrrn32ieGbrCW8iivl2ha8YzlDy9Wvv1pFKh3mzbTsomWHGLF3UsKcQFk/BqPg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@hapi/shot/-/shot-5.0.1.tgz", + "integrity": "sha512-AnhIhB0UCBi8JpJ+BEkNs29FQGpp9yrFWDzPO/J9maS11VyDRh5cd1c6di6dX8IpYs/rUYr6uchXZ94OCo1ZDA==", "requires": { "@hapi/hoek": "9.x.x", "@hapi/validate": "1.x.x" @@ -937,9 +923,9 @@ } }, "@mojaloop/central-services-shared": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/@mojaloop/central-services-shared/-/central-services-shared-11.2.0.tgz", - "integrity": "sha512-0x52CrQurhV1kX7ODT8WR8j1JwlGyvNZh9EPL7gSSAxRqNDlJym6rOloLKdoWkyD1BttFDRudKtZgKAhiBcR2w==", + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/@mojaloop/central-services-shared/-/central-services-shared-11.3.0.tgz", + "integrity": "sha512-DkZYoCe3Kla6JW2KoR+14Jt0f2uBQSoci3jCnMHZPol0z8MfOzfwoai9FEX2VETEpuDzD/zL1grQecrMFjIHvg==", "requires": { "@hapi/catbox": "11.1.1", "@hapi/catbox-memory": "5.0.0", @@ -953,10 +939,13 @@ "base64url": "3.0.1", "clone": "2.1.2", "data-urls": "2.0.0", + "dotenv": "8.2.0", + "env-var": "6.3.0", "immutable": "3.8.2", "lodash": "4.17.20", "mustache": "4.0.1", "openapi-backend": "3.5.2", + "parse-strings-in-object": "1.3.2", "raw-body": "2.4.1", "uuid4": "2.0.2" }, @@ -1005,6 +994,11 @@ "qs": "^6.9.3", "swagger-parser": "^9.0.1" } + }, + "parse-strings-in-object": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parse-strings-in-object/-/parse-strings-in-object-1.3.2.tgz", + "integrity": "sha512-3teTMOr3r9W8+Pu11XhCRIu3MUyfqVFW8il4wCRH8bd0MVh/2ssf0rRiQXk6YpFVfDdtm22JQPTRdNOAZvOeQw==" } } }, @@ -1186,9 +1180,9 @@ "dev": true }, "@npmcli/git": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-2.0.3.tgz", - "integrity": "sha512-c/ODsV5ppjB12VDXKc6hzVNgg6ZJX/etILUn3WgF5NLAYBhQLJ3fBq6uB2jQD4OwqOzJdPT1/xA3Xh3aaWGk5w==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-2.0.4.tgz", + "integrity": "sha512-OJZCmJ9DNn1cz9HPXXsPmUBnqaArot3CGYo63CyajHQk+g87rPXVOJByGsskQJhPsUUEXJcsZ2Q6bWd2jSwnBA==", "dev": true, "requires": { "@npmcli/promise-spawn": "^1.1.0", @@ -1481,9 +1475,9 @@ } }, "aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.0.1.tgz", + "integrity": "sha512-quoaXsZ9/BLNae5yiNoUz+Nhkwz83GhWwtYFglcjEQB2NDHCIpApbqXxIFnm4Pq/Nvhrsq5sYJFyohrrxnTGAA==", "dev": true, "requires": { "clean-stack": "^2.0.0", @@ -2500,9 +2494,9 @@ "dev": true }, "cli-boxes": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", - "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.0.tgz", + "integrity": "sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w==", "dev": true }, "cli-cursor": { @@ -3069,6 +3063,11 @@ "is-obj": "^2.0.0" } }, + "dotenv": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", + "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==" + }, "dotignore": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/dotignore/-/dotignore-0.1.2.tgz", @@ -3198,6 +3197,11 @@ "integrity": "sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA==", "dev": true }, + "env-var": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/env-var/-/env-var-6.3.0.tgz", + "integrity": "sha512-gaNzDZuVaJQJlP2SigAZLu/FieZN5MzdN7lgHNehESwlRanHwGQ/WUtJ7q//dhrj3aGBZM45yEaKOuvSJaf4mA==" + }, "env-variable": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/env-variable/-/env-variable-0.0.6.tgz", @@ -3726,20 +3730,12 @@ } }, "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", "dev": true, "requires": { - "estraverse": "^5.2.0" - }, - "dependencies": { - "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true - } + "estraverse": "^4.1.0" } }, "estraverse": { @@ -4644,9 +4640,9 @@ } }, "hapi-swagger": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/hapi-swagger/-/hapi-swagger-14.0.0.tgz", - "integrity": "sha512-ppMlFdUK8g3IMlre2Fd932ngnB6bBNzSLPFzjvbFBiC6i7sJvvvqWA2FdYDW/u3on9JvziikQFxTj/9zxvE/+A==", + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/hapi-swagger/-/hapi-swagger-13.1.0.tgz", + "integrity": "sha512-WzhMk4BcaC36poqLpBGITGiyytGjVYXqwU3DdECJGKZ5AVfAqaJuhlWQg5MkmZ0Be1JglUzOYPTPSvqqN9XHBw==", "requires": { "@hapi/boom": "^9.1.0", "@hapi/hoek": "^9.0.2", @@ -5709,9 +5705,9 @@ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" }, "json-parse-even-better-errors": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.0.tgz", - "integrity": "sha512-o3aP+RsWDJZayj1SbHNQAI8x0v3T3SKiGoZlNYfbUP1S3omJQ6i9CnqADqkSPaOAxwua4/1YWx5CM7oiChJt2Q==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true }, "json-parse-helpfulerror": { @@ -6955,9 +6951,9 @@ } }, "npm-check-updates": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-8.0.2.tgz", - "integrity": "sha512-YsJSmVPXWzBRSbzuVkMRV4M7tNtR3ptMQh0ZYzE3QXdZ8pxAYqrfvE8bJeZYcdsSBSRIJ6TZTmF6uS4rP/xaVQ==", + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-8.0.5.tgz", + "integrity": "sha512-EZ3DIFvKFNZzwV9OdEYITTAY6fmuD7evItEmf9XyntG4p29n8JpFaGrf9uCQIR0Hx3G5RFNsdCeURHzF6YXIAw==", "dev": true, "requires": { "chalk": "^4.1.0", @@ -9540,9 +9536,9 @@ "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" }, "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", "requires": { "has-flag": "^4.0.0" } @@ -9566,9 +9562,9 @@ "integrity": "sha1-cAcEaNbSl3ylI3suUZyn0Gouo/0=" }, "swagger-ui-dist": { - "version": "3.32.5", - "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-3.32.5.tgz", - "integrity": "sha512-3SKHv8UVqsKKknivtACHbFDGcn297jkoZN2h6zAZ7b2yoaJNMaRadQpC3qFw3GobZTGzqHCgHph4ZH9NkaCjrQ==" + "version": "3.32.1", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-3.32.1.tgz", + "integrity": "sha512-CaIKxDo91McgoesukS5v3nwQ8iur0MQmwNvJ+bPeyd8sOtoiNyXp55ZjO4pXewBdFHD0f9PvGovf2m5x/1typA==" }, "table": { "version": "5.4.6", @@ -10089,9 +10085,9 @@ "dev": true }, "uglify-js": { - "version": "3.10.3", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.10.3.tgz", - "integrity": "sha512-Lh00i69Uf6G74mvYpHCI9KVVXLcHW/xu79YTvH7Mkc9zyKUeSPz0owW0dguj0Scavns3ZOh3wY63J0Zb97Za2g==", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.10.1.tgz", + "integrity": "sha512-RjxApKkrPJB6kjJxQS3iZlf///REXWYxYJxO/MpmlQzVkDWVI3PSnCBWezMecmTU/TRkNxrl8bmsfFQCp+LO+Q==", "optional": true }, "unc-path-regex": { @@ -10275,9 +10271,9 @@ } }, "uri-js": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", - "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", "requires": { "punycode": "^2.1.0" } @@ -10374,9 +10370,9 @@ } }, "webidl-conversions": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", - "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==" + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", + "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==" }, "whatwg-mimetype": { "version": "2.3.0", @@ -10384,13 +10380,13 @@ "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==" }, "whatwg-url": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.2.1.tgz", - "integrity": "sha512-ZmVCr6nfBeaMxEHALLEGy0LszYjpJqf6PVNQUQ1qd9Et+q7Jpygd4rGGDXgHjD8e99yLFseD69msHDM4YwPZ4A==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.1.0.tgz", + "integrity": "sha512-vEIkwNi9Hqt4TV9RdnaBPNt+E2Sgmo3gePebCRgZ1R7g6d23+53zCTnuB0amKI4AXq6VM8jj2DUAa0S1vjJxkw==", "requires": { "lodash.sortby": "^4.7.0", "tr46": "^2.0.2", - "webidl-conversions": "^6.1.0" + "webidl-conversions": "^5.0.0" } }, "which": { diff --git a/package.json b/package.json index a5ab0659d..35013effc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@mojaloop/central-ledger", - "version": "10.5.2", + "version": "11.1.4", "description": "Central ledger hosted by a scheme to record and settle transfers", "license": "Apache-2.0", "author": "ModusBox", @@ -80,7 +80,7 @@ "@hapi/good": "9.0.0", "@hapi/hapi": "20.0.0", "@hapi/inert": "6.0.2", - "@hapi/joi": "^17.1.1", + "@hapi/joi": "17.1.1", "@hapi/vision": "6.0.1", "@mojaloop/central-object-store": "11.0.0-snapshot", "@mojaloop/central-services-database": "10.6.0", @@ -88,7 +88,7 @@ "@mojaloop/central-services-health": "10.6.0", "@mojaloop/central-services-logger": "10.6.0", "@mojaloop/central-services-metrics": "9.5.0", - "@mojaloop/central-services-shared": "11.2.0", + "@mojaloop/central-services-shared": "11.3.0", "@mojaloop/central-services-stream": "10.6.0", "@mojaloop/event-sdk": "10.6.0", "@mojaloop/forensic-logging-client": "8.3.0", @@ -106,7 +106,7 @@ "glob": "7.1.6", "hapi-auth-basic": "5.0.0", "hapi-auth-bearer-token": "6.2.1", - "hapi-swagger": "14.0.0", + "hapi-swagger": "13.1.0", "ilp-packet": "2.2.0", "joi": "^17.2.1", "knex": "0.21.5", @@ -129,7 +129,7 @@ "jsonpath": "1.0.2", "nodemon": "2.0.4", "npm-audit-resolver": "2.2.1", - "npm-check-updates": "8.0.2", + "npm-check-updates": "8.0.5", "nyc": "15.1.0", "pre-commit": "1.2.2", "proxyquire": "2.1.3", diff --git a/seeds/endpointType.js b/seeds/endpointType.js index 6c49ee401..ceb79bce6 100644 --- a/seeds/endpointType.js +++ b/seeds/endpointType.js @@ -138,6 +138,10 @@ const endpointTypes = [ name: 'FSPIOP_CALLBACK_URL_TRX_REQ_SERVICE', description: 'Participant callback URL to which transaction requests can be sent' }, + { + name: 'FSPIOP_CALLBACK_URL_BULK_QUOTES', + description: 'Bulk Quotes callback URL to which put bulkQuotes requests can be sent' + }, { name: 'TP_CB_URL_TRANSACTION_REQUEST_POST', description: 'Participant callback URL where POST /thirdpartyRequests/transactions can be sent' diff --git a/src/api/interface/swagger.json b/src/api/interface/swagger.json index 88e82a4b4..85e772b67 100644 --- a/src/api/interface/swagger.json +++ b/src/api/interface/swagger.json @@ -7,7 +7,7 @@ ], "info": { "title": "Central Ledger API Documentation", - "version": "10.3.0" + "version": "1.0" }, "tags": [], "paths": { diff --git a/src/domain/bulkTransfer/index.js b/src/domain/bulkTransfer/index.js index cf713e3d7..d1a17c641 100644 --- a/src/domain/bulkTransfer/index.js +++ b/src/domain/bulkTransfer/index.js @@ -24,7 +24,7 @@ 'use strict' /** - * @module src/domain/transfer/ + * @module src/domain/bulkTransfer/ */ const Enum = require('@mojaloop/central-services-shared').Enum @@ -54,7 +54,7 @@ const getBulkTransferById = async (id) => { } if (transfer.errorCode) { result.errorInformation = { - errorCode: transfer.errorCode, + errorCode: transfer.errorCode.toString(), errorDescription: transfer.errorDescription } } else { @@ -124,7 +124,7 @@ const getBulkTransferById = async (id) => { payerFsp: bulkTransfer.payerFsp, payeeFsp: bulkTransfer.payeeFsp, expiration: bulkTransfer.expirationDate, - completedDate: bulkTransfer.completedDate, + completedDate: bulkTransfer.completedTimestamp, payerBulkTransfer, payeeBulkTransfer } diff --git a/src/handlers/bulk/get/handler.js b/src/handlers/bulk/get/handler.js new file mode 100644 index 000000000..efae773a8 --- /dev/null +++ b/src/handlers/bulk/get/handler.js @@ -0,0 +1,203 @@ +/***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + 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 + + http://www.apache.org/licenses/LICENSE-2.0 + + 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. + + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + + * Gates Foundation + - Name Surname + + * ModusBox + - Steven Oderayi + -------------- + ******/ +'use strict' + +const Logger = require('@mojaloop/central-services-logger') +const EventSdk = require('@mojaloop/event-sdk') +const Util = require('@mojaloop/central-services-shared').Util +const Kafka = require('@mojaloop/central-services-shared').Util.Kafka +const Producer = require('@mojaloop/central-services-stream').Util.Producer +const Consumer = require('@mojaloop/central-services-stream').Util.Consumer +const Enum = require('@mojaloop/central-services-shared').Enum +const Metrics = require('@mojaloop/central-services-metrics') +const ErrorHandler = require('@mojaloop/central-services-error-handling') +const BulkTransferService = require('../../../domain/bulkTransfer') +const BulkTransferModel = require('../../../models/bulkTransfer/bulkTransfer') +const Validator = require('../shared/validator') +const Config = require('../../../lib/config') +const { ERROR_HANDLING } = require('../../../lib/config') + +const location = { module: 'BulkGetHandler', method: '', path: '' } +const consumerCommit = true +const fromSwitch = true + +/** + * @function BulkGetHandler + * + * @async + * @description Gets a bulk transfer by id. Gets Kafka config from default.json + * + * Calls createHandler to register the handler against the Stream Processing API. + * + * @param {error} error - error thrown if something fails within Kafka + * @param {array} messages - a list of messages to consume for the relevant topic + * + * @returns {object} - Returns a boolean: true if successful, or throws an error if failed + */ +const getBulkTransfer = async (error, messages) => { + const histTimerEnd = Metrics.getHistogram( + 'bulk_transfer_get', + 'Consume a get bulk transfer message from the kafka topic and process it accordingly', + ['success', 'fspId'] + ).startTimer() + if (error) { + throw ErrorHandler.Factory.reformatFSPIOPError(error) + } + const message = Array.isArray(messages) ? messages[0] : messages + const contextFromMessage = EventSdk.Tracer.extractContextFromMessage(message.value) + const span = EventSdk.Tracer.createChildSpanFromContext('cl_bulk_transfer_get', contextFromMessage) + try { + await span.audit(message, EventSdk.AuditEventAction.start) + const metadata = message.value.metadata + const action = metadata.event.action + const bulkTransferId = message.value.content.uriParams.id + const kafkaTopic = message.topic + Logger.isInfoEnabled && Logger.info(Util.breadcrumb(location, { method: `getBulkTransfer:${action}` })) + + const actionLetter = Enum.Events.ActionLetter.get + const params = { message, kafkaTopic, span, consumer: Consumer, producer: Producer } + const eventDetail = { functionality: Enum.Events.Event.Type.NOTIFICATION, action: Enum.Events.Event.Action.BULK_GET } + + Util.breadcrumb(location, { path: 'validationFailed' }) + + if (!(await Validator.validateParticipantByName(message.value.from)).isValid) { + Logger.isInfoEnabled && Logger.info(Util.breadcrumb(location, `breakParticipantDoesntExist--${actionLetter}1`)) + await Kafka.proceed(Config.KAFKA_CONFIG, params, { consumerCommit, histTimerEnd }) + histTimerEnd({ success: true, fspId: Config.INSTRUMENTATION_METRICS_LABELS.fspId }) + return true + } + // TODO: Validate this. Is this sufficient for checking existence of bulk transfer? + const bulkTransferLight = await BulkTransferModel.getById(bulkTransferId) + if (!bulkTransferLight) { + Logger.isInfoEnabled && Logger.info(Util.breadcrumb(location, `callbackErrorBulkTransferNotFound--${actionLetter}3`)) + const fspiopError = ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.BULK_TRANSFER_ID_NOT_FOUND, 'Provided Bulk Transfer ID was not found on the server.') + await Kafka.proceed(Config.KAFKA_CONFIG, params, { consumerCommit, fspiopError: fspiopError.toApiErrorObject(Config.ERROR_HANDLING), eventDetail, fromSwitch }) + throw fspiopError + } + // The SD says this should be 404 response which I think will not be constent with single transfers + // which responds with CLIENT_ERROR instead + const participants = await BulkTransferService.getParticipantsById(bulkTransferId) + if (![participants.payeeFsp, participants.payerFsp].includes(message.value.from)) { + Logger.isInfoEnabled && Logger.info(Util.breadcrumb(location, `callbackErrorNotBulkTransferParticipant--${actionLetter}2`)) + const fspiopError = ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.CLIENT_ERROR) + await Kafka.proceed(Config.KAFKA_CONFIG, params, { consumerCommit, fspiopError: fspiopError.toApiErrorObject(Config.ERROR_HANDLING), eventDetail, fromSwitch }) + throw fspiopError + } + const isPayeeRequest = participants.payeeFsp === message.value.from + Util.breadcrumb(location, { path: 'validationPassed' }) + Logger.isInfoEnabled && Logger.info(Util.breadcrumb(location, `callbackMessage--${actionLetter}4`)) + const bulkTransferResult = await BulkTransferService.getBulkTransferById(bulkTransferId) + const bulkTransfer = isPayeeRequest ? bulkTransferResult.payeeBulkTransfer : bulkTransferResult.payerBulkTransfer + let payload = { + bulkTransferState: bulkTransfer.bulkTransferState + } + let fspiopError + if (bulkTransfer.bulkTransferState === Enum.Transfers.BulkTransferState.REJECTED) { + payload = { + errorInformation: bulkTransfer.individualTransferResults[0].errorInformation + } + fspiopError = ErrorHandler.Factory.createFSPIOPErrorFromErrorInformation(payload.errorInformation) + } else if (bulkTransfer.bulkTransferState !== Enum.Transfers.BulkTransferState.PROCESSING) { + payload = { + ...payload, + completedTimestamp: bulkTransfer.completedTimestamp, + individualTransferResults: bulkTransfer.individualTransferResults, + extensionList: bulkTransfer.extensionList + } + } + message.value.content.payload = payload + if (fspiopError) { + await Kafka.proceed(Config.KAFKA_CONFIG, params, { consumerCommit, fspiopError: fspiopError.toApiErrorObject(ERROR_HANDLING), eventDetail, fromSwitch }) + } else { + await Kafka.proceed(Config.KAFKA_CONFIG, params, { consumerCommit, eventDetail, fromSwitch }) + } + histTimerEnd({ success: true, fspId: Config.INSTRUMENTATION_METRICS_LABELS.fspId }) + return true + } catch (err) { + histTimerEnd({ success: false, fspId: Config.INSTRUMENTATION_METRICS_LABELS.fspId }) + const fspiopError = ErrorHandler.Factory.reformatFSPIOPError(err) + Logger.isErrorEnabled && Logger.error(`${Util.breadcrumb(location)}::${err.message}--G0`) + const state = new EventSdk.EventStateMetadata(EventSdk.EventStatusType.failed, fspiopError.apiErrorCode.code, fspiopError.apiErrorCode.message) + await span.error(fspiopError, state) + await span.finish(fspiopError.message, state) + return true + } finally { + if (!span.isFinished) { + await span.finish() + } + } +} + +/** + * @function registerBulkFulfilHandler + * + * @async + * @description Registers the handler for bulk-transfer topic. Gets Kafka config from default.json + * + * @returns {boolean} - Returns a boolean: true if successful, or throws and error if failed + */ +const registerGetBulkTransferHandler = async () => { + try { + const bulkGetHandler = { + command: getBulkTransfer, + topicName: Kafka.transformGeneralTopicName(Config.KAFKA_CONFIG.TOPIC_TEMPLATES.GENERAL_TOPIC_TEMPLATE.TEMPLATE, Enum.Events.Event.Type.BULK, Enum.Events.Event.Action.GET), + config: Kafka.getKafkaConfig(Config.KAFKA_CONFIG, Enum.Kafka.Config.CONSUMER, Enum.Events.Event.Type.BULK.toUpperCase(), Enum.Events.Event.Action.GET.toUpperCase()) + } + bulkGetHandler.config.rdkafkaConf['client.id'] = bulkGetHandler.topicName + await Consumer.createHandler(bulkGetHandler.topicName, bulkGetHandler.config, bulkGetHandler.command) + return true + } catch (err) { + Logger.isErrorEnabled && Logger.error(err) + throw ErrorHandler.Factory.reformatFSPIOPError(err) + } +} + +/** + * @function RegisterAllHandlers + * + * @async + * @description Registers all module handlers + * + * @returns {boolean} - Returns a boolean: true if successful, or throws and error if failed + */ +const registerAllHandlers = async () => { + try { + await registerGetBulkTransferHandler() + return true + } catch (err) { + Logger.isErrorEnabled && Logger.error(err) + throw ErrorHandler.Factory.reformatFSPIOPError(err) + } +} + +module.exports = { + getBulkTransfer, + registerGetBulkTransferHandler, + registerAllHandlers +} diff --git a/src/handlers/bulk/index.js b/src/handlers/bulk/index.js index f8d28a3e8..6f129ceb0 100644 --- a/src/handlers/bulk/index.js +++ b/src/handlers/bulk/index.js @@ -34,6 +34,7 @@ const BulkPrepareHandlers = require('./prepare/handler') const BulkFulfilHandlers = require('./fulfil/handler') const BulkProcessingHandlers = require('./processing/handler') +const GetBulkTransferHandlers = require('./get/handler') const Logger = require('@mojaloop/central-services-logger') /** @@ -49,6 +50,7 @@ const registerAllHandlers = async () => { await BulkPrepareHandlers.registerAllHandlers() await BulkFulfilHandlers.registerAllHandlers() await BulkProcessingHandlers.registerAllHandlers() + await GetBulkTransferHandlers.registerAllHandlers() return true } catch (err) { Logger.isErrorEnabled && Logger.error(err) @@ -60,5 +62,6 @@ module.exports = { registerBulkPrepareHandler: BulkPrepareHandlers.registerBulkPrepareHandler, registerBulkFulfilHandler: BulkFulfilHandlers.registerBulkFulfilHandler, registerBulkProcessingHandler: BulkProcessingHandlers.registerBulkProcessingHandler, + registerGetBulkTransferHandler: GetBulkTransferHandlers.registerGetBulkTransferHandler, registerAllHandlers } diff --git a/src/handlers/bulk/processing/handler.js b/src/handlers/bulk/processing/handler.js index 80542d550..feffbe750 100644 --- a/src/handlers/bulk/processing/handler.js +++ b/src/handlers/bulk/processing/handler.js @@ -300,21 +300,30 @@ const bulkProcessing = async (error, messages) => { await (new BulkTransferResultModel(payeeBulkResponse)).save() const payerParams = Util.clone(params) const payeeParams = Util.clone(params) + let payerPayload + let payeePayload + + if (action === Enum.Events.Event.Action.BULK_ABORT && params.decodedPayload.errorInformation) { + payerPayload = { bulkTransferId: payerBulkResponse.bulkTransferId, errorInformation: params.decodedPayload.errorInformation } + payeePayload = { bulkTransferId: payeeBulkResponse.bulkTransferId, errorInformation: params.decodedPayload.errorInformation } + } else { + payerPayload = Util.omitNil({ + bulkTransferId: payerBulkResponse.bulkTransferId, + bulkTransferState: payerBulkResponse.bulkTransferState, + completedTimestamp: payerBulkResponse.completedTimestamp, + extensionList: payerBulkResponse.extensionList + }) + payeePayload = Util.omitNil({ + bulkTransferId: payeeBulkResponse.bulkTransferId, + bulkTransferState: payeeBulkResponse.bulkTransferState, + completedTimestamp: payeeBulkResponse.completedTimestamp, + extensionList: payeeBulkResponse.extensionList + }) + } - const payerPayload = Util.omitNil({ - bulkTransferId: payerBulkResponse.bulkTransferId, - bulkTransferState: payerBulkResponse.bulkTransferState, - completedTimestamp: payerBulkResponse.completedTimestamp, - extensionList: payerBulkResponse.extensionList - }) const payerMetadata = Util.StreamingProtocol.createMetadataWithCorrelatedEvent(params.message.value.metadata.event.id, payerParams.message.value.metadata.type, payerParams.message.value.metadata.action, Enum.Events.EventStatus.SUCCESS) payerParams.message.value = Util.StreamingProtocol.createMessage(params.message.value.id, participants.payerFsp, payerBulkResponse.headers[normalizedKeys[Enum.Http.Headers.FSPIOP.SOURCE]], payerMetadata, payerBulkResponse.headers, payerPayload) - const payeePayload = Util.omitNil({ - bulkTransferId: payeeBulkResponse.bulkTransferId, - bulkTransferState: payeeBulkResponse.bulkTransferState, - completedTimestamp: payeeBulkResponse.completedTimestamp, - extensionList: payeeBulkResponse.extensionList - }) + const payeeMetadata = Util.StreamingProtocol.createMetadataWithCorrelatedEvent(params.message.value.metadata.event.id, payeeParams.message.value.metadata.type, payeeParams.message.value.metadata.action, Enum.Events.EventStatus.SUCCESS) payeeParams.message.value = Util.StreamingProtocol.createMessage(params.message.value.id, participants.payeeFsp, Enum.Http.Headers.FSPIOP.SWITCH.value, payeeMetadata, payeeBulkResponse.headers, payeePayload) if ([Enum.Events.Event.Action.BULK_TIMEOUT_RECEIVED, Enum.Events.Event.Action.BULK_TIMEOUT_RESERVED].includes(action)) { diff --git a/src/handlers/bulk/shared/validator.js b/src/handlers/bulk/shared/validator.js index e784dd64a..6b55a049e 100644 --- a/src/handlers/bulk/shared/validator.js +++ b/src/handlers/bulk/shared/validator.js @@ -25,6 +25,7 @@ * ModusBox - Georgi Georgiev - Rajiv Mothilal + - Steven Oderayi -------------- ******/ 'use strict' @@ -130,7 +131,18 @@ const validateBulkTransferFulfilment = async (payload, headers) => { return { isValid, reasons } } +const validateParticipantBulkTransferId = async function (participantName, bulkTransferId) { + const bulkTransferParticipant = await BulkTransferService.getBulkTransferParticipant(participantName, bulkTransferId) + let validationPassed = false + if (Array.isArray(bulkTransferParticipant) && bulkTransferParticipant.length > 0) { + validationPassed = true + } + return validationPassed +} + module.exports = { validateBulkTransfer, - validateBulkTransferFulfilment + validateBulkTransferFulfilment, + validateParticipantByName, + validateParticipantBulkTransferId } diff --git a/src/handlers/index.js b/src/handlers/index.js index 2d3d547d5..b1b281730 100644 --- a/src/handlers/index.js +++ b/src/handlers/index.js @@ -59,6 +59,7 @@ Program.command('handler') // sub-command name, coffeeType = type, required .option('--bulkprepare', 'Start the Bulk Prepare Handler') .option('--bulkfulfil', 'Start the Bulk Fulfil Handler') .option('--bulkprocessing', 'Start the Bulk Processing Handler') + .option('--bulkget', 'Start the Bulk Get Handler') // .option('--reject', 'Start the Reject Handler') // function to execute when command is uses @@ -136,6 +137,14 @@ Program.command('handler') // sub-command name, coffeeType = type, required } handlerList.push(handler) } + if (args.bulkget) { + Logger.isDebugEnabled && Logger.debug('CLI: Executing --bulkget') + const handler = { + type: 'bulkget', + enabled: true + } + handlerList.push(handler) + } module.exports = Setup.initialize({ service: 'handler', diff --git a/src/handlers/register.js b/src/handlers/register.js index d1d29a723..e4415e01a 100644 --- a/src/handlers/register.js +++ b/src/handlers/register.js @@ -101,6 +101,7 @@ module.exports = { bulk: { registerBulkPrepareHandler: BulkHandlers.registerBulkPrepareHandler, registerBulkFulfilHandler: BulkHandlers.registerBulkFulfilHandler, - registerBulkProcessingHandler: BulkHandlers.registerBulkProcessingHandler + registerBulkProcessingHandler: BulkHandlers.registerBulkProcessingHandler, + registerBulkGetHandler: BulkHandlers.registerGetBulkTransferHandler } } diff --git a/src/handlers/transfers/handler.js b/src/handlers/transfers/handler.js index 682073485..c350b2586 100644 --- a/src/handlers/transfers/handler.js +++ b/src/handlers/transfers/handler.js @@ -292,6 +292,18 @@ const fulfil = async (error, messages) => { const params = { message, kafkaTopic, decodedPayload: payload, span, consumer: Consumer, producer: Producer } Logger.isInfoEnabled && Logger.info(Util.breadcrumb(location, { path: 'getById' })) + + // We fail early and silently to allow timeout handler abort transfer + // if 'RESERVED' transfer state is sent in with v1.0 content-type + if (headers['content-type'].split('=')[1] === '1.0' && payload.transferState === TransferState.RESERVED) { + Logger.isInfoEnabled && Logger.info(Util.breadcrumb(location, `failSilentlyforReservedStateWith1.0ContentType--${actionLetter}0`)) + const errorMessage = 'action "RESERVE" is not allowed in fulfil handler for v1.0 clients.' + Logger.isErrorEnabled && Logger.error(errorMessage) + !!span && span.error(errorMessage) + histTimerEnd({ success: true, fspId: Config.INSTRUMENTATION_METRICS_LABELS.fspId }) + return true + } + const transfer = await TransferService.getById(transferId) const transferStateEnum = transfer && transfer.transferStateEnumeration diff --git a/src/shared/setup.js b/src/shared/setup.js index 4e7e26b8b..cafc77e37 100644 --- a/src/shared/setup.js +++ b/src/shared/setup.js @@ -186,6 +186,10 @@ const createHandlers = async (handlers) => { await RegisterHandlers.bulk.registerBulkProcessingHandler() break } + case 'bulkget': { + await RegisterHandlers.bulk.registerBulkGetHandler() + break + } default: { const error = `Handler Setup - ${JSON.stringify(handler)} is not a valid handler to register!` Logger.isErrorEnabled && Logger.error(error) diff --git a/test/integration/handlers/handlers.test.js b/test/integration/handlers/handlers.test.js index dba70e02c..649ceef9d 100644 --- a/test/integration/handlers/handlers.test.js +++ b/test/integration/handlers/handlers.test.js @@ -143,11 +143,13 @@ const prepareTestData = async (dataObj) => { const prepareHeaders = { 'fspiop-source': payer.participant.name, - 'fspiop-destination': payee.participant.name + 'fspiop-destination': payee.participant.name, + 'content-type': 'application/vnd.interoperability.transfers+json;version=1.1' } const fulfilAbortRejectHeaders = { 'fspiop-source': payee.participant.name, - 'fspiop-destination': payer.participant.name + 'fspiop-destination': payer.participant.name, + 'content-type': 'application/vnd.interoperability.transfers+json;version=1.1' } const fulfilPayload = { diff --git a/test/unit/handlers/bulk/get/handler.test.js b/test/unit/handlers/bulk/get/handler.test.js new file mode 100644 index 000000000..dfab7abfb --- /dev/null +++ b/test/unit/handlers/bulk/get/handler.test.js @@ -0,0 +1,401 @@ +/***** + License + -------------- + Copyright © 2017 Bill & Melinda Gates Foundation + 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 + + http://www.apache.org/licenses/LICENSE-2.0 + + 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. + + Contributors + -------------- + This is the official list of the Mojaloop project contributors for this file. + Names of the original copyright holders (individuals or organizations) + should be listed with a '*' in the first column. People who have + contributed from an organization can be listed under the organization + that actually holds the copyright for their contributions (see the + Gates Foundation organization for an example). Those individuals should have + their names indented and be marked with a '-'. Email address can be added + optionally within square brackets . + + * Gates Foundation + - Name Surname + + * Steven Oderayi + -------------- + ******/ +'use strict' + +const Uuid = require('uuid4') +const Sinon = require('sinon') +const Proxyquire = require('proxyquire') +const Test = require('tapes')(require('tape')) +const EventSdk = require('@mojaloop/event-sdk') +const Kafka = require('@mojaloop/central-services-shared').Util.Kafka +const MainUtil = require('@mojaloop/central-services-shared').Util +const KafkaConsumer = require('@mojaloop/central-services-stream').Kafka.Consumer +const Consumer = require('@mojaloop/central-services-stream').Util.Consumer +const Enum = require('@mojaloop/central-services-shared').Enum +const Comparators = require('@mojaloop/central-services-shared').Util.Comparators +const Validator = require('../../../../../src/handlers/bulk/shared/validator') +const BulkTransferService = require('../../../../../src/domain/bulkTransfer') +const BulkTransferModel = require('../../../../../src/models/bulkTransfer/bulkTransfer') +const ilp = require('../../../../../src/models/transfer/ilpPacket') +// const TransferState = Enum.Transfers.TransferState +// const TransferInternalState = Enum.Transfers.TransferInternalState + +const bulkTransfer = { + bulkTransferId: 'fake-bulk-transfer-id', + bulkQuoteId: 'fake-bulk-quote-id', + payerFsp: 'dfsp1', + payeeFsp: 'dfsp2', + expiration: '2016-05-24T08:38:08.699-04:00', + individualTransfers: [ + { + transferId: 'b51ec534-ee48-4575-b6a9-ead2955b8999', + transferAmount: { + currency: 'USD', + amount: '433.88' + }, + ilpPacket: 'AYIBgQAAAAAAAASwNGxldmVsb25lLmRmc3AxLm1lci45T2RTOF81MDdqUUZERmZlakgyOVc4bXFmNEpLMHlGTFGCAUBQU0svMS4wCk5vbmNlOiB1SXlweUYzY3pYSXBFdzVVc05TYWh3CkVuY3J5cHRpb246IG5vbmUKUGF5bWVudC1JZDogMTMyMzZhM2ItOGZhOC00MTYzLTg0NDctNGMzZWQzZGE5OGE3CgpDb250ZW50LUxlbmd0aDogMTM1CkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbgpTZW5kZXItSWRlbnRpZmllcjogOTI4MDYzOTEKCiJ7XCJmZWVcIjowLFwidHJhbnNmZXJDb2RlXCI6XCJpbnZvaWNlXCIsXCJkZWJpdE5hbWVcIjpcImFsaWNlIGNvb3BlclwiLFwiY3JlZGl0TmFtZVwiOlwibWVyIGNoYW50XCIsXCJkZWJpdElkZW50aWZpZXJcIjpcIjkyODA2MzkxXCJ9IgA', + condition: 'YlK5TZyhflbXaDRPtR5zhCu8FrbgvrQwwmzuH0iQ0AI' + } + ], + extensionList: { + extension: [ + { + key: 'key1', + value: 'value1' + }, + { + key: 'key2', + value: 'value2' + } + ] + } +} + +const bulkTransferReturn = { + bulkTransferId: bulkTransfer.bulkTransferId, + bulkTransferStateId: 'COMPLETED', + completedTimestamp: new Date().toISOString(), + payerFsp: 'payerfsp', + payeeFsp: 'payeefsp', + bulkQuoteId: bulkTransfer.bulkQuoteId, + expirationDate: new Date().toISOString() +} + +const messageProtocol = { + id: Uuid(), + from: bulkTransfer.payerFsp, + to: bulkTransfer.payeeFsp, + type: 'application/json', + content: { + headers: { + 'fspiop-source': bulkTransfer.payeeFsp, + 'fspiop-destination': 'source' + }, + uriParams: { id: bulkTransfer.bulkTransferId } + }, + metadata: { + event: { + id: Uuid(), + type: Enum.Events.Event.Type.BULK, + action: Enum.Events.Event.Action.GET, + createdAt: new Date(), + state: { + status: 'success', + code: 0 + } + } + }, + pp: '' +} + +const topicName = 'topic-test' + +const messages = [ + { + topic: topicName, + value: messageProtocol + } +] + +const config = { + options: { + mode: 2, + batchSize: 1, + pollFrequency: 10, + recursiveTimeout: 100, + messageCharset: 'utf8', + messageAsJSON: true, + sync: true, + consumeTimeout: 1000 + }, + rdkafkaConf: { + 'client.id': 'kafka-test', + debug: 'all', + 'group.id': 'central-ledger-kafka', + 'metadata.broker.list': 'localhost:9092', + 'enable.auto.commit': false + } +} + +const command = () => { } + +let SpanStub +let allBulkTransferHandlers + +Test('Bulk Transfer GET handler', getHandlerTest => { + let sandbox + + getHandlerTest.beforeEach(test => { + sandbox = Sinon.createSandbox() + SpanStub = { + audit: sandbox.stub().callsFake(), + error: sandbox.stub().callsFake(), + finish: sandbox.stub().callsFake(), + debug: sandbox.stub().callsFake(), + info: sandbox.stub().callsFake(), + getChild: sandbox.stub().returns(SpanStub), + setTags: sandbox.stub().callsFake() + } + + const TracerStub = { + extractContextFromMessage: sandbox.stub().callsFake(() => { + return {} + }), + createChildSpanFromContext: sandbox.stub().callsFake(() => { + return SpanStub + }) + } + + const EventSdkStub = { + Tracer: TracerStub + } + + allBulkTransferHandlers = Proxyquire('../../../../../src/handlers/bulk/get/handler', { + '@mojaloop/event-sdk': EventSdkStub + }) + + sandbox.stub(KafkaConsumer.prototype, 'constructor').returns(Promise.resolve()) + sandbox.stub(KafkaConsumer.prototype, 'connect').returns(Promise.resolve()) + sandbox.stub(KafkaConsumer.prototype, 'consume').returns(Promise.resolve()) + sandbox.stub(KafkaConsumer.prototype, 'commitMessageSync').returns(Promise.resolve()) + sandbox.stub(Comparators) + sandbox.stub(Validator) + sandbox.stub(BulkTransferService) + sandbox.stub(BulkTransferModel) + sandbox.stub(Consumer, 'getConsumer').returns({ + commitMessageSync: async function () { + return true + } + }) + sandbox.stub(Consumer, 'isConsumerAutoCommitEnabled').returns(false) + sandbox.stub(ilp) + sandbox.stub(Kafka) + sandbox.stub(MainUtil.StreamingProtocol) + Kafka.produceGeneralMessage.returns(Promise.resolve()) + test.end() + }) + + getHandlerTest.afterEach(test => { + sandbox.restore() + test.end() + }) + + getHandlerTest.test('registerGetBulkTransferHandler should', registerHandlerTest => { + registerHandlerTest.test('returns true when registering the GET bulk transfer handler', async (test) => { + await Consumer.createHandler(topicName, config, command) + Kafka.transformAccountToTopicName.returns(topicName) + Kafka.proceed.returns(true) + Kafka.getKafkaConfig.returns(config) + const result = await allBulkTransferHandlers.registerGetBulkTransferHandler() + test.equal(result, true) + test.end() + }) + + registerHandlerTest.test('return an error when registering GET bulk transfer handler.', async (test) => { + try { + await Consumer.createHandler(topicName, config, command) + Kafka.transformGeneralTopicName.returns(topicName) + Kafka.getKafkaConfig.throws(new Error()) + await allBulkTransferHandlers.registerGetBulkTransferHandler() + test.fail('Error not thrown') + test.end() + } catch (e) { + test.pass('Error thrown') + test.end() + } + }) + registerHandlerTest.end() + }) + + getHandlerTest.test('get bulk transfer by id should', getBulkTransferTest => { + getBulkTransferTest.test('return true on a single message', async (test) => { + const localMessages = MainUtil.clone(messages) + await Consumer.createHandler(topicName, config, command) + Kafka.transformAccountToTopicName.returns(topicName) + Kafka.proceed.returns(true) + Kafka.getKafkaConfig.returns(config) + const result = await allBulkTransferHandlers.getBulkTransfer(null, localMessages[0]) + test.equal(result, true) + test.end() + }) + + getBulkTransferTest.test('return true on an array of messages', async (test) => { + const localMessages = MainUtil.clone(messages) + await Consumer.createHandler(topicName, config, command) + Kafka.transformAccountToTopicName.returns(topicName) + Kafka.proceed.returns(true) + Kafka.getKafkaConfig.returns(config) + Consumer.isConsumerAutoCommitEnabled.returns(true) + const result = await allBulkTransferHandlers.getBulkTransfer(null, localMessages) + test.equal(result, true) + test.end() + }) + + getBulkTransferTest.test('return an error when an error is passed in', async (test) => { + try { + const localMessages = MainUtil.clone(messages) + await Consumer.createHandler(topicName, config, command) + Kafka.transformGeneralTopicName.returns(topicName) + Kafka.getKafkaConfig.returns(config) + await allBulkTransferHandlers.getBulkTransfer(true, localMessages) + test.fail('Error not thrown') + test.end() + } catch (e) { + test.pass('Error thrown') + test.end() + } + }) + + getBulkTransferTest.test('return an error when the Kafka topic is invalid', async (test) => { + const localMessages = MainUtil.clone(messages) + await Consumer.createHandler(topicName, config, command) + Consumer.getConsumer.throws(new Error()) + Kafka.getKafkaConfig.returns(config) + const result = await allBulkTransferHandlers.getBulkTransfer(null, localMessages) + test.equal(result, true) + test.end() + }) + + getBulkTransferTest.test('return an error when the bulk transfer by id is not found', async (test) => { + const localMessages = MainUtil.clone(messages) + await Consumer.createHandler(topicName, config, command) + Kafka.transformAccountToTopicName.returns(topicName) + Kafka.proceed.returns(true) + Kafka.getKafkaConfig.returns(config) + Validator.validateParticipantByName.returns({ isValid: true }) + BulkTransferService.getParticipantsById.withArgs(bulkTransfer.bulkTransferId).returns({ payeeFsp: bulkTransfer.payeeFsp, payerFsp: bulkTransfer.payerFsp }) + BulkTransferModel.getById.returns(null) + const result = await allBulkTransferHandlers.getBulkTransfer(null, localMessages) + test.equal(result, true) + test.end() + }) + + getBulkTransferTest.test('return an error when the bulk transfer by id is not found - autocommit enabled', async (test) => { + const localMessages = MainUtil.clone(messages) + await Consumer.createHandler(topicName, config, command) + Kafka.transformAccountToTopicName.returns(topicName) + Kafka.proceed.returns(true) + Kafka.getKafkaConfig.returns(config) + Validator.validateParticipantByName.returns({ isValid: true }) + BulkTransferService.getParticipantsById.withArgs(bulkTransfer.bulkTransferId).returns({ payeeFsp: bulkTransfer.payeeFsp, payerFsp: bulkTransfer.payerFsp }) + BulkTransferModel.getById.returns(null) + Consumer.isConsumerAutoCommitEnabled.returns(true) + const result = await allBulkTransferHandlers.getBulkTransfer(null, localMessages) + test.equal(result, true) + test.end() + }) + + getBulkTransferTest.test('return an error when the requester is not involved in the bulk transfer', async (test) => { + const localMessages = MainUtil.clone(messages) + await Consumer.createHandler(topicName, config, command) + Kafka.transformAccountToTopicName.returns(topicName) + Kafka.proceed.returns(true) + Kafka.getKafkaConfig.returns(config) + Validator.validateParticipantByName.returns({ isValid: true }) + Validator.validateParticipantBulkTransferId.returns(false) + BulkTransferService.getParticipantsById.withArgs(bulkTransfer.bulkTransferId).returns({ payeeFsp: bulkTransfer.payeeFsp, payerFsp: bulkTransfer.payerFsp }) + BulkTransferModel.getById.returns({}) + Consumer.isConsumerAutoCommitEnabled.returns(true) + localMessages[0].value.from = 'invalidfsp' + const result = await allBulkTransferHandlers.getBulkTransfer(null, localMessages) + test.equal(result, true) + test.end() + }) + + getBulkTransferTest.test('return an error when the requester is not involved in the bulk transfer - autocommit disabled', async (test) => { + const localMessages = MainUtil.clone(messages) + await Consumer.createHandler(topicName, config, command) + Kafka.transformAccountToTopicName.returns(topicName) + Kafka.proceed.returns(true) + Kafka.getKafkaConfig.returns(config) + Validator.validateParticipantByName.returns({ isValid: true }) + Validator.validateParticipantBulkTransferId.returns(false) + BulkTransferService.getParticipantsById.withArgs(bulkTransfer.bulkTransferId).returns({ payeeFsp: bulkTransfer.payeeFsp, payerFsp: bulkTransfer.payerFsp }) + BulkTransferModel.getById.returns({}) + Consumer.isConsumerAutoCommitEnabled.returns(false) + localMessages[0].value.from = 'invalidfsp' + const result = await allBulkTransferHandlers.getBulkTransfer(null, localMessages) + test.equal(result, true) + test.end() + }) + + getBulkTransferTest.test('return an error when the bulk transfer by id is found - autocommit enabled', async (test) => { + const localMessages = MainUtil.clone(messages) + await Consumer.createHandler(topicName, config, command) + Kafka.transformAccountToTopicName.returns(topicName) + Kafka.proceed.returns(true) + Kafka.getKafkaConfig.returns(config) + Validator.validateParticipantByName.returns({ isValid: true }) + BulkTransferService.getParticipantsById.withArgs(bulkTransfer.bulkTransferId).returns({ payeeFsp: bulkTransfer.payeeFsp, payerFsp: bulkTransfer.payerFsp }) + BulkTransferModel.getById.withArgs(bulkTransfer.bulkTransferId).returns(Promise.resolve(bulkTransferReturn)) + Consumer.isConsumerAutoCommitEnabled.returns(true) + const result = await allBulkTransferHandlers.getBulkTransfer(null, localMessages) + test.equal(result, true) + test.end() + }) + + getBulkTransferTest.test('log an error when general message cannot be produced', async (test) => { + const localMessages = MainUtil.clone(messages) + await Consumer.createHandler(topicName, config, command) + Kafka.proceed.throws(new Error()) + Validator.validateParticipantByName.returns({ isValid: true }) + BulkTransferService.getParticipantsById.withArgs(bulkTransfer.bulkTransferId).returns({ payeeFsp: bulkTransfer.payeeFsp, payerFsp: bulkTransfer.payerFsp }) + const bulkTransferResult = MainUtil.clone(bulkTransferReturn) + bulkTransferResult.bulkTransferStateId = Enum.Transfers.BulkProcessingState.PROCESSING + bulkTransferResult.extensionList = [] + BulkTransferModel.getById.withArgs(bulkTransfer.bulkTransferId).returns(Promise.resolve(bulkTransferResult)) + const bulkTransferResult2 = { + ...bulkTransferResult, + bulkTransferState: 'COMPLETED', + payerBulkTransfer: { + bulkTransferState: 'COMPLETED', + individualTransferResults: [] + }, + payeeBulkTransfer: { + bulkTransferState: 'COMPLETED', + individualTransferResults: [] + } + } + BulkTransferService.getBulkTransferById.withArgs(bulkTransfer.bulkTransferId).returns(Promise.resolve(bulkTransferResult2)) + + try { + await allBulkTransferHandlers.getBulkTransfer(null, localMessages) + const expectedState = new EventSdk.EventStateMetadata(EventSdk.EventStatusType.failed, '2001', 'Internal server error') + test.ok(SpanStub.finish.calledWith('', expectedState)) + test.end() + } catch (e) { + test.fail('Error thrown') + test.end() + } + }) + + getBulkTransferTest.end() + }) + + getHandlerTest.end() +}) diff --git a/test/unit/handlers/transfers/handler.test.js b/test/unit/handlers/transfers/handler.test.js index 3125c6495..bb2d50623 100644 --- a/test/unit/handlers/transfers/handler.test.js +++ b/test/unit/handlers/transfers/handler.test.js @@ -131,7 +131,7 @@ const messageProtocol = { to: transfer.payeeFsp, type: 'application/json', content: { - headers: { 'fspiop-destination': transfer.payerFsp }, + headers: { 'fspiop-destination': transfer.payerFsp, 'content-type': 'application/vnd.interoperability.transfers+json;version=1.1' }, uriParams: { id: transfer.transferId }, payload: transfer }, @@ -177,7 +177,8 @@ const fulfilMessages = [ uriParams: { id: messageProtocol.content.uriParams.id }, headers: { 'fspiop-source': 'dfsp1', - 'fspiop-destination': 'dfsp2' + 'fspiop-destination': 'dfsp2', + 'content-type': 'application/vnd.interoperability.transfers+json;version=1.1' } }, metadata: { @@ -196,7 +197,8 @@ const fulfilMessages = [ uriParams: { id: messageProtocolBulkCommit.content.uriParams.id }, headers: { 'fspiop-source': 'dfsp1', - 'fspiop-destination': 'dfsp2' + 'fspiop-destination': 'dfsp2', + 'content-type': 'application/vnd.interoperability.transfers+json;version=1.1' } }, metadata: { @@ -957,6 +959,20 @@ Test('Transfer handler', transferHandlerTest => { }) transferHandlerTest.test('fulfil should', fulfilTest => { + fulfilTest.test('fail validation when when RESERVED transfer state is received from v1.0 clients', async (test) => { + const localfulfilMessages = MainUtil.clone(fulfilMessages) + localfulfilMessages[0].value.content.headers['content-type'] = 'application/vnd.interoperability.transfers+json;version=1.0' + localfulfilMessages[0].value.content.payload.transferState = 'RESERVED' + await Consumer.createHandler(topicName, config, command) + Kafka.transformGeneralTopicName.returns(topicName) + TransferService.getById.returns(Promise.resolve(null)) + Kafka.proceed.returns(true) + + const result = await allTransferHandlers.fulfil(null, localfulfilMessages) + test.equal(result, true) + test.end() + }) + fulfilTest.test('fail validation when invalid event action is provided', async (test) => { const localfulfilMessages = MainUtil.clone(fulfilMessages) await Consumer.createHandler(topicName, config, command) diff --git a/test/util/scripts/populateTestData.sh b/test/util/scripts/populateTestData.sh index c13ecd17a..26b0e8e02 100755 --- a/test/util/scripts/populateTestData.sh +++ b/test/util/scripts/populateTestData.sh @@ -240,6 +240,16 @@ do \"value\": \"http://localhost:1080/${FSP}\" }'" + sh -c "curl -X POST \ + ${CENTRAL_LEDGER_ADMIN_URI_PREFIX}://${CENTRAL_LEDGER_ADMIN_HOST}:${CENTRAL_LEDGER_ADMIN_PORT}${CENTRAL_LEDGER_ADMIN_BASE}participants/${FSP}/endpoints \ + -H 'Cache-Control: no-cache' \ + -H 'Content-Type: application/json' \ + -d '{ + \"type\": \"FSPIOP_CALLBACK_URL_BULK_QUOTES\", + \"value\": \"http://localhost:1080\" + }'" + + echo echo "Retrieving EndPoints for '$FSP'" echo "---------------------------------------------------------------------" diff --git a/test/util/scripts/populateTestDataForLegacySimulator.sh b/test/util/scripts/populateTestDataForLegacySimulator.sh new file mode 100755 index 000000000..ced737b90 --- /dev/null +++ b/test/util/scripts/populateTestDataForLegacySimulator.sh @@ -0,0 +1,261 @@ +#!/usr/bin/env bash +echo "---------------------------------------------------------------------" +echo "Starting script to populate test data.." +echo "---------------------------------------------------------------------" +echo + +CWD="${0%/*}" + +if [[ "$CWD" =~ ^(.*)\.sh$ ]]; +then + CWD="." +fi + +echo "Loading env vars..." +source $CWD/env.sh + +echo +echo "---------------------------------------------------------------------" +echo " Creating TestData for $FSPList" +echo "---------------------------------------------------------------------" + +echo "---------------------------------------------------------------------" +echo "Creating Hub Reconciliation account for the Scheme so that participant accounts in that currency can be created." +echo "---------------------------------------------------------------------" +curl -X POST \ + ${CENTRAL_LEDGER_ADMIN_URI_PREFIX}://${CENTRAL_LEDGER_ADMIN_HOST}:${CENTRAL_LEDGER_ADMIN_PORT}${CENTRAL_LEDGER_ADMIN_BASE}participants/Hub/accounts \ + -H 'Cache-Control: no-cache' \ + -H 'Content-Type: application/json' \ + -H 'cache-control: no-cache' \ + -d '{ + "currency": "USD", + "type": "HUB_RECONCILIATION" +}' + +echo "---------------------------------------------------------------------" +echo "Creating Hub Multilateral Net Settlement account for the Scheme so that participant accounts in that currency can be created." +echo "---------------------------------------------------------------------" +curl -X POST \ + ${CENTRAL_LEDGER_ADMIN_URI_PREFIX}://${CENTRAL_LEDGER_ADMIN_HOST}:${CENTRAL_LEDGER_ADMIN_PORT}${CENTRAL_LEDGER_ADMIN_BASE}participants/Hub/accounts \ + -H 'Cache-Control: no-cache' \ + -H 'Content-Type: application/json' \ + -H 'cache-control: no-cache' \ + -d '{ + "currency": "USD", + "type": "HUB_MULTILATERAL_SETTLEMENT" +}' + +echo +echo "---------------------------------------------------------------------" +echo " Creating TestData for $FSPList" +echo "---------------------------------------------------------------------" +echo " Prerequisites for Central-Ledger:" +echo " 1. Ensure you run 'npm run migrate'" +echo " 2. The below requests only work for the 'ADMIN' API" + +for FSP in "${FSPList[@]}" +do + echo '' + echo "*********************************************************************" + echo '' + echo + echo "Creating participants '$FSP'" + echo "---------------------------------------------------------------------" + sh -c "curl -i -X POST \ + ${CENTRAL_LEDGER_ADMIN_URI_PREFIX}://${CENTRAL_LEDGER_ADMIN_HOST}:${CENTRAL_LEDGER_ADMIN_PORT}${CENTRAL_LEDGER_ADMIN_BASE}participants \ + -H 'Cache-Control: no-cache' \ + -H 'Content-Type: application/json' \ + -d '{ + \"name\": \"$FSP\", + \"currency\":\"USD\" + }'" + + echo + echo "Setting limits and initial position for '$FSP'" + echo "---------------------------------------------------------------------" + sh -c "curl -i -X POST \ + ${CENTRAL_LEDGER_ADMIN_URI_PREFIX}://${CENTRAL_LEDGER_ADMIN_HOST}:${CENTRAL_LEDGER_ADMIN_PORT}${CENTRAL_LEDGER_ADMIN_BASE}participants/${FSP}/initialPositionAndLimits \ + -H 'Cache-Control: no-cache' \ + -H 'Content-Type: application/json' \ + -d '{ + \"currency\": \"USD\", + \"limit\": { + \"type\": \"NET_DEBIT_CAP\", + \"value\": ${DEFAULT_NET_DEBIT_CAP} + }, + \"initialPosition\": 0 + }'" + + echo + echo "Retrieving limits for '$FSP'" + echo "---------------------------------------------------------------------" + curl -X GET \ + ${CENTRAL_LEDGER_ADMIN_URI_PREFIX}://${CENTRAL_LEDGER_ADMIN_HOST}:${CENTRAL_LEDGER_ADMIN_PORT}${CENTRAL_LEDGER_ADMIN_BASE}participants/${FSP}/limits \ + -H 'Cache-Control: no-cache' + + echo + echo "Set callback URIs for each FSP '$FSP'" + echo "---------------------------------------------------------------------" + sh -c "curl -X POST \ + ${CENTRAL_LEDGER_ADMIN_URI_PREFIX}://${CENTRAL_LEDGER_ADMIN_HOST}:${CENTRAL_LEDGER_ADMIN_PORT}${CENTRAL_LEDGER_ADMIN_BASE}participants/${FSP}/endpoints \ + -H 'Cache-Control: no-cache' \ + -H 'Content-Type: application/json' \ + -d '{ + \"type\": \"FSPIOP_CALLBACK_URL_TRANSFER_POST\", + \"value\": \"http://localhost:8444/${FSP}/transfers\" + }'" + + sh -c "curl -X POST \ + ${CENTRAL_LEDGER_ADMIN_URI_PREFIX}://${CENTRAL_LEDGER_ADMIN_HOST}:${CENTRAL_LEDGER_ADMIN_PORT}${CENTRAL_LEDGER_ADMIN_BASE}participants/${FSP}/endpoints \ + -H 'Cache-Control: no-cache' \ + -H 'Content-Type: application/json' \ + -d '{ + \"type\": \"FSPIOP_CALLBACK_URL_PARTICIPANT_PUT\", + \"value\": \"http://localhost:8444/${FSP}/participants/{{partyIdType}}/{{partyIdentifier}}\" + }'" + + sh -c "curl -X POST \ + ${CENTRAL_LEDGER_ADMIN_URI_PREFIX}://${CENTRAL_LEDGER_ADMIN_HOST}:${CENTRAL_LEDGER_ADMIN_PORT}${CENTRAL_LEDGER_ADMIN_BASE}participants/${FSP}/endpoints \ + -H 'Cache-Control: no-cache' \ + -H 'Content-Type: application/json' \ + -d '{ + \"type\": \"FSPIOP_CALLBACK_URL_PARTIES_GET\", + \"value\": \"http://localhost:8444/${FSP}/parties/{{partyIdType}}/{{partyIdentifier}}\" + }'" + + sh -c "curl -X POST \ + ${CENTRAL_LEDGER_ADMIN_URI_PREFIX}://${CENTRAL_LEDGER_ADMIN_HOST}:${CENTRAL_LEDGER_ADMIN_PORT}${CENTRAL_LEDGER_ADMIN_BASE}participants/${FSP}/endpoints \ + -H 'Cache-Control: no-cache' \ + -H 'Content-Type: application/json' \ + -d '{ + \"type\": \"FSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR\", + \"value\": \"http://localhost:8444/${FSP}/participants/{{partyIdType}}/{{partyIdentifier}}/error\" + }'" + + sh -c "curl -X POST \ + ${CENTRAL_LEDGER_ADMIN_URI_PREFIX}://${CENTRAL_LEDGER_ADMIN_HOST}:${CENTRAL_LEDGER_ADMIN_PORT}${CENTRAL_LEDGER_ADMIN_BASE}participants/${FSP}/endpoints \ + -H 'Cache-Control: no-cache' \ + -H 'Content-Type: application/json' \ + -d '{ + \"type\": \"FSPIOP_CALLBACK_URL_PARTICIPANT_BATCH_PUT\", + \"value\": \"http://localhost:8444/${FSP}/participants/{{requestId}}\" + }'" + + sh -c "curl -X POST \ + ${CENTRAL_LEDGER_ADMIN_URI_PREFIX}://${CENTRAL_LEDGER_ADMIN_HOST}:${CENTRAL_LEDGER_ADMIN_PORT}${CENTRAL_LEDGER_ADMIN_BASE}participants/${FSP}/endpoints \ + -H 'Cache-Control: no-cache' \ + -H 'Content-Type: application/json' \ + -d '{ + \"type\": \"FSPIOP_CALLBACK_URL_PARTICIPANT_BATCH_PUT_ERROR\", + \"value\": \"http://localhost:8444/${FSP}\/participants/{{requestId}}/error\" + }'" + + sh -c "curl -X POST \ + ${CENTRAL_LEDGER_ADMIN_URI_PREFIX}://${CENTRAL_LEDGER_ADMIN_HOST}:${CENTRAL_LEDGER_ADMIN_PORT}${CENTRAL_LEDGER_ADMIN_BASE}participants/${FSP}/endpoints \ + -H 'Cache-Control: no-cache' \ + -H 'Content-Type: application/json' \ + -d '{ + \"type\": \"FSPIOP_CALLBACK_URL_PARTIES_PUT\", + \"value\": \"http://localhost:8444/${FSP}/parties/{{partyIdType}}/{{partyIdentifier}}\" + }'" + + sh -c "curl -X POST \ + ${CENTRAL_LEDGER_ADMIN_URI_PREFIX}://${CENTRAL_LEDGER_ADMIN_HOST}:${CENTRAL_LEDGER_ADMIN_PORT}${CENTRAL_LEDGER_ADMIN_BASE}participants/${FSP}/endpoints \ + -H 'Cache-Control: no-cache' \ + -H 'Content-Type: application/json' \ + -d '{ + \"type\": \"FSPIOP_CALLBACK_URL_PARTIES_PUT_ERROR\", + \"value\": \"http://localhost:8444/${FSP}/parties/{{partyIdType}}/{{partyIdentifier}}\" + }'" + + sh -c "curl -X POST \ + ${CENTRAL_LEDGER_ADMIN_URI_PREFIX}://${CENTRAL_LEDGER_ADMIN_HOST}:${CENTRAL_LEDGER_ADMIN_PORT}${CENTRAL_LEDGER_ADMIN_BASE}participants/${FSP}/endpoints \ + -H 'Cache-Control: no-cache' \ + -H 'Content-Type: application/json' \ + -d '{ + \"type\": \"FSPIOP_CALLBACK_URL_TRANSFER_PUT\", + \"value\": \"http://localhost:8444/${FSP}/transfers/{{transferId}}\" + }'" + + sh -c "curl -X POST \ + ${CENTRAL_LEDGER_ADMIN_URI_PREFIX}://${CENTRAL_LEDGER_ADMIN_HOST}:${CENTRAL_LEDGER_ADMIN_PORT}${CENTRAL_LEDGER_ADMIN_BASE}participants/${FSP}/endpoints \ + -H 'Cache-Control: no-cache' \ + -H 'Content-Type: application/json' \ + -d '{ + \"type\": \"FSPIOP_CALLBACK_URL_TRANSFER_ERROR\", + \"value\": \"http://localhost:8444/${FSP}/transfers/{{transferId}}/error\" + }'" + + sh -c "curl -X POST \ + ${CENTRAL_LEDGER_ADMIN_URI_PREFIX}://${CENTRAL_LEDGER_ADMIN_HOST}:${CENTRAL_LEDGER_ADMIN_PORT}${CENTRAL_LEDGER_ADMIN_BASE}participants/${FSP}/endpoints \ + -H 'Cache-Control: no-cache' \ + -H 'Content-Type: application/json' \ + -d '{ + \"type\": \"FSPIOP_CALLBACK_URL_BULK_TRANSFER_POST\", + \"value\": \"http://localhost:8444/${FSP}/bulkTransfers\" + }'" + + sh -c "curl -X POST \ + ${CENTRAL_LEDGER_ADMIN_URI_PREFIX}://${CENTRAL_LEDGER_ADMIN_HOST}:${CENTRAL_LEDGER_ADMIN_PORT}${CENTRAL_LEDGER_ADMIN_BASE}participants/${FSP}/endpoints \ + -H 'Cache-Control: no-cache' \ + -H 'Content-Type: application/json' \ + -d '{ + \"type\": \"FSPIOP_CALLBACK_URL_BULK_TRANSFER_PUT\", + \"value\": \"http://localhost:8444/${FSP}/bulkTransfers/{{id}}\" + }'" + + sh -c "curl -X POST \ + ${CENTRAL_LEDGER_ADMIN_URI_PREFIX}://${CENTRAL_LEDGER_ADMIN_HOST}:${CENTRAL_LEDGER_ADMIN_PORT}${CENTRAL_LEDGER_ADMIN_BASE}participants/${FSP}/endpoints \ + -H 'Cache-Control: no-cache' \ + -H 'Content-Type: application/json' \ + -d '{ + \"type\": \"FSPIOP_CALLBACK_URL_BULK_TRANSFER_ERROR\", + \"value\": \"http://localhost:8444/${FSP}/bulkTransfers/{{id}}/error\" + }'" + + sh -c "curl -X POST \ + ${CENTRAL_LEDGER_ADMIN_URI_PREFIX}://${CENTRAL_LEDGER_ADMIN_HOST}:${CENTRAL_LEDGER_ADMIN_PORT}${CENTRAL_LEDGER_ADMIN_BASE}participants/${FSP}/endpoints \ + -H 'Cache-Control: no-cache' \ + -H 'Content-Type: application/json' \ + -d '{ + \"type\": \"FSPIOP_CALLBACK_URL_QUOTES\", + \"value\": \"http://localhost:8444/${FSP}\" + }'" + + sh -c "curl -X POST \ + ${CENTRAL_LEDGER_ADMIN_URI_PREFIX}://${CENTRAL_LEDGER_ADMIN_HOST}:${CENTRAL_LEDGER_ADMIN_PORT}${CENTRAL_LEDGER_ADMIN_BASE}participants/${FSP}/endpoints \ + -H 'Cache-Control: no-cache' \ + -H 'Content-Type: application/json' \ + -d '{ + \"type\": \"FSPIOP_CALLBACK_URL_AUTHORIZATIONS\", + \"value\": \"http://localhost:8444/${FSP}\" + }'" + + sh -c "curl -X POST \ + ${CENTRAL_LEDGER_ADMIN_URI_PREFIX}://${CENTRAL_LEDGER_ADMIN_HOST}:${CENTRAL_LEDGER_ADMIN_PORT}${CENTRAL_LEDGER_ADMIN_BASE}participants/${FSP}/endpoints \ + -H 'Cache-Control: no-cache' \ + -H 'Content-Type: application/json' \ + -d '{ + \"type\": \"FSPIOP_CALLBACK_URL_TRX_REQ_SERVICE\", + \"value\": \"http://localhost:8444/${FSP}\" + }'" + + sh -c "curl -X POST \ + ${CENTRAL_LEDGER_ADMIN_URI_PREFIX}://${CENTRAL_LEDGER_ADMIN_HOST}:${CENTRAL_LEDGER_ADMIN_PORT}${CENTRAL_LEDGER_ADMIN_BASE}participants/${FSP}/endpoints \ + -H 'Cache-Control: no-cache' \ + -H 'Content-Type: application/json' \ + -d '{ + \"type\": \"FSPIOP_CALLBACK_URL_BULK_QUOTES\", + \"value\": \"http://localhost:8444\" + }'" + + echo + echo "Retrieving EndPoints for '$FSP'" + echo "---------------------------------------------------------------------" + curl -X GET \ + ${CENTRAL_LEDGER_ADMIN_URI_PREFIX}://${CENTRAL_LEDGER_ADMIN_HOST}:${CENTRAL_LEDGER_ADMIN_PORT}${CENTRAL_LEDGER_ADMIN_BASE}participants/${FSP}/endpoints \ + -H 'Cache-Control: no-cache' + +done + +echo