Browse Source

refactor: cleanup code, add environment configuration, add upload script and target

develop
Apostolos Fanakis 4 years ago
parent
commit
06c8e98f28
  1. 4
      packages/concordia-app/src/constants/configuration/defaults.js
  2. 10
      packages/concordia-app/src/constants/contracts/ContractNames.js
  3. 12
      packages/concordia-app/src/options/drizzleOptions.js
  4. 71
      packages/concordia-app/src/utils/drizzleUtils.js
  5. 2
      packages/concordia-contracts-provider/.gitignore
  6. 14
      packages/concordia-contracts-provider/src/constants.js
  7. 5
      packages/concordia-contracts-provider/src/controllers/download.js
  8. 14
      packages/concordia-contracts-provider/src/index.js
  9. 6
      packages/concordia-contracts-provider/src/middleware/upload.js
  10. 10
      packages/concordia-contracts-provider/src/utils/storageUtils.js
  11. 5
      packages/concordia-contracts/constants/config/defaults.js
  12. 10
      packages/concordia-contracts/package.json
  13. 31
      packages/concordia-contracts/utils/contractsProviderUtils.js
  14. 3104
      yarn.lock

4
packages/concordia-app/src/constants/configuration/defaults.js

@ -5,3 +5,7 @@ export const WEB3_PORT_SOCKET_CONNECT_MAX_ATTEMPTS_DEFAULT = 3;
export const REACT_APP_RENDEZVOUS_HOST_DEFAULT = '127.0.0.1'; export const REACT_APP_RENDEZVOUS_HOST_DEFAULT = '127.0.0.1';
export const REACT_APP_RENDEZVOUS_PORT_DEFAULT = '9090'; export const REACT_APP_RENDEZVOUS_PORT_DEFAULT = '9090';
export const REACT_APP_CONTRACTS_SUPPLIER_HOST_DEFAULT = '127.0.0.1';
export const REACT_APP_CONTRACTS_SUPPLIER_PORT_DEFAULT = '8400';
export const REACT_APP_CONTRACTS_VERSION_HASH_DEFAULT = 'latest';

10
packages/concordia-app/src/constants/contracts/ContractNames.js

@ -1,5 +1,11 @@
export const FORUM_CONTRACT = 'Forum'; export const FORUM_CONTRACT = 'Forum';
export const POST_VOTING_CONTRACT = 'PostVoting'; export const POST_VOTING_CONTRACT = 'PostVoting';
export const VOTING_CONTRACT = 'Voting'; export const VOTING_CONTRACT = 'Voting';
export const NUMBER_OF_CONTRACTS = 4;
export const NUMBER_OF_CONTRACTS = 4; const CONTRACTS = [
FORUM_CONTRACT,
POST_VOTING_CONTRACT,
VOTING_CONTRACT,
];
export default CONTRACTS;

12
packages/concordia-app/src/options/drizzleOptions.js

@ -2,7 +2,7 @@
import { contracts } from 'concordia-contracts'; import { contracts } from 'concordia-contracts';
import web3Options from './web3Options'; import web3Options from './web3Options';
import appEvents from '../constants/contracts/events'; import appEvents from '../constants/contracts/events';
import { downloadContractArtifactsSync } from '../utils/drizzleUtils'; import downloadContractArtifactsSync from '../utils/drizzleUtils';
const drizzleOptions = { const drizzleOptions = {
web3: web3Options, web3: web3Options,
@ -11,14 +11,10 @@ const drizzleOptions = {
reloadWindowOnAccountChange: true, // We need it to reinitialize breeze and create new Orbit databases reloadWindowOnAccountChange: true, // We need it to reinitialize breeze and create new Orbit databases
}; };
const CONTRACTS_SUPPLIER_URL = process.env.REACT_APP_CONTRACTS_SUPPLIER; if (process.env.REACT_APP_USE_EXTERNAL_CONTRACTS_SUPPLIER) {
drizzleOptions.contracts = downloadContractArtifactsSync();
if (!CONTRACTS_SUPPLIER_URL) {
drizzleOptions.contracts = contracts;
} else { } else {
const remoteContracts = downloadContractArtifactsSync(); drizzleOptions.contracts = contracts;
console.log(remoteContracts);
drizzleOptions.contracts = remoteContracts;
} }
export default drizzleOptions; export default drizzleOptions;

71
packages/concordia-app/src/utils/drizzleUtils.js

@ -1,47 +1,62 @@
// const downloadContractArtifacts = async () => { import {
import { NUMBER_OF_CONTRACTS } from '../constants/contracts/ContractNames'; REACT_APP_CONTRACTS_SUPPLIER_HOST_DEFAULT,
REACT_APP_CONTRACTS_SUPPLIER_PORT_DEFAULT, REACT_APP_CONTRACTS_VERSION_HASH_DEFAULT,
} from '../constants/configuration/defaults';
import CONTRACTS from '../constants/contracts/ContractNames';
function getContractsDownloadRequest() {
const CONTRACTS_SUPPLIER_HOST = process.env.REACT_APP_CONTRACTS_SUPPLIER_HOST
|| REACT_APP_CONTRACTS_SUPPLIER_HOST_DEFAULT;
const CONTRACTS_SUPPLIER_PORT = process.env.REACT_APP_CONTRACTS_SUPPLIER_PORT
|| REACT_APP_CONTRACTS_SUPPLIER_PORT_DEFAULT;
const CONTRACTS_VERSION_HASH = process.env.REACT_APP_CONTRACTS_VERSION_HASH
|| REACT_APP_CONTRACTS_VERSION_HASH_DEFAULT;
export const downloadContractArtifacts = async () => { const xhrRequest = new XMLHttpRequest();
const headers = new Headers();
headers.append('Access-Control-Allow-Origin', 'http://localhost:7000');
headers.append('Access-Control-Allow-Credentials', 'true');
const requestOptions = { xhrRequest.open('GET',
method: 'GET', `http://${CONTRACTS_SUPPLIER_HOST}:${CONTRACTS_SUPPLIER_PORT}/contracts/${CONTRACTS_VERSION_HASH}`,
redirect: 'follow', false);
headers, xhrRequest.setRequestHeader('Access-Control-Allow-Origin', 'http://localhost:7000');
}; xhrRequest.setRequestHeader('Access-Control-Allow-Credentials', 'true');
const remoteContracts = await fetch('http://127.0.0.1:8400/contracts/asdf', requestOptions) return xhrRequest;
.then((response) => response.text()) }
.then((contractsRawData) => JSON.parse(contractsRawData));
if (remoteContracts.length !== NUMBER_OF_CONTRACTS) { function validateRemoteContracts(remoteContracts) {
if (remoteContracts.length !== CONTRACTS.length) {
throw new Error(`Version mismatch detected. Artifacts brought ${remoteContracts.length} contracts but app throw new Error(`Version mismatch detected. Artifacts brought ${remoteContracts.length} contracts but app
expected ${NUMBER_OF_CONTRACTS}`); expected ${CONTRACTS.length}`);
} }
return remoteContracts; const contractsPresentStatus = CONTRACTS.map((contract) => ({
}; contract,
present: remoteContracts.contains((remoteContract) => remoteContract.contractName === contract),
}));
if (contractsPresentStatus.reduce((accumulator, contract) => accumulator && contract.present, true)) {
throw new Error(`Contracts missing from artifacts. Supplier didn't bring ${contractsPresentStatus
.filter((contractPresentStatus) => contractPresentStatus.present === false)
.map((contractPresentStatus) => contractPresentStatus.contract)
.join(', ')}.`);
}
}
const downloadContractArtifactsSync = () => {
const xhrRequest = getContractsDownloadRequest();
export const downloadContractArtifactsSync = () => {
const xhrRequest = new XMLHttpRequest();
// xhrRequest.withCredentials = true;
xhrRequest.open('GET', 'http://127.0.0.1:8400/contracts/asdf', false);
xhrRequest.setRequestHeader('Access-Control-Allow-Origin', 'http://localhost:7000');
xhrRequest.setRequestHeader('Access-Control-Allow-Credentials', 'true');
xhrRequest.send(null); xhrRequest.send(null);
if (xhrRequest.status === 200) { if (xhrRequest.status === 200) {
const contractsRawData = xhrRequest.responseText; const contractsRawData = xhrRequest.responseText;
const remoteContracts = JSON.parse(contractsRawData); const remoteContracts = JSON.parse(contractsRawData);
if (remoteContracts.length !== NUMBER_OF_CONTRACTS) { validateRemoteContracts(remoteContracts);
throw new Error(`Version mismatch detected. Artifacts brought ${remoteContracts.length} contracts but app
expected ${NUMBER_OF_CONTRACTS}`);
}
return remoteContracts; return remoteContracts;
} }
throw new Error(`Remote contract artifacts download request failed!\n${xhrRequest.responseText}`); throw new Error(`Remote contract artifacts download request failed!\n${xhrRequest.responseText}`);
}; };
export default downloadContractArtifactsSync;

2
packages/concordia-contracts-provider/.gitignore

@ -20,3 +20,5 @@ yarn-error.log*
.env.development.local .env.development.local
.env.test.local .env.test.local
.env.production.local .env.production.local
contracts-uploads

14
packages/concordia-contracts-provider/src/constants.js

@ -1,3 +1,11 @@
export const API_HOST = '127.0.0.1'; import path from 'path';
export const API_PORT = '8400';
export const UPLOADED_CONTRACTS_DIR = './contracts-uploads/'; const PROVIDER_PORT = '8400';
const UPLOAD_CONTRACTS_DIRECTORY = path.join(__dirname, '..', 'contracts-uploads');
const CORS_ALLOWED_ORIGINS = ['localhost:7000', '127.0.0.1:7000'];
export default {
port: PROVIDER_PORT,
uploadsDirectory: UPLOAD_CONTRACTS_DIRECTORY,
corsAllowedOrigins: CORS_ALLOWED_ORIGINS,
};

5
packages/concordia-contracts-provider/src/controllers/download.js

@ -1,10 +1,11 @@
import * as fs from 'fs'; import * as fs from 'fs';
import path from 'path'; import path from 'path';
import { UPLOADED_CONTRACTS_DIR } from '../constants'; import getStorageLocation from '../utils/storageUtils';
const downloadContracts = async (req, res) => { const downloadContracts = async (req, res) => {
const { params: { hash } } = req; const { params: { hash } } = req;
const directoryPath = path.join(`${__dirname}/../../${UPLOADED_CONTRACTS_DIR}/${hash}`); const directoryPath = getStorageLocation(hash);
const contracts = []; const contracts = [];
fs.readdirSync(directoryPath).forEach((contractFilename) => { fs.readdirSync(directoryPath).forEach((contractFilename) => {

14
packages/concordia-contracts-provider/src/index.js

@ -1,12 +1,17 @@
import express from 'express'; import express from 'express';
import cors from 'cors'; import cors from 'cors';
import initRoutes from './routes/web'; import initRoutes from './routes/web';
import { API_HOST, API_PORT } from './constants'; import constants from './constants';
const PROVIDER_PORT = process.env.CONTRACTS_PROVIDER_PORT || constants.port;
const ALLOWED_ORIGINS = process.env.CORS_ALLOWED_ORIGINS
? process.env.CORS_ALLOWED_ORIGINS.split(';')
: constants.corsAllowedOrigins;
const app = express(); const app = express();
const corsOptions = { const corsOptions = {
origin: ['localhost:7000', '127.0.0.1:7000', 'http://localhost:7000'], origin: ALLOWED_ORIGINS,
optionsSuccessStatus: 200, // some legacy browsers (IE11, various SmartTVs) choke on 204 optionsSuccessStatus: 200, // some legacy browsers (IE11, various SmartTVs) choke on 204
}; };
@ -14,6 +19,7 @@ app.use(express.urlencoded({ extended: true }));
app.use(cors(corsOptions)); app.use(cors(corsOptions));
initRoutes(app); initRoutes(app);
app.listen(API_PORT, () => {
console.log(`Contracts provider listening at http://${API_HOST}:${API_PORT}`); app.listen(PROVIDER_PORT, () => {
console.log(`Contracts provider listening at http://127.0.0.1:${PROVIDER_PORT}`);
}); });

6
packages/concordia-contracts-provider/src/middleware/upload.js

@ -1,17 +1,15 @@
import * as util from 'util'; import * as util from 'util';
import * as path from 'path';
import * as fs from 'fs'; import * as fs from 'fs';
import multer from 'multer'; import multer from 'multer';
import { UPLOADED_CONTRACTS_DIR } from '../constants'; import getStorageLocation from '../utils/storageUtils';
const storage = multer.diskStorage({ const storage = multer.diskStorage({
destination: (req, file, callback) => { destination: (req, file, callback) => {
const { params: { hash } } = req; const { params: { hash } } = req;
const contractsPath = path.join(`${__dirname}/../../${UPLOADED_CONTRACTS_DIR}/${hash}`); const contractsPath = getStorageLocation(hash);
fs.mkdirSync(contractsPath, { recursive: true }); fs.mkdirSync(contractsPath, { recursive: true });
callback(null, contractsPath); callback(null, contractsPath);
// callback(null, UPLOADED_CONTRACTS_DIR);
}, },
filename: (req, file, callback) => { filename: (req, file, callback) => {
const match = ['application/json']; const match = ['application/json'];

10
packages/concordia-contracts-provider/src/utils/storageUtils.js

@ -0,0 +1,10 @@
import path from 'path';
import constants from '../constants';
const getStorageLocation = (hash) => {
const UPLOADS_DIRECTORY = process.env.UPLOAD_CONTRACTS_DIRECTORY || constants.uploadsDirectory;
return path.join(UPLOADS_DIRECTORY, hash);
};
export default getStorageLocation;

5
packages/concordia-contracts/constants/config/defaults.js

@ -4,6 +4,9 @@ const DEVELOP_CHAIN_PORT_DEFAULT = '8545';
const TEST_CHAIN_HOST_DEFAULT = '127.0.0.1'; const TEST_CHAIN_HOST_DEFAULT = '127.0.0.1';
const TEST_CHAIN_PORT_DEFAULT = '8546'; const TEST_CHAIN_PORT_DEFAULT = '8546';
const CONTRACTS_PROVIDER_HOST_DEFAULT = '127.0.0.1';
const CONTRACTS_PROVIDER_PORT_DEFAULT = '8400';
module.exports = { module.exports = {
develop: { develop: {
chainHost: DEVELOP_CHAIN_HOST_DEFAULT, chainHost: DEVELOP_CHAIN_HOST_DEFAULT,
@ -13,4 +16,6 @@ module.exports = {
chainHost: TEST_CHAIN_HOST_DEFAULT, chainHost: TEST_CHAIN_HOST_DEFAULT,
chainPort: TEST_CHAIN_PORT_DEFAULT, chainPort: TEST_CHAIN_PORT_DEFAULT,
}, },
contractsProviderHost: CONTRACTS_PROVIDER_HOST_DEFAULT,
contractsProviderPort: CONTRACTS_PROVIDER_PORT_DEFAULT,
}; };

10
packages/concordia-contracts/package.json

@ -10,13 +10,15 @@
"_eslint": "yarn eslint . --format table", "_eslint": "yarn eslint . --format table",
"_solhint": "yarn solhint --formatter table contracts/*.sol test/*.sol", "_solhint": "yarn solhint --formatter table contracts/*.sol test/*.sol",
"test": "yarn truffle test", "test": "yarn truffle test",
"migrate": "yarn _migrate --network develop", "migrate": "yarn _migrate --network develop && yarn upload",
"migrate-reset": "yarn _migrate --network develop --reset", "migrate-reset": "yarn _migrate --network develop --reset && yarn upload",
"_migrate": "yarn truffle migrate" "_migrate": "yarn truffle migrate",
"upload": "node ./utils/contractsProviderUtils.js $npm_package_version"
}, },
"dependencies": { "dependencies": {
"@openzeppelin/contracts": "~3.2.0", "@openzeppelin/contracts": "~3.2.0",
"truffle": "~5.1.55" "truffle": "~5.1.55",
"unirest": "^0.6.0"
}, },
"devDependencies": { "devDependencies": {
"eslint": "^6.8.0", "eslint": "^6.8.0",

31
packages/concordia-contracts/utils/contractsProviderUtils.js

@ -0,0 +1,31 @@
const path = require('path');
const unirest = require('unirest');
const { contracts } = require('../index');
const defaults = require('../constants/config/defaults');
const uploadContractsToProviderUnirest = (versionHash, tag) => {
const CONTRACTS_PROVIDER_HOST = process.env.CONTRACTS_PROVIDER_HOST || defaults.contractsProviderHost;
const CONTRACTS_PROVIDER_PORT = process.env.CONTRACTS_PROVIDER_PORT || defaults.contractsProviderPort;
const uploadPath = `http://${CONTRACTS_PROVIDER_HOST}:${CONTRACTS_PROVIDER_PORT}/contracts/${versionHash}`;
const req = unirest('POST', uploadPath);
contracts
.forEach((contract) => req
.attach('contracts', path.join(__dirname, '../', 'build/', `${contract.contractName}.json`)));
console.log(`Uploading to ${uploadPath}`);
req.end((res) => {
if (res.error) {
throw new Error(`Failed to upload contracts to provider: ${res.error}`);
}
console.log('Contracts uploaded to provider.');
});
};
const main = () => {
uploadContractsToProviderUnirest(process.argv[2], process.argv[3]);
};
main();

3104
yarn.lock

File diff suppressed because it is too large
Loading…
Cancel
Save