From 15cc91097b1d94ef674321866c5ac149d5fab2ab Mon Sep 17 00:00:00 2001 From: Claudio Viola Date: Thu, 9 Jul 2020 12:58:51 +0200 Subject: [PATCH] Feature/otc 624 rework central settlement integration test set up (#314) * OTC-624: refactoring integration tests initial data setup * OTC-624 fixing and refactoring cleaning up * OTC-624 refactoring and cleaning up test setup * Ignoring package updates * OTC-624 reverting back merge conflict change * OTC-624 renamed scenario and fixing axios version * OTC-624 renamed folder due to order of tests --- .dockerignore | 16 + audit-resolve.json | 275 ++++++----- package-lock.json | 12 +- package.json | 2 +- test/integration-config.js | 12 - test/integration/config.js | 28 ++ test/integration/helpers/api.js | 143 ++++++ test/integration/helpers/models.js | 3 + test/integration/helpers/transferData.js | 451 ------------------ test/integration/helpers/utils.js | 40 ++ .../settlementTransfer.test.js | 29 +- .../settlementTransferData.js | 208 ++++++++ 12 files changed, 621 insertions(+), 598 deletions(-) create mode 100644 .dockerignore delete mode 100644 test/integration-config.js create mode 100644 test/integration/config.js create mode 100644 test/integration/helpers/api.js delete mode 100644 test/integration/helpers/transferData.js create mode 100644 test/integration/helpers/utils.js rename test/integration/{ => settlement_deferred_net_scenario}/settlementTransfer.test.js (96%) create mode 100644 test/integration/settlement_deferred_net_scenario/settlementTransferData.js diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..8c99980a --- /dev/null +++ b/.dockerignore @@ -0,0 +1,16 @@ +deploy/ +coverage/ +node_modules/ +.dockerignore +.editorconfig +.git/ +.gitignore +.istanbul.yml +circle.yml +docker-compose.circle.yml +docker-compose.dev.yml +docker-compose.functional.yml +docker-compose.yml +Dockerfile +LICENSE +sonar-project.properties diff --git a/audit-resolve.json b/audit-resolve.json index a79919e7..663a2cbc 100644 --- a/audit-resolve.json +++ b/audit-resolve.json @@ -1,224 +1,279 @@ { "decisions": { "1523|@mojaloop/central-ledger>@mojaloop/central-object-store>@mojaloop/central-services-logger>winston>async>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253075, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-ledger>@mojaloop/central-services-health>@mojaloop/central-services-logger>winston>async>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253075, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-ledger>@mojaloop/central-services-health>@mojaloop/central-services-shared>@mojaloop/central-services-logger>winston>async>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253075, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-ledger>@mojaloop/central-services-logger>winston>async>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253075, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-ledger>@mojaloop/central-services-shared>@mojaloop/central-services-logger>winston>async>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253075, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-ledger>@mojaloop/central-services-stream>@mojaloop/central-services-logger>winston>async>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253075, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-ledger>@mojaloop/central-services-health>@mojaloop/central-services-shared>@mojaloop/event-sdk>@mojaloop/central-services-logger>winston>async>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-ledger>@mojaloop/central-services-health>@mojaloop/central-services-shared>@mojaloop/event-sdk>winston>async>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-ledger>@mojaloop/central-services-shared>@mojaloop/event-sdk>@mojaloop/central-services-logger>winston>async>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-ledger>@mojaloop/event-sdk>@mojaloop/central-services-logger>winston>async>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-ledger>@mojaloop/forensic-logging-client>@mojaloop/central-services-logger>winston>async>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-services-health>@mojaloop/central-services-logger>winston>async>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-services-health>@mojaloop/central-services-shared>@mojaloop/central-services-logger>winston>async>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-services-health>@mojaloop/central-services-shared>@mojaloop/event-sdk>@mojaloop/central-services-logger>winston>async>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-services-logger>winston>async>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-services-shared>@mojaloop/central-services-logger>winston>async>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-services-shared>@mojaloop/event-sdk>@mojaloop/central-services-logger>winston>async>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-services-health>@mojaloop/central-services-shared>@mojaloop/event-sdk>winston>async>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-services-shared>@mojaloop/event-sdk>winston>async>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-services-stream>@mojaloop/central-services-logger>winston>async>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-ledger>@mojaloop/central-services-database>knex>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-services-database>knex>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-ledger>knex>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-ledger>@mojaloop/central-services-database>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-services-database>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-ledger>@mojaloop/central-services-error-handling>@mojaloop/sdk-standard-components>request-promise-native>request-promise-core>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-ledger>@mojaloop/central-services-health>@mojaloop/central-services-error-handling>@mojaloop/sdk-standard-components>request-promise-native>request-promise-core>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-ledger>@mojaloop/central-services-health>@mojaloop/central-services-shared>@mojaloop/central-services-error-handling>@mojaloop/sdk-standard-components>request-promise-native>request-promise-core>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-ledger>@mojaloop/central-services-shared>@mojaloop/central-services-error-handling>@mojaloop/sdk-standard-components>request-promise-native>request-promise-core>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-ledger>@mojaloop/central-services-stream>@mojaloop/central-services-error-handling>@mojaloop/sdk-standard-components>request-promise-native>request-promise-core>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-services-stream>@mojaloop/central-services-error-handling>@mojaloop/sdk-standard-components>request-promise-native>request-promise-core>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-ledger>@mojaloop/central-services-error-handling>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-ledger>@mojaloop/central-services-health>@mojaloop/central-services-error-handling>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-ledger>@mojaloop/central-services-health>@mojaloop/central-services-shared>@mojaloop/central-services-error-handling>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-ledger>@mojaloop/central-services-shared>@mojaloop/central-services-error-handling>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-ledger>@mojaloop/central-services-stream>@mojaloop/central-services-error-handling>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-ledger>@mojaloop/central-services-health>@mojaloop/central-services-shared>@mojaloop/event-sdk>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-ledger>@mojaloop/central-services-health>@mojaloop/central-services-shared>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-ledger>@mojaloop/central-services-shared>@mojaloop/event-sdk>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-ledger>@mojaloop/event-sdk>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-ledger>@mojaloop/central-services-shared>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-ledger>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-services-error-handling>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-services-health>@mojaloop/central-services-error-handling>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-services-health>@mojaloop/central-services-shared>@mojaloop/central-services-error-handling>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-services-shared>@mojaloop/central-services-error-handling>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-services-health>@mojaloop/central-services-shared>@mojaloop/event-sdk>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-services-health>@mojaloop/central-services-shared>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-services-health>@mojaloop/central-services-shared>openapi-backend>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-services-health>@mojaloop/central-services-shared>openapi-backend>mock-json-schema>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-services-shared>openapi-backend>mock-json-schema>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-services-shared>@mojaloop/event-sdk>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-services-shared>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-services-shared>openapi-backend>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 }, "1523|@mojaloop/central-services-stream>@mojaloop/central-services-error-handling>lodash": { - "decision": "postpone", - "madeAt": 1593766074456 + "decision": "ignore", + "madeAt": 1594217253076, + "expiresAt": 1594822043578 } }, "rules": {}, diff --git a/package-lock.json b/package-lock.json index 253d3a71..def65635 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2097,9 +2097,9 @@ } }, "@types/node": { - "version": "13.13.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.12.tgz", - "integrity": "sha512-zWz/8NEPxoXNT9YyF2osqyA9WjssZukYpgI4UYZpOjcyqwIUqWGkcCionaEb9Ki+FULyPyvNFpg/329Kd2/pbw==" + "version": "13.13.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.13.tgz", + "integrity": "sha512-UfvBE9oRCAJVzfR+3eWm/sdLFe/qroAPEXP3GPJ1SehQiEVgZT6NQZWYbPMiJ3UdcKM06v4j+S1lTcdWCmw+3g==" }, "ajv": { "version": "6.12.2", @@ -8504,12 +8504,6 @@ } } }, - "node-fetch": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", - "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==", - "dev": true - }, "node-gyp": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-6.1.0.tgz", diff --git a/package.json b/package.json index 7483cfab..d96d09ca 100644 --- a/package.json +++ b/package.json @@ -54,11 +54,11 @@ }, "devDependencies": { "@hapi/joi": "17.1.1", + "axios": "0.19.2", "bluebird": "3.7.2", "eslint": "7.4.0", "faucet": "0.0.1", "get-port": "5.1.1", - "node-fetch": "2.6.0", "nodemon": "2.0.4", "npm-audit-resolver": "2.2.0", "npm-check-updates": "6.0.1", diff --git a/test/integration-config.js b/test/integration-config.js deleted file mode 100644 index ef722c40..00000000 --- a/test/integration-config.js +++ /dev/null @@ -1,12 +0,0 @@ -const config = { - CENTRAL_LEDGER_HOST: process.env.CENTRAL_LEDGER_HOST || 'localhost', - CENTRAL_LEDGER_PORT: process.env.CENTRAL_LEDGER_PORT || '3001', - ML_API_ADAPTER_HOST: process.env.ML_API_ADAPTER_HOST || 'localhost', - ML_API_ADAPTER_PORT: process.env.ML_API_ADAPTER_PORT || '3000', - SIMULATOR_HOST: process.env.SIMULATOR_HOST || 'localhost', - SIMULATOR_PORT: process.env.SIMULATOR_PORT || '8444', - SIMULATOR_REMOTE_HOST: process.env.SIMULATOR_REMOTE_HOST || 'localhost', - SIMULATOR_REMOTE_PORT: process.env.SIMULATOR_REMOTE_PORT || '8444' -} - -module.exports = config diff --git a/test/integration/config.js b/test/integration/config.js new file mode 100644 index 00000000..1904b768 --- /dev/null +++ b/test/integration/config.js @@ -0,0 +1,28 @@ +const config = { + URI_PREFIX: 'http', + CENTRAL_LEDGER_HOST: process.env.CENTRAL_LEDGER_HOST || 'localhost', + CENTRAL_LEDGER_PORT: process.env.CENTRAL_LEDGER_PORT || '3001', + CENTRAL_LEDGER_BASE: '', + ML_API_ADAPTER_HOST: process.env.ML_API_ADAPTER_HOST || 'localhost', + ML_API_ADAPTER_PORT: process.env.ML_API_ADAPTER_PORT || '3000', + ML_API_ADAPTER_BASE: '', + SIMULATOR_HOST: process.env.SIMULATOR_HOST || 'localhost', + SIMULATOR_PORT: process.env.SIMULATOR_PORT || '8444', + SIMULATOR_CORR_ENDPOINT: '/payeefsp/correlationid', + SIMULATOR_REMOTE_HOST: process.env.SIMULATOR_REMOTE_HOST || 'simulator-int', + SIMULATOR_REMOTE_PORT: process.env.SIMULATOR_REMOTE_PORT || '8444', + get CENTRAL_LEDGER_URL () { + return `${this.URI_PREFIX}://${this.CENTRAL_LEDGER_HOST}:${this.CENTRAL_LEDGER_PORT}${this.CENTRAL_LEDGER_BASE}` + }, + get SIMULATOR_URL () { + return `${this.URI_PREFIX}://${this.SIMULATOR_REMOTE_HOST}:${this.SIMULATOR_REMOTE_PORT}` + }, + get ML_API_ADAPTER_URL () { + return `${this.URI_PREFIX}://${this.ML_API_ADAPTER_HOST}:${this.ML_API_ADAPTER_PORT}${this.ML_API_ADAPTER_BASE}` + }, + get SIMULATOR_HOST_URL () { + return `${this.URI_PREFIX}://${this.SIMULATOR_HOST}:${this.SIMULATOR_PORT}${this.SIMULATOR_CORR_ENDPOINT}` + } +} + +module.exports = config diff --git a/test/integration/helpers/api.js b/test/integration/helpers/api.js new file mode 100644 index 00000000..836293f4 --- /dev/null +++ b/test/integration/helpers/api.js @@ -0,0 +1,143 @@ +/***** + 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 + - Claudio Viola + -------------- + ******/ +'use strict' + +const Config = require('../config') +const axios = require('axios') +const Utils = require('./utils') +const Logger = require('@mojaloop/central-services-logger') + +async function getParticipantAccount (currency) { + const url = `${Config.CENTRAL_LEDGER_URL}/participants/Hub/accounts?currency=${currency}` + const res = await axios.get(url) + return res.data +} + +async function createParticipantAccount (currency, type) { + const url = `${Config.CENTRAL_LEDGER_URL}/participants/Hub/accounts` + const body = { + currency, + type + } + return axios.post(url, body) +} + +async function addParticipant (currency, fspName) { + const url = `${Config.CENTRAL_LEDGER_URL}/participants` + return axios.post(url, { + name: fspName, + currency + }) +} + +async function addParticipantEndpoint (participant, endpointType, endpoint) { + const url = `${Config.CENTRAL_LEDGER_URL}/participants/${participant}/endpoints` + const body = { + type: endpointType, + value: endpoint + } + return axios.post(url, body) +} + +async function createNetDebitCapInitialPositionAndLimit (participant, initialPosition, currency, limitValue) { + const url = `${Config.CENTRAL_LEDGER_URL}/participants/${participant}/initialPositionAndLimits` + return axios.post(url, { + currency, + limit: { + type: 'NET_DEBIT_CAP', + value: limitValue + }, + initialPosition: initialPosition + }) +} + +async function sendTransfer (payerFsp, payeeFsp, transfer) { + const url = `${Config.ML_API_ADAPTER_URL}/transfers` + const currentDateGMT = new Date().toGMTString() + const expirationDate = new Date((new Date()).getTime() + (24 * 60 * 60 * 1000)) + + const headers = { + Accept: 'application/vnd.interoperability.transfers+json;version=1.0', + 'Content-Type': 'application/vnd.interoperability.transfers+json;version=1.0', + Date: currentDateGMT, + 'FSPIOP-Source': payerFsp, + 'FSPIOP-Destination': payeeFsp + } + const body = { + transferId: transfer.transferId, + payerFsp, + payeeFsp, + amount: transfer.amount, + ilpPacket: transfer.ilpPacket, + condition: transfer.ilpCondition, + expiration: expirationDate.toISOString(), + extensionList: { + extension: [{ + key: 'prepare', + value: 'description' + }] + } + } + return axios.post(url, body, { + headers: headers + }) +} + +async function waitForTransferToBeCommited (transferId, sleepMs, iterations) { + const localEnum = { + transferStates: { + COMMITTED: 'COMMITTED' + } + } + const url = `${Config.SIMULATOR_HOST_URL}/${transferId}` + for (let i = 0; i < iterations; i++) { + Logger.info(`Waiting for transfer ${transferId} to be committed...`) + try { + const simulatorResponse = await axios.get(url) + if (simulatorResponse.data && simulatorResponse.data.transferState === localEnum.transferStates.COMMITTED) { + return + } + } catch (err) { + if (err.type === 'invalid-json') { + Logger.info(`Transfer not processed yet. Awaiting ${sleepMs} ms...`) + } else { + Logger.info(err.message) + throw err + } + } + await Utils.sleep(sleepMs) + } + throw new Error('Transfer did not commit in time') +} + +module.exports = { + addParticipant, + addParticipantEndpoint, + createNetDebitCapInitialPositionAndLimit, + createParticipantAccount, + getParticipantAccount, + sendTransfer, + waitForTransferToBeCommited +} diff --git a/test/integration/helpers/models.js b/test/integration/helpers/models.js index 46e58c85..aace0227 100644 --- a/test/integration/helpers/models.js +++ b/test/integration/helpers/models.js @@ -33,6 +33,9 @@ module.exports = { settlementModel: { create: async (record) => { return Db.settlementModel.insert(record) + }, + truncate: async (record) => { + return Db.settlementModel.truncate() } }, settlementWindowContent: { diff --git a/test/integration/helpers/transferData.js b/test/integration/helpers/transferData.js deleted file mode 100644 index a44807aa..00000000 --- a/test/integration/helpers/transferData.js +++ /dev/null @@ -1,451 +0,0 @@ -/***** - 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 - - Georgi Georgiev - -------------- - ******/ - -'use strict' - -const Test = require('tapes')(require('tape')) -const Sinon = require('sinon') -const TestConfig = require('../../integration-config') -const Logger = require('@mojaloop/central-services-logger') -const fetch = require('node-fetch') -const Uuid = require('uuid4') -const transferParticipantStateChangeService = require('../../../src/domain/transferParticipantStateChange') -const SettlementModelModel = require('../../../src/models/settlement/settlementModel') -const Models = require('./models') - -const rand8 = () => { - return Math.floor(Math.random() * 1000000000) -} -const sleep = (ms) => { - return new Promise(resolve => { - setTimeout(resolve, ms) - }) -} -const currencies = ['USD', 'TZS'] - -const settlementModels = [ - { - name: 'DEFERRED_NET', - settlementGranularityId: 2, // NET - settlementInterchangeId: 2, // MULTILATERAL - settlementDelayId: 2, // DEFERRED - ledgerAccountTypeId: 1, // POSITION - autoPositionReset: true, - currencyId: null - }, - { - name: 'DEFERRED_NET_USD', - settlementGranularityId: 2, // NET - settlementInterchangeId: 2, // MULTILATERAL - settlementDelayId: 2, // DEFERRED - ledgerAccountTypeId: 1, // POSITION - autoPositionReset: true, - currencyId: 'USD' - } -] - -/** - * The following services must be running: - * central-ledger, ml-api-adapter, simulator, mysql, kafka - */ -module.exports = { - currencies, - setup: () => { - Test('PrepareTransferData should', prepareTransferDataTest => { - const URI_PREFIX = 'http' - const CENTRAL_LEDGER_HOST = TestConfig.CENTRAL_LEDGER_HOST - const CENTRAL_LEDGER_PORT = TestConfig.CENTRAL_LEDGER_PORT - const CENTRAL_LEDGER_BASE = '' - const ML_API_ADAPTER_HOST = TestConfig.ML_API_ADAPTER_HOST - const ML_API_ADAPTER_PORT = TestConfig.ML_API_ADAPTER_PORT - const ML_API_ADAPTER_BASE = '' - const SIMULATOR_REMOTE_HOST = TestConfig.SIMULATOR_REMOTE_HOST - const SIMULATOR_REMOTE_PORT = TestConfig.SIMULATOR_REMOTE_PORT - const SIMULATOR_HOST = TestConfig.SIMULATOR_HOST - const SIMULATOR_PORT = TestConfig.SIMULATOR_PORT - const SIMULATOR_CORR_ENDPOINT = '/payeefsp/correlationid' - const payerFsp = `fsp${rand8()}` - const payeeFsp = `fsp${rand8()}` - const fspList = [ - { - fspName: payerFsp, - endpointBase: `${URI_PREFIX}://${SIMULATOR_REMOTE_HOST}:${SIMULATOR_REMOTE_PORT}/payerfsp` - }, - { - fspName: payeeFsp, - endpointBase: `${URI_PREFIX}://${SIMULATOR_REMOTE_HOST}:${SIMULATOR_REMOTE_PORT}/payeefsp` - } - ] - const currencies = ['USD', 'TZS'] - const transfers = [] - for (const currency of currencies) { - transfers.push({ - transferId: Uuid(), - amount: { - amount: (10 + Math.floor(Math.random() * 9000) / 100).toString().substr(0, 5), // transfer amount between 10.00 and 100 - currency - }, - ilpPacket: 'AYIC9AAAAAAAABdwHWcucGF5ZWVmc3AubXNpc2RuLjIyNTU2OTk5MTI1ggLKZXlKMGNtRnVjMkZqZEdsdmJrbGtJam9pTXpFek16SmtNamN0TnpRM1lpMDBPVGs1TFRnd09USXROak01T1dJM1pEa3hZakU0SWl3aWNYVnZkR1ZKWkNJNkltUTVZVEZqT1RWa0xUUmxaall0TkdFeU5DMWhObU5pTFdJek5HSTFPRFEzT1RNeU1pSXNJbkJoZVdWbElqcDdJbkJoY25SNVNXUkpibVp2SWpwN0luQmhjblI1U1dSVWVYQmxJam9pVFZOSlUwUk9JaXdpY0dGeWRIbEpaR1Z1ZEdsbWFXVnlJam9pTWpJMU5UWTVPVGt4TWpVaUxDSm1jM0JKWkNJNkluQmhlV1ZsWm5Od0luMTlMQ0p3WVhsbGNpSTZleUp3WVhKMGVVbGtTVzVtYnlJNmV5SndZWEowZVVsa1ZIbHdaU0k2SWsxVFNWTkVUaUlzSW5CaGNuUjVTV1JsYm5ScFptbGxjaUk2SWpJeU5UQTNNREE0TVRneElpd2labk53U1dRaU9pSndZWGxsY21aemNDSjlMQ0p3WlhKemIyNWhiRWx1Wm04aU9uc2lZMjl0Y0d4bGVFNWhiV1VpT25zaVptbHljM1JPWVcxbElqb2lUV0YwY3lJc0lteGhjM1JPWVcxbElqb2lTR0ZuYldGdUluMHNJbVJoZEdWUFprSnBjblJvSWpvaU1UazRNeTB4TUMweU5TSjlmU3dpWVcxdmRXNTBJanA3SW1GdGIzVnVkQ0k2SWpZd0lpd2lZM1Z5Y21WdVkza2lPaUpWVTBRaWZTd2lkSEpoYm5OaFkzUnBiMjVVZVhCbElqcDdJbk5qWlc1aGNtbHZJam9pVkZKQlRsTkdSVklpTENKcGJtbDBhV0YwYjNJaU9pSlFRVmxGVWlJc0ltbHVhWFJwWVhSdmNsUjVjR1VpT2lKRFQwNVRWVTFGVWlKOWZRAA', - ilpCondition: 'u1cSTBLEZ03awvrLHWaQjCnd3GAB9_17Y2WhGdvepjk' - }) - } - const localEnum = { - transferStates: { - COMMITTED: 'COMMITTED' - } - } - const sleepMilliseconds = 1000 - - let sandbox - prepareTransferDataTest.beforeEach(test => { - sandbox = Sinon.createSandbox() - test.end() - }) - prepareTransferDataTest.afterEach(test => { - sandbox.restore() - test.end() - }) - - prepareTransferDataTest.test('init settlement models for integration testing:', async test => { - try { - for (const model of settlementModels) { - const record = await SettlementModelModel.getByName(model.name) - if (record && record.name === model.name) { - model.settlementModelId = record.settlementModelId - test.pass(`Settlement model ${model.name} already exists`) - } else { - const id = await Models.settlementModel.create(model) - const record1 = await SettlementModelModel.getByName(model.name) - if (record1 && record1.name === model.name && record1.settlementModelId === id) { - model.settlementModelId = id - test.pass(`Settlement model ${model.name} has been successfully inserted with id = ${id}`) - } else { - throw new Error(`Settlement model ${model.name} could not be instantiated`) - } - } - } - test.end() - } catch (err) { - Logger.error(`settlementTransferTest failed with error - ${err}`) - test.fail() - test.end() - } - }) - - prepareTransferDataTest.test('check if Hub accounts exists', async test => { - try { - for (const currency of currencies) { - const url = `${URI_PREFIX}://${CENTRAL_LEDGER_HOST}:${CENTRAL_LEDGER_PORT}${CENTRAL_LEDGER_BASE}/participants/Hub/accounts?currency=${currency}` - const opts = { method: 'GET' } - const res = await fetch(url, opts) - test.equal(res.status, 200, 'returned 200 OK') - - const response = await res.json() - let hubReconciliationAccountExists = false - let hubMLNSAccountExists = false - if (response && response.length) { - hubReconciliationAccountExists = response.findIndex(account => { - return account.ledgerAccountType === 'HUB_RECONCILIATION' - }) >= 0 - hubMLNSAccountExists = response.findIndex(account => { - return account.ledgerAccountType === 'HUB_MULTILATERAL_SETTLEMENT' - }) >= 0 - } - - if (hubReconciliationAccountExists) { - test.pass(`${currency} HUB_RECONCILIATION found`) - } else { - try { - const url = `${URI_PREFIX}://${CENTRAL_LEDGER_HOST}:${CENTRAL_LEDGER_PORT}${CENTRAL_LEDGER_BASE}/participants/Hub/accounts` - const headers = { - 'Content-Type': 'application/json' - } - const body = { - currency, - type: 'HUB_RECONCILIATION' - } - const opts = { - method: 'POST', - headers, - body: JSON.stringify(body) - } - const res = await fetch(url, opts) - test.equal(res.status, 201, 'returned 201 Created') - } catch (err) { - Logger.error(`creating HUB_RECONCILIATION failed with error - ${err}`) - test.fail() - } - } - - if (hubMLNSAccountExists) { - test.pass(`${currency} HUB_MULTILATERAL_SETTLEMENT found`) - } else { - try { - const url = `${URI_PREFIX}://${CENTRAL_LEDGER_HOST}:${CENTRAL_LEDGER_PORT}${CENTRAL_LEDGER_BASE}/participants/Hub/accounts` - const headers = { - 'Content-Type': 'application/json' - } - const body = { - currency, - type: 'HUB_MULTILATERAL_SETTLEMENT' - } - const opts = { - method: 'POST', - headers, - body: JSON.stringify(body) - } - const res = await fetch(url, opts) - test.equal(res.status, 201, 'returned 201 Created') - } catch (err) { - Logger.error(`creating HUB_MULTILATERAL_SETTLEMENT failed with error - ${err}`) - test.fail() - } - } - } - test.end() - } catch (err) { - Logger.error(`prepareTransferDataTest failed with error - ${err}`) - test.fail() - test.end() - } - }) - - prepareTransferDataTest.test('add participant and participant account', async test => { - try { - for (const currency of currencies) { - for (const fsp of fspList) { - const url = `${URI_PREFIX}://${CENTRAL_LEDGER_HOST}:${CENTRAL_LEDGER_PORT}${CENTRAL_LEDGER_BASE}/participants` - const headers = { - 'Content-Type': 'application/json' - } - const body = { - name: fsp.fspName, - currency - } - const opts = { - method: 'POST', - headers, - body: JSON.stringify(body) - } - const res = await fetch(url, opts) - test.equal(res.status, 201, `returned 201 Created for ${fsp.fspName}`) - } - } - test.end() - } catch (err) { - Logger.error(`prepareTransferDataTest failed with error - ${err}`) - test.fail() - test.end() - } - }) - - prepareTransferDataTest.test('add participant account limits', async test => { - try { - for (const currency of currencies) { - for (const fsp of fspList) { - const url = `${URI_PREFIX}://${CENTRAL_LEDGER_HOST}:${CENTRAL_LEDGER_PORT}${CENTRAL_LEDGER_BASE}/participants/${fsp.fspName}/initialPositionAndLimits` - const headers = { - 'Content-Type': 'application/json' - } - const body = { - currency, - limit: { - type: 'NET_DEBIT_CAP', - value: 1000 - }, - initialPosition: 0 - } - const opts = { - method: 'POST', - headers, - body: JSON.stringify(body) - } - const res = await fetch(url, opts) - test.equal(res.status, 201, `returned 201 created limits for ${fsp.fspName}`) - } - } - test.end() - } catch (err) { - Logger.error(`prepareTransferDataTest failed with error - ${err}`) - test.fail() - test.end() - } - }) - - prepareTransferDataTest.test('add participant FSPIOP_CALLBACK_URL_TRANSFER_POST endpoint', async test => { - try { - const headers = { - 'Content-Type': 'application/json' - } - for (const fsp of fspList) { - const url = `${URI_PREFIX}://${CENTRAL_LEDGER_HOST}:${CENTRAL_LEDGER_PORT}${CENTRAL_LEDGER_BASE}/participants/${fsp.fspName}/endpoints` - const body = { - type: 'FSPIOP_CALLBACK_URL_TRANSFER_POST', - value: `${fsp.endpointBase}/transfers` - } - const opts = { - method: 'POST', - headers, - body: JSON.stringify(body) - } - const res = await fetch(url, opts) - test.equal(res.status, 201, `returned 201 created endpoint for ${fsp.fspName}`) - } - test.end() - } catch (err) { - Logger.error(`prepareTransferDataTest failed with error - ${err}`) - test.fail() - test.end() - } - }) - - prepareTransferDataTest.test('add participant FSPIOP_CALLBACK_URL_TRANSFER_PUT endpoint', async test => { - const headers = { - 'Content-Type': 'application/json' - } - for (const fsp of fspList) { - try { - const url = `${URI_PREFIX}://${CENTRAL_LEDGER_HOST}:${CENTRAL_LEDGER_PORT}${CENTRAL_LEDGER_BASE}/participants/${fsp.fspName}/endpoints` - const body = { - type: 'FSPIOP_CALLBACK_URL_TRANSFER_PUT', - value: `${fsp.endpointBase}/transfers/{{transferId}}` - } - const opts = { - method: 'POST', - headers, - body: JSON.stringify(body) - } - const res = await fetch(url, opts) - test.equal(res.status, 201, `returned 201 created endpoint for ${fsp.fspName}`) - } catch (err) { - Logger.error(`prepareTransferDataTest failed with error - ${err}`) - test.fail() - test.end() - } - } - test.end() - }) - - prepareTransferDataTest.test('create FSPIOP_CALLBACK_URL_TRANSFER_ERROR endpoint', async test => { - const headers = { - 'Content-Type': 'application/json' - } - for (const fsp of fspList) { - try { - const url = `${URI_PREFIX}://${CENTRAL_LEDGER_HOST}:${CENTRAL_LEDGER_PORT}${CENTRAL_LEDGER_BASE}/participants/${fsp.fspName}/endpoints` - const body = { - type: 'FSPIOP_CALLBACK_URL_TRANSFER_ERROR', - value: `${fsp.endpointBase}/transfers/{{transferId}}/error` - } - const opts = { - method: 'POST', - headers, - body: JSON.stringify(body) - } - const res = await fetch(url, opts) - test.equal(res.status, 201, `returned 201 created endpoint for ${fsp.fspName}`) - } catch (err) { - Logger.error(`prepareTransferDataTest failed with error - ${err}`) - test.fail() - test.end() - } - } - test.end() - }) - - for (const transfer of transfers) { - prepareTransferDataTest.test(`create a transfer for the amount of ${transfer.amount.amount} ${transfer.amount.currency}`, async test => { - const currentDateGMT = new Date().toGMTString() - const expirationDate = new Date((new Date()).getTime() + (24 * 60 * 60 * 1000)) - - const headers = { - Accept: 'application/vnd.interoperability.transfers+json;version=1.0', - 'Content-Type': 'application/vnd.interoperability.transfers+json;version=1.0', - Date: currentDateGMT, - 'FSPIOP-Source': payerFsp, - 'FSPIOP-Destination': payeeFsp - } - const url = `${URI_PREFIX}://${ML_API_ADAPTER_HOST}:${ML_API_ADAPTER_PORT}${ML_API_ADAPTER_BASE}/transfers` - const body = { - transferId: transfer.transferId, - payerFsp, - payeeFsp, - amount: transfer.amount, - ilpPacket: transfer.ilpPacket, - condition: transfer.ilpCondition, - expiration: expirationDate.toISOString(), - extensionList: { - extension: [{ - key: 'prepare', - value: 'description' - }] - } - } - const opts = { - method: 'POST', - headers, - body: JSON.stringify(body) - } - - const simulatorUrl = `${URI_PREFIX}://${SIMULATOR_HOST}:${SIMULATOR_PORT}${SIMULATOR_CORR_ENDPOINT}/${transfer.transferId}` - - try { - const res = await fetch(url, opts) - test.equal(res.status, 202, 'transfer PREPARE request returned 202 Accepted') - - let transferCommitted = false - for (let i = 0; i < 10; i++) { - const simulatorRes = await fetch(simulatorUrl) - try { - const simulatorResponse = await simulatorRes.json() - if (simulatorResponse && simulatorResponse.transferState === localEnum.transferStates.COMMITTED) { - await transferParticipantStateChangeService.processMsgFulfil(transfer.transferId, 'success', []) - transferCommitted = true - break - } - } catch (err) { - if (err.type === 'invalid-json') { - Logger.info(`Transfer not processed yet. Awaiting ${sleepMilliseconds} ms...`) - } else { - Logger.info(err.message) - throw err - } - } - await sleep(sleepMilliseconds) - } - test.ok(transferCommitted, 'transfer successfully COMMITTED by payee fsp') - test.end() - } catch (err) { - Logger.error(`prepareTransferDataTest failed with error - ${err}`) - test.fail() - test.end() - } - }) - } - - prepareTransferDataTest.end() - }) - } -} diff --git a/test/integration/helpers/utils.js b/test/integration/helpers/utils.js new file mode 100644 index 00000000..9d280341 --- /dev/null +++ b/test/integration/helpers/utils.js @@ -0,0 +1,40 @@ +/***** + 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 + - Claudio Viola + -------------- + ******/ +'use strict' + +function rand8 () { + return Math.floor(Math.random() * 1000000000) +} + +async function sleep (ms) { + return new Promise(resolve => { + setTimeout(resolve, ms) + }) +} + +module.exports = { + rand8, + sleep +} diff --git a/test/integration/settlementTransfer.test.js b/test/integration/settlement_deferred_net_scenario/settlementTransfer.test.js similarity index 96% rename from test/integration/settlementTransfer.test.js rename to test/integration/settlement_deferred_net_scenario/settlementTransfer.test.js index bb0faa75..ffd973a5 100644 --- a/test/integration/settlementTransfer.test.js +++ b/test/integration/settlement_deferred_net_scenario/settlementTransfer.test.js @@ -28,21 +28,21 @@ const Test = require('tapes')(require('tape')) const Sinon = require('sinon') const Logger = require('@mojaloop/central-services-logger') const MLNumber = require('@mojaloop/ml-number') -const TransferData = require('./helpers/transferData') -const Models = require('./helpers/models') -const Config = require('../../src/lib/config') -const Db = require('../../src/lib/db') -const SettlementWindowService = require('../../src/domain/settlementWindow') -const SettlementService = require('../../src/domain/settlement') -const Enums = require('../../src/models/lib/enums') -const SettlementWindowStateChangeModel = require('../../src/models/settlementWindow/settlementWindowStateChange') -const SettlementModel = require('../../src/models/settlement/settlement') -const SettlementStateChangeModel = require('../../src/models/settlement/settlementStateChange') -const SettlementParticipantCurrencyModel = require('../../src/models/settlement/settlementParticipantCurrency') +const SettlementTransferData = require('./settlementTransferData') +const Models = require('../helpers/models') +const Config = require('../../../src/lib/config') +const Db = require('../../../src/lib/db') +const SettlementWindowService = require('../../../src/domain/settlementWindow') +const SettlementService = require('../../../src/domain/settlement') +const Enums = require('../../../src/models/lib/enums') +const SettlementWindowStateChangeModel = require('../../../src/models/settlementWindow/settlementWindowStateChange') +const SettlementModel = require('../../../src/models/settlement/settlement') +const SettlementStateChangeModel = require('../../../src/models/settlement/settlementStateChange') +const SettlementParticipantCurrencyModel = require('../../../src/models/settlement/settlementParticipantCurrency') const TransferModel = require('@mojaloop/central-ledger/src/models/transfer/transfer') const TransferStateChangeModel = require('@mojaloop/central-ledger/src/models/transfer/transferStateChange') const ParticipantPositionModel = require('@mojaloop/central-ledger/src/models/position/participantPosition') -const Producer = require('../../src/lib/kafka/producer') +const Producer = require('../../../src/lib/kafka/producer') const StreamProducer = require('@mojaloop/central-services-stream').Util.Producer // require('leaked-handles').set({ fullStack: true, timeout: 5000, debugSockets: true }) @@ -91,10 +91,9 @@ const getEnums = async () => { } } -TransferData.setup() - Test('SettlementTransfer should', async settlementTransferTest => { await Db.connect(Config.DATABASE) + await SettlementTransferData.init() const enums = await getEnums() let settlementWindowId let settlementData @@ -126,7 +125,7 @@ Test('SettlementTransfer should', async settlementTransferTest => { test.equal(closedWindow.settlementWindowStateId, enums.settlementWindowStates.CLOSED, `window id ${settlementWindowId} is CLOSED`) test.equal(openWindow.settlementWindowStateId, enums.settlementWindowStates.OPEN, `window id ${res2.settlementWindowId} is OPEN`) - for (const currency of TransferData.currencies) { + for (const currency of SettlementTransferData.currencies) { const settlementWindowContentData = await Models.settlementWindowContent.getByParams({ settlementWindowId, currencyId: currency }) const id = settlementWindowContentData[0].settlementWindowContentId test.equal(settlementWindowContentData.length, 1, `window content id ${id} has been created`) diff --git a/test/integration/settlement_deferred_net_scenario/settlementTransferData.js b/test/integration/settlement_deferred_net_scenario/settlementTransferData.js new file mode 100644 index 00000000..4eb4ec9b --- /dev/null +++ b/test/integration/settlement_deferred_net_scenario/settlementTransferData.js @@ -0,0 +1,208 @@ +/***** + 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 + - Georgi Georgiev + - Claudio Viola + -------------- + ******/ + +'use strict' + +const Config = require('../config') +const Logger = require('@mojaloop/central-services-logger') +const Uuid = require('uuid4') +const transferParticipantStateChangeService = require('../../../src/domain/transferParticipantStateChange') +const Api = require('../helpers/api') +const Db = require('../../../src/lib/db') +const Utils = require('../helpers/utils') + +const currencies = ['USD', 'TZS'] + +const settlementModels = [ + { + name: 'DEFERRED_NET', + settlementGranularityId: 2, // NET + settlementInterchangeId: 2, // MULTILATERAL + settlementDelayId: 2, // DEFERRED + ledgerAccountTypeId: 1, // POSITION + autoPositionReset: true, + currencyId: null + }, + { + name: 'DEFERRED_NET_USD', + settlementGranularityId: 2, // NET + settlementInterchangeId: 2, // MULTILATERAL + settlementDelayId: 2, // DEFERRED + ledgerAccountTypeId: 1, // POSITION + autoPositionReset: true, + currencyId: 'USD' + } +] + +const payerFsp = `fsp${Utils.rand8()}` +const payeeFsp = `fsp${Utils.rand8()}` +const fspList = [ + { + fspName: payerFsp, + endpointBase: `${Config.SIMULATOR_URL}/payerfsp` + }, + { + fspName: payeeFsp, + endpointBase: `${Config.SIMULATOR_URL}/payeefsp` + } +] +const transfers = [] +for (const currency of currencies) { + transfers.push({ + transferId: Uuid(), + amount: { + amount: (10 + Math.floor(Math.random() * 9000) / 100).toString().substr(0, 5), // transfer amount between 10.00 and 100 + currency + }, + ilpPacket: 'AYIC9AAAAAAAABdwHWcucGF5ZWVmc3AubXNpc2RuLjIyNTU2OTk5MTI1ggLKZXlKMGNtRnVjMkZqZEdsdmJrbGtJam9pTXpFek16SmtNamN0TnpRM1lpMDBPVGs1TFRnd09USXROak01T1dJM1pEa3hZakU0SWl3aWNYVnZkR1ZKWkNJNkltUTVZVEZqT1RWa0xUUmxaall0TkdFeU5DMWhObU5pTFdJek5HSTFPRFEzT1RNeU1pSXNJbkJoZVdWbElqcDdJbkJoY25SNVNXUkpibVp2SWpwN0luQmhjblI1U1dSVWVYQmxJam9pVFZOSlUwUk9JaXdpY0dGeWRIbEpaR1Z1ZEdsbWFXVnlJam9pTWpJMU5UWTVPVGt4TWpVaUxDSm1jM0JKWkNJNkluQmhlV1ZsWm5Od0luMTlMQ0p3WVhsbGNpSTZleUp3WVhKMGVVbGtTVzVtYnlJNmV5SndZWEowZVVsa1ZIbHdaU0k2SWsxVFNWTkVUaUlzSW5CaGNuUjVTV1JsYm5ScFptbGxjaUk2SWpJeU5UQTNNREE0TVRneElpd2labk53U1dRaU9pSndZWGxsY21aemNDSjlMQ0p3WlhKemIyNWhiRWx1Wm04aU9uc2lZMjl0Y0d4bGVFNWhiV1VpT25zaVptbHljM1JPWVcxbElqb2lUV0YwY3lJc0lteGhjM1JPWVcxbElqb2lTR0ZuYldGdUluMHNJbVJoZEdWUFprSnBjblJvSWpvaU1UazRNeTB4TUMweU5TSjlmU3dpWVcxdmRXNTBJanA3SW1GdGIzVnVkQ0k2SWpZd0lpd2lZM1Z5Y21WdVkza2lPaUpWVTBRaWZTd2lkSEpoYm5OaFkzUnBiMjVVZVhCbElqcDdJbk5qWlc1aGNtbHZJam9pVkZKQlRsTkdSVklpTENKcGJtbDBhV0YwYjNJaU9pSlFRVmxGVWlJc0ltbHVhWFJwWVhSdmNsUjVjR1VpT2lKRFQwNVRWVTFGVWlKOWZRAA', + ilpCondition: 'u1cSTBLEZ03awvrLHWaQjCnd3GAB9_17Y2WhGdvepjk' + }) +} + +/** + * [init Initialise all the data required for running the scenario] + * @return {[type]} [description] + */ +async function init () { + Logger.info('Setting up initial data for settlement transfer test') + try { + Logger.info('Initializing settlement models') + await initSettlementModels() + + Logger.info('Checking that hub accounts exist') + await checkHubAccountsExist() + + Logger.info('Initializing participants') + await initParticipants() + Logger.info('Initializing participants endpoints') + + await initParticipantEndpoints() + Logger.info('Initializing participants net debit cap') + await initNetDebitCapPositionAndLimits() + Logger.info('Initializing transfers') + await initTransfers() + } catch (err) { + Logger.error(`Error setting up initial settlement data ${err}`) + } +} + +/** + * [initSettlementModels Initialize the settlement models required for the test] + * @return {[type]} [description] + */ +async function initSettlementModels () { + const knex = await Db.getKnex() + await knex.raw('SET FOREIGN_KEY_CHECKS = 0;') + await Db.settlementModel.truncate() + await knex.raw('SET FOREIGN_KEY_CHECKS = 1;') + await knex.batchInsert('settlementModel', settlementModels) +} + +/** + * [checkHubAccountsExist Checks that the right hubs exist, if not create them] + * @return {[type]} [description] + */ +async function checkHubAccountsExist () { + for (const currency of currencies) { + const response = await Api.getParticipantAccount(currency) + let hubReconciliationAccountExists = false + let hubMLNSAccountExists = false + if (response && response.length) { + hubReconciliationAccountExists = response.findIndex(account => { + return account.ledgerAccountType === 'HUB_RECONCILIATION' + }) >= 0 + hubMLNSAccountExists = response.findIndex(account => { + return account.ledgerAccountType === 'HUB_MULTILATERAL_SETTLEMENT' + }) >= 0 + } + + if (hubReconciliationAccountExists === false) { + await Api.createParticipantAccount(currency, 'HUB_RECONCILIATION') + } + if (hubMLNSAccountExists === false) { + await Api.createParticipantAccount(currency, 'HUB_MULTILATERAL_SETTLEMENT') + } + } +} + +/** + * [initParticipants creates participants for the scenario test] + * @return {[Promise]} [description] + */ +async function initParticipants () { + for (const currency of currencies) { + for (const fsp of fspList) { + await Api.addParticipant(currency, fsp.fspName) + } + } +} + +/** + * [initNetDebitCapPositionAndLimits Initialize participant net debit cap and initial position for each currency] + * @return {[Promise]} [description] + */ +async function initNetDebitCapPositionAndLimits () { + for (const currency of currencies) { + for (const fsp of fspList) { + await Api.createNetDebitCapInitialPositionAndLimit(fsp.fspName, 0, currency, 1000) + } + } +} + +/** + * [initParticipantEndpoints Sets up participant endpoints] + * @return {[Promise]} [description] + */ +async function initParticipantEndpoints () { + for (const fsp of fspList) { + // reaching deadlock if doing promise.all + await Api.addParticipantEndpoint(fsp.fspName, 'FSPIOP_CALLBACK_URL_TRANSFER_POST', `${fsp.endpointBase}/transfers`) + await Api.addParticipantEndpoint(fsp.fspName, 'FSPIOP_CALLBACK_URL_TRANSFER_PUT', `${fsp.endpointBase}/transfers/{{transferId}}`) + await Api.addParticipantEndpoint(fsp.fspName, 'FSPIOP_CALLBACK_URL_TRANSFER_ERROR', `${fsp.endpointBase}/transfers/{{transferId}}/error`) + } +} + +/** + * [initTransfers Initiailize transfers for the settlement scenario] + * @return {[Promise]} [description] + */ +async function initTransfers () { + const SLEEP_MS = 1000 + for (const transfer of transfers) { + try { + await Api.sendTransfer(payerFsp, payeeFsp, transfer) + await Api.waitForTransferToBeCommited(transfer.transferId, SLEEP_MS, 10) + await transferParticipantStateChangeService.processMsgFulfil(transfer.transferId, 'success', []) + } catch (err) { + Logger.error(`prepareTransferDataTest failed with error - ${err}`) + } + } +} + +module.exports = { + currencies, + init +}