This repository has been archived by the owner on Dec 1, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 13
/
start_operator.js
executable file
·147 lines (124 loc) · 5.73 KB
/
start_operator.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#!/usr/bin/env node
const fs = require("mz/fs")
const path = require("path")
const express = require("express")
const cors = require("cors")
const bodyParser = require("body-parser")
const onProcessExit = require("exit-hook")
const Web3 = require("web3")
const Operator = require("./src/operator")
const { throwIfSetButNotContract } = require("./src/utils/checkArguments")
const defaultServers = require("./defaultServers.json")
const deployDemoToken = require("./src/utils/deployDemoToken")
const operatorRouter = require("./src/routers/member")
const adminRouter = require("./src/routers/admin")
const revenueDemoRouter = require("./src/routers/revenueDemo")
const Channel = require("./src/joinPartChannel")
const MonoplasmaJson = require("./build/contracts/Monoplasma.json")
const {
ETHEREUM_SERVER,
ETHEREUM_NETWORK_ID,
ETHEREUM_PRIVATE_KEY,
TOKEN_ADDRESS,
CONTRACT_ADDRESS,
FREEZE_PERIOD_SECONDS,
GAS_PRICE_GWEI,
RESET,
STORE_DIR,
QUIET,
// these will be used 1) for demo token 2) if TOKEN_ADDRESS doesn't support name() and symbol()
TOKEN_SYMBOL,
TOKEN_NAME,
// if ETHEREUM_SERVER isn't specified, start a local Ethereum simulator (Ganache) in given port
GANACHE_PORT,
JOIN_PART_CHANNEL_PORT,
// web UI for revenue sharing demo
WEBSERVER_PORT,
// don't launch web server in start_operator script
// by default start serving static files under demo/public. This is for dev where UI is launched with `npm start` under demo directory.
//EXTERNAL_WEBSERVER,
ADMINFEE_WEI
} = process.env
const log = QUIET ? () => {} : console.log
const error = (e, ...args) => {
console.error(e.stack, args)
process.exit(1)
}
const storeDir = fs.existsSync(STORE_DIR) ? STORE_DIR : __dirname + "/demo/public/data"
const FileStore = require("./src/fileStore")
const fileStore = new FileStore(storeDir, log)
let ganache = null
function stopGanache() {
if (ganache) {
log("Shutting down Ethereum simulator...")
ganache.shutdown()
ganache = null
}
}
onProcessExit(stopGanache)
async function start() {
let privateKey
let ethereumServer = ETHEREUM_SERVER || defaultServers[ETHEREUM_NETWORK_ID]
if (ethereumServer) {
if (!ETHEREUM_PRIVATE_KEY) { throw new Error("Private key required to deploy the airdrop contract. Deploy transaction must be signed.") }
privateKey = ETHEREUM_PRIVATE_KEY.startsWith("0x") ? ETHEREUM_PRIVATE_KEY : "0x" + ETHEREUM_PRIVATE_KEY
if (privateKey.length !== 66) { throw new Error("Malformed private key, must be 64 hex digits long (optionally prefixed with '0x')") }
} else {
// use account 0: 0xa3d1f77acff0060f7213d7bf3c7fec78df847de1
privateKey = "0x5e98cce00cff5dea6b454889f359a4ec06b9fa6b88e9d69b86de8e1c81887da0"
log("Starting Ethereum simulator...")
const ganachePort = GANACHE_PORT || 8545
const ganacheLog = msg => { log(" <Ganache> " + msg) }
ganache = await require("./src/utils/startGanache")(ganachePort, ganacheLog, error)
ethereumServer = ganache.url
}
log(`Connecting to ${ethereumServer}`)
const web3 = new Web3(ethereumServer)
const account = web3.eth.accounts.wallet.add(privateKey)
await throwIfSetButNotContract(web3, TOKEN_ADDRESS, "Environment variable TOKEN_ADDRESS")
await throwIfSetButNotContract(web3, CONTRACT_ADDRESS, "Environment variable CONTRACT_ADDRESS")
const opts = {
from: account.address,
gas: 4000000,
gasPrice: GAS_PRICE_GWEI || 4000000000,
}
// ignore the saved config / saved state if not using a fresh ganache instance
// augment the config / saved state with variables that may be useful for the validators
const config = RESET || ganache ? {} : await fileStore.loadState()
config.tokenAddress = TOKEN_ADDRESS || config.tokenAddress || await deployDemoToken(web3, TOKEN_NAME, TOKEN_SYMBOL, opts, log)
config.freezePeriodSeconds = +FREEZE_PERIOD_SECONDS || config.freezePeriodSeconds || 20
const newContractAdminFee = ADMINFEE_WEI || 0
config.contractAddress = CONTRACT_ADDRESS || config.contractAddress || await deployContract(web3, config.tokenAddress, config.freezePeriodSeconds, newContractAdminFee, opts, log)
config.ethereumServer = ethereumServer
config.ethereumNetworkId = ETHEREUM_NETWORK_ID
config.channelPort = JOIN_PART_CHANNEL_PORT
config.operatorAddress = account.address
log("Starting the joinPartChannel and Operator")
const adminChannel = new Channel(JOIN_PART_CHANNEL_PORT)
adminChannel.startServer()
const operatorChannel = new Channel(JOIN_PART_CHANNEL_PORT)
const operator = new Operator(web3, operatorChannel, config, fileStore, log, error)
await operator.start()
log("Starting web server...")
const port = WEBSERVER_PORT || 8080
const serverURL = `http://localhost:${port}`
const app = express()
app.use(cors())
app.use(bodyParser.json({limit: "50mb"}))
app.use("/api", operatorRouter(operator.plasma.getMemberApi()))
app.use("/admin", adminRouter(adminChannel))
app.use("/demo", revenueDemoRouter(operator))
app.use(express.static(path.join(__dirname, "demo/public")))
app.listen(port, () => log(`Web server started at ${serverURL}`))
log("[DONE]")
}
async function deployContract(web3, tokenAddress, freezePeriodSeconds, adminFee, sendOptions, log) {
log(`Deploying root chain contract (token @ ${tokenAddress}, freezePeriodSeconds = ${freezePeriodSeconds})...`)
const Monoplasma = new web3.eth.Contract(MonoplasmaJson.abi)
const monoplasma = await Monoplasma.deploy({
data: MonoplasmaJson.bytecode,
arguments: [tokenAddress, freezePeriodSeconds, adminFee]
}).send(sendOptions)
return monoplasma.options.address
}
start().catch(error)