Contract Build Improvements (#215)
This commit is contained in:
parent
0496b58130
commit
f8910b1e09
|
@ -1 +1,2 @@
|
||||||
.idea
|
.idea
|
||||||
|
contract/build
|
12
.travis.yml
12
.travis.yml
|
@ -2,7 +2,7 @@ matrix:
|
||||||
include:
|
include:
|
||||||
# Frontend
|
# Frontend
|
||||||
- language: node_js
|
- language: node_js
|
||||||
node_js: 8.11.4
|
node_js: 8.13.0
|
||||||
before_install:
|
before_install:
|
||||||
- cd frontend/
|
- cd frontend/
|
||||||
install: yarn
|
install: yarn
|
||||||
|
@ -15,17 +15,23 @@ matrix:
|
||||||
before_install:
|
before_install:
|
||||||
- cd backend/
|
- cd backend/
|
||||||
- cp .env.example .env
|
- cp .env.example .env
|
||||||
|
env:
|
||||||
|
- FLASK_APP=app.py FLASK_DEBUG=1 CROWD_FUND_URL=https://eip-712.herokuapp.com/contract/crowd-fund
|
||||||
|
CROWD_FUND_FACTORY_URL=https://eip-712.herokuapp.com/contract/factory
|
||||||
install: pip install -r requirements/dev.txt
|
install: pip install -r requirements/dev.txt
|
||||||
script:
|
script:
|
||||||
- flask test
|
- flask test
|
||||||
# Contracts
|
# Contracts
|
||||||
- language: node_js
|
- language: node_js
|
||||||
node_js: 8.11.4
|
node_js: 8.13.0
|
||||||
before_install:
|
before_install:
|
||||||
- cd contract/
|
- cd contract/
|
||||||
install: yarn && yarn add global truffle ganache-cli
|
install: yarn && yarn add global truffle ganache-cli@6.1.8
|
||||||
before_script:
|
before_script:
|
||||||
- ganache-cli > /dev/null &
|
- ganache-cli > /dev/null &
|
||||||
- sleep 10
|
- sleep 10
|
||||||
script:
|
script:
|
||||||
- yarn run test
|
- yarn run test
|
||||||
|
env:
|
||||||
|
- CROWD_FUND_URL=https://eip-712.herokuapp.com/contract/crowd-fund
|
||||||
|
CROWD_FUND_FACTORY_URL=https://eip-712.herokuapp.com/contract/factory
|
||||||
|
|
|
@ -9,5 +9,8 @@ SENDGRID_API_KEY="optional, but emails won't send without it"
|
||||||
# for ropsten use the following
|
# for ropsten use the following
|
||||||
# ETHEREUM_ENDPOINT_URI = "https://ropsten.infura.io/API_KEY"
|
# ETHEREUM_ENDPOINT_URI = "https://ropsten.infura.io/API_KEY"
|
||||||
ETHEREUM_ENDPOINT_URI = "http://localhost:8545"
|
ETHEREUM_ENDPOINT_URI = "http://localhost:8545"
|
||||||
|
CROWD_FUND_URL = "https://eip-712.herokuapp.com/contract/crowd-fund"
|
||||||
|
CROWD_FUND_FACTORY_URL = "https://eip-712.herokuapp.com/contract/factory"
|
||||||
UPLOAD_DIRECTORY = "/tmp"
|
UPLOAD_DIRECTORY = "/tmp"
|
||||||
UPLOAD_URL = "http://localhost:5000" # for constructing download url
|
UPLOAD_URL = "http://localhost:5000" # for constructing download url
|
||||||
|
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
# Config file for automatic testing at travis-ci.org
|
|
||||||
sudo: false # http://docs.travis-ci.com/user/migrating-from-legacy/
|
|
||||||
language: python
|
|
||||||
env:
|
|
||||||
- FLASK_APP=app.py FLASK_DEBUG=1
|
|
||||||
python:
|
|
||||||
- 2.7
|
|
||||||
- 3.4
|
|
||||||
- 3.5
|
|
||||||
- 3.6
|
|
||||||
install:
|
|
||||||
- pip install -r requirements/dev.txt
|
|
||||||
- nvm install 6.10
|
|
||||||
- nvm use 6.10
|
|
||||||
- npm install
|
|
||||||
before_script:
|
|
||||||
- npm run lint
|
|
||||||
- npm run build
|
|
||||||
- flask lint
|
|
||||||
script: flask test
|
|
|
@ -15,6 +15,8 @@ ENV = env.str("FLASK_ENV", default="production")
|
||||||
DEBUG = ENV == "development"
|
DEBUG = ENV == "development"
|
||||||
SITE_URL = env.str('SITE_URL', default='https://grant.io')
|
SITE_URL = env.str('SITE_URL', default='https://grant.io')
|
||||||
AUTH_URL = env.str('AUTH_URL', default='https://eip-712.herokuapp.com')
|
AUTH_URL = env.str('AUTH_URL', default='https://eip-712.herokuapp.com')
|
||||||
|
CROWD_FUND_FACTORY_URL = env.str('CROWD_FUND_FACTORY_URL', default=None)
|
||||||
|
CROWD_FUND_URL = env.str('CROWD_FUND_URL', default=None)
|
||||||
SQLALCHEMY_DATABASE_URI = env.str("DATABASE_URL")
|
SQLALCHEMY_DATABASE_URI = env.str("DATABASE_URL")
|
||||||
QUEUES = ["default"]
|
QUEUES = ["default"]
|
||||||
SECRET_KEY = env.str("SECRET_KEY")
|
SECRET_KEY = env.str("SECRET_KEY")
|
||||||
|
|
|
@ -2,6 +2,8 @@ import json
|
||||||
import time
|
import time
|
||||||
from flask_web3 import current_web3
|
from flask_web3 import current_web3
|
||||||
from .util import batch_call, call_array, RpcError
|
from .util import batch_call, call_array, RpcError
|
||||||
|
import requests
|
||||||
|
from grant.settings import CROWD_FUND_URL
|
||||||
|
|
||||||
|
|
||||||
crowd_fund_abi = None
|
crowd_fund_abi = None
|
||||||
|
@ -11,11 +13,18 @@ def get_crowd_fund_abi():
|
||||||
global crowd_fund_abi
|
global crowd_fund_abi
|
||||||
if crowd_fund_abi:
|
if crowd_fund_abi:
|
||||||
return crowd_fund_abi
|
return crowd_fund_abi
|
||||||
|
|
||||||
|
if CROWD_FUND_URL:
|
||||||
|
crowd_fund_json = requests.get(CROWD_FUND_URL).json()
|
||||||
|
crowd_fund_abi = crowd_fund_json['abi']
|
||||||
|
return crowd_fund_abi
|
||||||
|
|
||||||
with open("../contract/build/contracts/CrowdFund.json", "r") as read_file:
|
with open("../contract/build/contracts/CrowdFund.json", "r") as read_file:
|
||||||
crowd_fund_abi = json.load(read_file)['abi']
|
crowd_fund_abi = json.load(read_file)['abi']
|
||||||
return crowd_fund_abi
|
return crowd_fund_abi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def read_proposal(address):
|
def read_proposal(address):
|
||||||
current_web3.eth.defaultAccount = current_web3.eth.accounts[0]
|
current_web3.eth.defaultAccount = current_web3.eth.accounts[0]
|
||||||
crowd_fund_abi = get_crowd_fund_abi()
|
crowd_fund_abi = get_crowd_fund_abi()
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
import copy
|
|
||||||
import json
|
import json
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from grant.extensions import web3
|
|
||||||
from ..config import BaseTestConfig
|
|
||||||
from grant.web3.proposal import read_proposal
|
|
||||||
from flask_web3 import current_web3
|
|
||||||
import eth_tester.backends.pyevm.main as py_evm_main
|
import eth_tester.backends.pyevm.main as py_evm_main
|
||||||
|
from flask_web3 import current_web3
|
||||||
|
from grant.extensions import web3
|
||||||
|
from grant.settings import CROWD_FUND_URL, CROWD_FUND_FACTORY_URL
|
||||||
|
from grant.web3.proposal import read_proposal
|
||||||
|
|
||||||
|
from ..config import BaseTestConfig
|
||||||
|
import requests
|
||||||
# increase gas limit on eth-tester
|
# increase gas limit on eth-tester
|
||||||
# https://github.com/ethereum/web3.py/issues/1013
|
# https://github.com/ethereum/web3.py/issues/1013
|
||||||
# https://gitter.im/ethereum/py-evm?at=5b7eb68c4be56c5918854337
|
# https://gitter.im/ethereum/py-evm?at=5b7eb68c4be56c5918854337
|
||||||
|
@ -23,10 +24,17 @@ class TestWeb3ProposalRead(BaseTestConfig):
|
||||||
BaseTestConfig.setUp(self)
|
BaseTestConfig.setUp(self)
|
||||||
# the following will properly configure web3 with test config
|
# the following will properly configure web3 with test config
|
||||||
web3.init_app(self.real_app)
|
web3.init_app(self.real_app)
|
||||||
with open("../contract/build/contracts/CrowdFundFactory.json", "r") as read_file:
|
if CROWD_FUND_FACTORY_URL:
|
||||||
crowd_fund_factory_json = json.load(read_file)
|
crowd_fund_factory_json = requests.get(CROWD_FUND_FACTORY_URL).json()
|
||||||
with open("../contract/build/contracts/CrowdFund.json", "r") as read_file:
|
else:
|
||||||
self.crowd_fund_json = json.load(read_file)
|
with open("../frontend/client/lib/contracts/CrowdFundFactory.json", "r") as read_file:
|
||||||
|
crowd_fund_factory_json = json.load(read_file)
|
||||||
|
|
||||||
|
if CROWD_FUND_URL:
|
||||||
|
self.crowd_fund_json = requests.get(CROWD_FUND_URL).json()
|
||||||
|
else:
|
||||||
|
with open("../frontend/client/lib/contracts/CrowdFund.json", "r") as read_file:
|
||||||
|
self.crowd_fund_json = json.load(read_file)
|
||||||
current_web3.eth.defaultAccount = current_web3.eth.accounts[0]
|
current_web3.eth.defaultAccount = current_web3.eth.accounts[0]
|
||||||
CrowdFundFactory = current_web3.eth.contract(
|
CrowdFundFactory = current_web3.eth.contract(
|
||||||
abi=crowd_fund_factory_json['abi'], bytecode=crowd_fund_factory_json['bytecode'])
|
abi=crowd_fund_factory_json['abi'], bytecode=crowd_fund_factory_json['bytecode'])
|
||||||
|
@ -78,13 +86,13 @@ class TestWeb3ProposalRead(BaseTestConfig):
|
||||||
|
|
||||||
def create_crowd_fund(self):
|
def create_crowd_fund(self):
|
||||||
tx_hash = self.crowd_fund_factory.functions.createCrowdFund(
|
tx_hash = self.crowd_fund_factory.functions.createCrowdFund(
|
||||||
5000000000000000000, # ethAmount
|
5000000000000000000, # ethAmount
|
||||||
current_web3.eth.accounts[0], # payout
|
current_web3.eth.accounts[0], # payout
|
||||||
[current_web3.eth.accounts[0]], # trustees
|
[current_web3.eth.accounts[0]], # trustees
|
||||||
[5000000000000000000], # milestone amounts
|
[5000000000000000000], # milestone amounts
|
||||||
60, # duration (minutes)
|
60, # duration (minutes)
|
||||||
60, # voting period (minutes)
|
60, # voting period (minutes)
|
||||||
True # immediate first milestone payout
|
True # immediate first milestone payout
|
||||||
).transact()
|
).transact()
|
||||||
tx_receipt = current_web3.eth.waitForTransactionReceipt(tx_hash)
|
tx_receipt = current_web3.eth.waitForTransactionReceipt(tx_hash)
|
||||||
tx_events = self.crowd_fund_factory.events.ContractCreated().processReceipt(tx_receipt)
|
tx_events = self.crowd_fund_factory.events.ContractCreated().processReceipt(tx_receipt)
|
||||||
|
|
|
@ -2,5 +2,4 @@ node_modules
|
||||||
.idea/
|
.idea/
|
||||||
yarn-error.log
|
yarn-error.log
|
||||||
.env
|
.env
|
||||||
build/abi
|
build
|
||||||
build/typedefs
|
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -5,4 +5,7 @@ FUND_ETH_ADDRESSES=0x4bbeEB066eD09B7AEd07bF39EEe0460DFa261520,0xDECAF9CD2367cdbb
|
||||||
NO_DEV_TS_CHECK=true
|
NO_DEV_TS_CHECK=true
|
||||||
|
|
||||||
# Set the public host url (no trailing slash)
|
# Set the public host url (no trailing slash)
|
||||||
PUBLIC_HOST_URL=https://demo.grant.io
|
PUBLIC_HOST_URL=https://demo.grant.io
|
||||||
|
|
||||||
|
CROWD_FUND_URL = "https://eip-712.herokuapp.com/contract/crowd-fund"
|
||||||
|
CROWD_FUND_FACTORY_URL = "https://eip-712.herokuapp.com/contract/factory"
|
|
@ -1 +1 @@
|
||||||
8.11.4
|
8.13.0
|
|
@ -0,0 +1 @@
|
||||||
|
web: yarn start
|
|
@ -1,9 +1,9 @@
|
||||||
import axios from './axios';
|
import axios from './axios';
|
||||||
import { Proposal, TeamMember, Update } from 'types';
|
import { Proposal, TeamMember, Update } from 'types';
|
||||||
import {
|
import {
|
||||||
|
formatProposalFromGet,
|
||||||
formatTeamMemberForPost,
|
formatTeamMemberForPost,
|
||||||
formatTeamMemberFromGet,
|
formatTeamMemberFromGet,
|
||||||
formatProposalFromGet,
|
|
||||||
} from 'utils/api';
|
} from 'utils/api';
|
||||||
import { PROPOSAL_CATEGORY } from './constants';
|
import { PROPOSAL_CATEGORY } from './constants';
|
||||||
|
|
||||||
|
@ -91,6 +91,16 @@ export function verifyEmail(code: string): Promise<any> {
|
||||||
return axios.post(`/api/v1/email/${code}/verify`);
|
return axios.post(`/api/v1/email/${code}/verify`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function fetchCrowdFundFactoryJSON(): Promise<any> {
|
||||||
|
const res = await axios.get(process.env.CROWD_FUND_FACTORY_URL as string);
|
||||||
|
return res.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function fetchCrowdFundJSON(): Promise<any> {
|
||||||
|
const res = await axios.get(process.env.CROWD_FUND_URL as string);
|
||||||
|
return res.data;
|
||||||
|
}
|
||||||
|
|
||||||
export function postProposalUpdate(
|
export function postProposalUpdate(
|
||||||
proposalId: number,
|
proposalId: number,
|
||||||
title: string,
|
title: string,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import Web3 from 'web3';
|
import Web3 from 'web3';
|
||||||
import getContractInstance from './getContract';
|
import getContractInstance from './getContract';
|
||||||
import CrowdFund from 'lib/contracts/CrowdFund.json';
|
import { fetchCrowdFundJSON } from 'api/api';
|
||||||
|
|
||||||
const contractCache = {} as { [key: string]: any };
|
const contractCache = {} as { [key: string]: any };
|
||||||
|
|
||||||
|
@ -9,6 +9,12 @@ export async function getCrowdFundContract(web3: Web3 | null, deployedAddress: s
|
||||||
throw new Error('getCrowdFundAddress: web3 was null but is required!');
|
throw new Error('getCrowdFundAddress: web3 was null but is required!');
|
||||||
}
|
}
|
||||||
if (!contractCache[deployedAddress]) {
|
if (!contractCache[deployedAddress]) {
|
||||||
|
let CrowdFund;
|
||||||
|
if (process.env.CROWD_FUND_FACTORY_URL) {
|
||||||
|
CrowdFund = await fetchCrowdFundJSON();
|
||||||
|
} else {
|
||||||
|
CrowdFund = await import('./contracts/CrowdFund.json');
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
contractCache[deployedAddress] = await getContractInstance(
|
contractCache[deployedAddress] = await getContractInstance(
|
||||||
web3,
|
web3,
|
||||||
|
|
|
@ -1,18 +1,22 @@
|
||||||
import { SagaIterator } from 'redux-saga';
|
import { SagaIterator } from 'redux-saga';
|
||||||
import { put, all, fork, take, takeLatest, select, call } from 'redux-saga/effects';
|
import { all, call, fork, put, select, take, takeLatest } from 'redux-saga/effects';
|
||||||
import { setWeb3, setAccounts, setContract } from './actions';
|
import { setAccounts, setContract, setWeb3 } from './actions';
|
||||||
import { selectWeb3 } from './selectors';
|
import { selectWeb3 } from './selectors';
|
||||||
import { safeEnable } from 'utils/web3';
|
import { safeEnable } from 'utils/web3';
|
||||||
import types from './types';
|
import types from './types';
|
||||||
|
import { fetchCrowdFundFactoryJSON } from 'api/api';
|
||||||
|
|
||||||
/* tslint:disable no-var-requires --- TODO: find a better way to import contract */
|
/* tslint:disable no-var-requires --- TODO: find a better way to import contract */
|
||||||
const CrowdFundFactory = require('lib/contracts/CrowdFundFactory.json');
|
let CrowdFundFactory = require('lib/contracts/CrowdFundFactory.json');
|
||||||
|
|
||||||
export function* bootstrapWeb3(): SagaIterator {
|
export function* bootstrapWeb3(): SagaIterator {
|
||||||
// Don't attempt to bootstrap web3 on SSR
|
// Don't attempt to bootstrap web3 on SSR
|
||||||
if (process.env.SERVER_SIDE_RENDER) {
|
if (process.env.SERVER_SIDE_RENDER) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (process.env.CROWD_FUND_FACTORY_URL) {
|
||||||
|
CrowdFundFactory = yield call(fetchCrowdFundFactoryJSON);
|
||||||
|
}
|
||||||
|
|
||||||
yield put<any>(setWeb3());
|
yield put<any>(setWeb3());
|
||||||
yield take(types.WEB3_FULFILLED);
|
yield take(types.WEB3_FULFILLED);
|
||||||
|
|
|
@ -26,14 +26,29 @@ dotenvFiles.forEach(dotenvFile => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!process.env.PUBLIC_HOST_URL) {
|
const envProductionRequiredHandler = (envVariable, fallbackValue) => {
|
||||||
if (process.env.NODE_ENV === 'production') {
|
if (!process.env[envVariable]) {
|
||||||
throw new Error(
|
if (process.env.NODE_ENV === 'production') {
|
||||||
'The process.env.PUBLIC_HOST_URL environment variable is required but was not specified.',
|
throw new Error(
|
||||||
);
|
`The process.env.${envVariable} environment variable is required but was not specified.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
process.env[envVariable] = fallbackValue;
|
||||||
}
|
}
|
||||||
process.env.PUBLIC_HOST_URL = 'http://localhost:' + (process.env.PORT || 3000);
|
};
|
||||||
}
|
|
||||||
|
envProductionRequiredHandler(
|
||||||
|
'PUBLIC_HOST_URL',
|
||||||
|
'http://localhost:' + (process.env.PORT || 3000),
|
||||||
|
);
|
||||||
|
envProductionRequiredHandler(
|
||||||
|
'CROWD_FUND_URL',
|
||||||
|
'https://eip-712.herokuapp.com/contract/crowd-fund',
|
||||||
|
);
|
||||||
|
envProductionRequiredHandler(
|
||||||
|
'CROWD_FUND_FACTORY_URL',
|
||||||
|
'https://eip-712.herokuapp.com/contract/factory',
|
||||||
|
);
|
||||||
|
|
||||||
const appDirectory = fs.realpathSync(process.cwd());
|
const appDirectory = fs.realpathSync(process.cwd());
|
||||||
process.env.NODE_PATH = (process.env.NODE_PATH || '')
|
process.env.NODE_PATH = (process.env.NODE_PATH || '')
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "grant",
|
"name": "grant",
|
||||||
"version": "1.0.1",
|
"version": "1.0.2",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -10,12 +10,16 @@
|
||||||
"lint": "tslint --project ./tsconfig.json --config ./tslint.json -e \"**/build/**\"",
|
"lint": "tslint --project ./tsconfig.json --config ./tslint.json -e \"**/build/**\"",
|
||||||
"start": "NODE_ENV=production node ./build/server/server.js",
|
"start": "NODE_ENV=production node ./build/server/server.js",
|
||||||
"now": "npm run build && now -e BACKEND_URL=https://grant-stage.herokuapp.com",
|
"now": "npm run build && now -e BACKEND_URL=https://grant-stage.herokuapp.com",
|
||||||
|
"heroku-postbuild": "yarn build",
|
||||||
"tsc": "tsc",
|
"tsc": "tsc",
|
||||||
"link-contracts": "cd client/lib && ln -s ../../build/contracts contracts",
|
"link-contracts": "cd client/lib && ln -s ../../build/contracts contracts",
|
||||||
"ganache": "ganache-cli -b 5",
|
"ganache": "ganache-cli -b 5",
|
||||||
"truffle": "truffle exec ./bin/init-truffle.js && cd client/lib/contracts && truffle console",
|
"truffle": "truffle exec ./bin/init-truffle.js && cd client/lib/contracts && truffle console",
|
||||||
"storybook": "start-storybook -p 9001 -c .storybook"
|
"storybook": "start-storybook -p 9001 -c .storybook"
|
||||||
},
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "8.13.0"
|
||||||
|
},
|
||||||
"husky": {
|
"husky": {
|
||||||
"hooks": {
|
"hooks": {
|
||||||
"pre-commit": "lint-staged",
|
"pre-commit": "lint-staged",
|
||||||
|
|
Loading…
Reference in New Issue