Skip to content

Commit

Permalink
Merge branch 'master' into faster-signup-flow
Browse files Browse the repository at this point in the history
# Conflicts:
#	src/server/verification/verificationAPI.js
  • Loading branch information
fernandomg committed May 27, 2019
2 parents bf76b4b + bc24504 commit 08b2658
Show file tree
Hide file tree
Showing 11 changed files with 119 additions and 67 deletions.
5 changes: 3 additions & 2 deletions .env.dev
Expand Up @@ -2,7 +2,7 @@ NODE_ENV=development
GUNDB_PASS=password
MNEMONIC="drip industry pizza deny pistol stem must device citizen crowd offer now"
INFURA_API=
NETWORK=truffle
NETWORK=develop
LOG_LEVEL=trace
PLIVO_AUTH_ID=MADSFJASDF2341ASDF0G
PLIVO_AUTH_TOKEN=YWRiMl2nomwsdfoQeTBadk9290dkmEAVB13zg5G5
Expand All @@ -16,4 +16,5 @@ MAUTIC_TOKEN=""
ZOOM_API_URL=https://api.zoomauth.com/api/v1/biometrics
ZOOM_TOKEN=
ZOOM_MIN_MATCH_LEVEL=1
ALLOW_DUPLICATE_USER_DATA=true
ALLOW_DUPLICATE_USER_DATA=true
SKIP_EMAIL_VERIFICATION=true
3 changes: 2 additions & 1 deletion .env.example
Expand Up @@ -3,7 +3,7 @@ NODE_ENV=development
GUNDB_PASS=password
MNEMONIC=choice congress hobby buddy dutch busy army eager empty solution start grunt
INFURA_API=
NETWORK=kovan
NETWORK=production
LOG_LEVEL=trace
PLIVO_AUTH_ID=MADSFJASDF2341ASDF0G
PLIVO_AUTH_TOKEN=YWRiMl2nomwsdfoQeTBadk9290dkmEAVB13zg5G5
Expand All @@ -29,3 +29,4 @@ GUN_PRIVATE_S3=
AWS_S3_BUCKET=1
#allow multiple users to register with same mobile/email - for testing
ALLOW_DUPLICATE_USER_DATA=true
SKIP_EMAIL_VERIFICATION=true
7 changes: 5 additions & 2 deletions .travis.yml
Expand Up @@ -7,20 +7,23 @@ env:
global:
- GUNDB_PASS=test
- MNEMONIC="choice congress hobby buddy dutch busy army eager empty solution start grunt"
- NETWORK=truffle
- PRIVATE_KEY=0x4a82fd2f72fe7a1f4258a3f091ecc06d4d523efc20fd4d0ce21c8bed799088c1
- NETWORK=develop
- LOG_LEVEL=trace

before_install:
- npm install -g ganache-cli truffle webpack

before_script:
- export CONTRACTSTAG=${CONTRACTSTAG:-`node -pe "require('./node_modules/@gooddollar/goodcontracts/package.json').version"`}
- export CONTRACTSTAG=${CONTRACTSTAG:-`node -pe "require('./package.json').dependencies['@gooddollar/goodcontracts']"`}
- node -pe "require('./package.json').dependencies['@gooddollar/goodcontracts']"
- git clone https://github.com/GoodDollar/GoodContracts --branch=v$CONTRACTSTAG
- ganache-cli -m "$MNEMONIC" --port 9545 --networkId 4447 -g 10000000000 &
- cd GoodContracts || true
- npm i
- truffle migrate --reset --network develop
- npm link
- ls -la releases
- cd ..

script:
Expand Down
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -39,7 +39,7 @@
"dependencies": {
"@babel/polyfill": "^7.2.5",
"@colony/purser-metamask": "^2.1.0",
"@gooddollar/goodcontracts": "0.0.14",
"@gooddollar/goodcontracts": "0.0.15",
"@sendgrid/mail": "^6.3.1",
"aws-sdk": "^2.450.0",
"body-parser": "^1.18.3",
Expand Down
3 changes: 2 additions & 1 deletion src/imports/otp.js
Expand Up @@ -20,7 +20,8 @@ const sendOTP = (user: UserRecord): Promise<any> => {
const { mobile } = user
const client = new plivo.Client(plivoAuthID, plivoAuthToken)
const otp = generateOTP(conf.otpDigits)
return Promise.all([client.messages.create(plivoPhoneNumber, mobile, otp), otp])
const msg = 'Your GoodDollar Verification Code Is: ' + otp
return Promise.all([client.messages.create(plivoPhoneNumber, mobile, msg), otp])
}

export { generateOTP, sendOTP }
100 changes: 66 additions & 34 deletions src/server/blockchain/AdminWallet.js
Expand Up @@ -8,10 +8,12 @@ import IdentityABI from '@gooddollar/goodcontracts/build/contracts/Identity.json
import RedemptionABI from '@gooddollar/goodcontracts/build/contracts/RedemptionFunctional.json'
import GoodDollarABI from '@gooddollar/goodcontracts/build/contracts/GoodDollar.json'
import ReserveABI from '@gooddollar/goodcontracts/build/contracts/GoodDollarReserve.json'
import ContractsAddress from '@gooddollar/goodcontracts/releases/deployment.json'
import conf from '../server.config'
import logger from '../../imports/pino-logger'
import { type TransactionReceipt } from './blockchain-types'
import moment from 'moment'
import get from 'lodash/get'

const log = logger.child({ from: 'AdminWallet' })
export class Wallet {
Expand Down Expand Up @@ -66,44 +68,74 @@ export class Wallet {
}

async init() {
log.debug('Initializing wallet:', { mnemonic: this.mnemonic, conf: conf.ethereum })
this.wallet = new HDWalletProvider(this.mnemonic, this.getWeb3TransportProvider(), 0, 10)

this.web3 = new Web3(this.wallet, {
defaultAccount: this.address,
defaultGasPrice: Web3.utils.toWei('1', 'gwei'),
defaultGas: 500000
})
this.address = this.wallet.addresses[0]
let account = this.web3.eth.accounts.privateKeyToAccount(
'0x' + this.wallet.wallets[this.address]._privKey.toString('hex')
log.debug('Initializing wallet:', { conf: conf.ethereum })

if (conf.privateKey) {
this.web3 = new Web3(this.getWeb3TransportProvider(), null, {
defaultGasPrice: Web3.utils.toWei('1', 'gwei'),
defaultGas: 500000
})
let account = this.web3.eth.accounts.privateKeyToAccount(conf.privateKey)
this.web3.eth.accounts.wallet.add(account)
this.web3.eth.defaultAccount = account.address
this.address = account.address
log.debug('Initialized by private key:', account.address)
} else if (conf.mnemonic) {
this.wallet = new HDWalletProvider(this.mnemonic, this.getWeb3TransportProvider(), 0, 10)

this.web3 = new Web3(this.wallet, null, {
defaultAccount: this.address,
defaultGasPrice: Web3.utils.toWei('1', 'gwei'),
defaultGas: 500000
})
this.address = this.wallet.addresses[0]
let account = this.web3.eth.accounts.privateKeyToAccount(
'0x' + this.wallet.wallets[this.address]._privKey.toString('hex')
)
this.web3.eth.accounts.wallet.add(account)
}
this.network = conf.network
this.networkId = conf.ethereum.network_id
this.identityContract = new this.web3.eth.Contract(
IdentityABI.abi,
get(ContractsAddress, `${this.network}.Identity`, IdentityABI.networks[this.networkId].address),
{
from: this.address,
gas: 500000,
gasPrice: Web3.utils.toWei('1', 'gwei')
}
)
this.claimContract = new this.web3.eth.Contract(
RedemptionABI.abi,
get(ContractsAddress, `${this.network}.RedemptionFunctional`, RedemptionABI.networks[this.networkId].address),
{
from: this.address,
gas: 500000,
gasPrice: Web3.utils.toWei('1', 'gwei')
}
)
this.tokenContract = new this.web3.eth.Contract(
GoodDollarABI.abi,
get(ContractsAddress, `${this.network}.GoodDollar`, GoodDollarABI.networks[this.networkId].address),
{
from: this.address,
gas: 500000,
gasPrice: Web3.utils.toWei('1', 'gwei')
}
)
this.reserveContract = new this.web3.eth.Contract(
ReserveABI.abi,
get(ContractsAddress, `${this.network}.GoodDollarReserve`, ReserveABI.networks[this.networkId].address),
{
from: this.address,
gas: 500000,
gasPrice: Web3.utils.toWei('1', 'gwei')
}
)
this.web3.eth.accounts.wallet.add(account)
this.networkId = conf.ethereum.network_id // ropsten network
this.identityContract = new this.web3.eth.Contract(IdentityABI.abi, IdentityABI.networks[this.networkId].address, {
from: this.address,
gas: 500000,
gasPrice: Web3.utils.toWei('1', 'gwei')
})
this.claimContract = new this.web3.eth.Contract(RedemptionABI.abi, RedemptionABI.networks[this.networkId].address, {
from: this.address,
gas: 500000,
gasPrice: Web3.utils.toWei('1', 'gwei')
})
this.tokenContract = new this.web3.eth.Contract(GoodDollarABI.abi, GoodDollarABI.networks[this.networkId].address, {
from: this.address,
gas: 500000,
gasPrice: Web3.utils.toWei('1', 'gwei')
})
this.reserveContract = new this.web3.eth.Contract(ReserveABI.abi, ReserveABI.networks[this.networkId].address, {
from: this.address,
gas: 500000,
gasPrice: Web3.utils.toWei('1', 'gwei')
})
try {
let gdbalance = await this.tokenContract.methods.balanceOf(this.address).call()
let nativebalance = await this.web3.eth.getBalance(this.address)
log.debug('AdminWallet Ready:', { account, gdbalance, nativebalance })
log.debug('AdminWallet Ready:', { account: this.address, gdbalance, nativebalance })
} catch (e) {
log.error('Error initializing wallet', e)
}
Expand Down
12 changes: 3 additions & 9 deletions src/server/networks.js
@@ -1,23 +1,17 @@
const networks = {
kovan: {
42: {
network_id: 42,
web3Transport: 'HttpProvider',
httpWeb3Provider: `https://kovan.infura.io/v3/${process.env.INFURA_API}`,
websocketWeb3Provider: 'wss://kovan.infura.io/ws'
},
ganache: {
network_id: 6000,
web3Transport: 'HttpProvider',
httpWeb3Provider: 'http://localhost:8545/',
websocketWeb3Provider: 'wss://localhost:8545/ws'
},
truffle: {
4447: {
network_id: 4447,
web3Transport: 'HttpProvider',
httpWeb3Provider: 'http://localhost:9545/',
websocketWeb3Provider: 'ws://localhost:9545/ws'
},
fuse: {
121: {
network_id: 121,
web3Transport: 'HttpProvider',
httpWeb3Provider: 'https://rpc.fuse.io/',
Expand Down
18 changes: 16 additions & 2 deletions src/server/server.config.js
@@ -1,4 +1,5 @@
import networks from './networks'
import ContractsAddress from '@gooddollar/goodcontracts/releases/deployment.json'

require('dotenv').config()
const convict = require('convict')
Expand Down Expand Up @@ -39,6 +40,12 @@ const conf = convict({
env: 'MNEMONIC',
default: ''
},
privateKey: {
doc: 'Wallet private key',
format: '*',
env: 'PRIVATE_KEY',
default: undefined
},
infuraKey: {
doc: 'Infura API Key',
format: '*',
Expand All @@ -53,7 +60,7 @@ const conf = convict({
},
network: {
doc: 'The blockchain network to connect to',
format: ['kovan', 'mainnet', 'rinkbey', 'ropsten', 'truffle', 'ganache', 'fuse'],
format: ['kovan', 'mainnet', 'rinkbey', 'ropsten', 'truffle', 'ganache', 'fuse', 'production', 'develop'],
default: 'kovan',
env: 'NETWORK'
},
Expand Down Expand Up @@ -202,13 +209,20 @@ const conf = convict({
format: Boolean,
env: 'ALLOW_DUPLICATE_USER_DATA',
default: false
},
skipEmailVerification: {
doc: 'Allow to register with unverified email',
format: Boolean,
env: 'SKIP_EMAIL_VERIFICATION',
default: false
}
})

// Load environment dependent configuration
const env = conf.get('env')
const network = conf.get('network')
conf.set('ethereum', networks[network])
const networkId = ContractsAddress[network].networkId
conf.set('ethereum', networks[networkId])
//parse S3 details for gundb in format of key,secret,bucket
const privateS3 = process.env.GUN_PRIVATE_S3
if (privateS3) {
Expand Down
6 changes: 5 additions & 1 deletion src/server/storage/storageAPI.js
Expand Up @@ -20,7 +20,11 @@ const setup = (app: Router, storage: StorageAPI) => {
const logger = req.log.child({ from: 'storageAPI - /user/add' })

//check that user passed all min requirements
if (['production', 'staging'].includes(conf.env) && (!userRecord.smsValidated || !userRecord.isEmailConfirmed))
if (
['production', 'staging'].includes(conf.env) &&
(userRecord.smsValidated !== true ||
(conf.skipEmailVerification === false && userRecord.isEmailConfirmed !== true))
)
throw new Error('User email or mobile not verified!')

const user: UserRecord = defaults(body.user, { identifier: userRecord.loggedInAs })
Expand Down
24 changes: 13 additions & 11 deletions src/server/verification/verificationAPI.js
Expand Up @@ -156,18 +156,20 @@ const setup = (app: Router, verifier: VerificationAPI, storage: StorageAPI) => {
userRec.mauticId = mauticContact.contact.fields.all.id
log.debug('created new user mautic contact', userRec)
}
const code = generateOTP(10)
if (!user.isEmailConfirmed) {
const validationLink = `${conf.walletUrl}/Signup/EmailConfirmation/?validation=${code}`
Mautic.sendVerificationEmail(userRec, validationLink)
log.debug('send new user email validation link', validationLink)
if (conf.skipEmailVerification === false) {
const code = generateOTP(10)
if (!user.isEmailConfirmed) {
const validationLink = `${conf.walletUrl}/Signup/EmailConfirmation/?validation=${code}`
Mautic.sendVerificationEmail(userRec, validationLink)
log.debug('send new user email validation link', validationLink)
}
// updates/adds user with the emailVerificationCode to be used for verification later and with mauticId
storage.updateUser({
identifier: user.loggedInAs,
mauticId: userRec.mauticId,
emailVerificationCode: code
})
}
// updates/adds user with the emailVerificationCode to be used for verification later and with mauticId
storage.updateUser({
identifier: user.loggedInAs,
mauticId: userRec.mauticId,
emailVerificationCode: code
})

res.json({ ok: 1 })
})
Expand Down

0 comments on commit 08b2658

Please sign in to comment.