-
Notifications
You must be signed in to change notification settings - Fork 82
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'development' into Master
Naming the version as 0.1
- Loading branch information
Showing
50 changed files
with
2,683 additions
and
48 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
node_modules |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
const fs = require('fs'); | ||
const helpers = require('./common/helpers.ts') | ||
|
||
const DockerOdeWrapper = { | ||
docker: { | ||
listContainers(dockerInstance) { | ||
return new Promise((resolve, reject) => { | ||
dockerInstance.listContainers((error, containers) => { | ||
if(error) { | ||
reject(error); | ||
} else { | ||
resolve(containers); | ||
} | ||
}); | ||
}) | ||
}, | ||
getContainer(dockerInstance, id) { | ||
return new Promise((resolve) => { | ||
resolve(dockerInstance.getContainer(id)); | ||
}); | ||
}, | ||
}, | ||
container: { | ||
exec(dockerInstance, container, command) { | ||
return new Promise((resolve, reject) => { | ||
container.exec({ Cmd: command.split(" "), AttachStdIn: true, AttachStdout: true}, (error, exec) => { | ||
exec.start({hijack: true, stdin: false}, (err, stream) => { | ||
if (error) { | ||
console.log(`Command \"${command}\" failed to run`); | ||
reject(err); | ||
} else { | ||
console.log(`Command \"${command}\" executed successfully`); | ||
return helpers.demuxStream(stream) | ||
.then((output) => { | ||
return resolve(output) | ||
}) | ||
|
||
} | ||
}) | ||
}) | ||
}) | ||
} | ||
} | ||
} | ||
|
||
module.exports = DockerOdeWrapper; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
FROM node:14 | ||
COPY start.sh / | ||
WORKDIR /usr/src/app/blockchain-client/src | ||
COPY . . | ||
RUN npm i | ||
ENTRYPOINT ["sh", "/start.sh"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
const apis = [ | ||
{ | ||
name: "Get Accounts", | ||
description: "Returns the list of ethereum accounts in the container.", | ||
command: "getAccounts", | ||
parameters: [] | ||
}, | ||
{ | ||
name: "Get Balance", | ||
description: "Returns the balance of the account specified as parameter.", | ||
command: "getBalance", | ||
parameters: [{el: "input", name: "Account index", required: true}] | ||
}, | ||
{ | ||
name: "Set Etherbase", | ||
description: "Sets the account which will be receiving ether when mining.", | ||
command: "setEtherBase", | ||
parameters: [{el: "input", name: "Account index", required: true}] | ||
}, | ||
{ | ||
name: "Get Coinbase", | ||
description: "Returns the address of the account collecting ether when mining", | ||
command: "getCoinBase", | ||
}, | ||
{ | ||
name: "Start Mining", | ||
description: "Starts the mining process on the coinbase account.", | ||
command: "startMiner", | ||
parameters: [{el: "input", name: "Number of threads", required: false}] | ||
}, | ||
{ | ||
name: "Stop Mining", | ||
description: "Stop the mining process.", | ||
command: "stopMiner", | ||
parameters: [] | ||
}, | ||
{ | ||
name: "Send Transaction", | ||
description: "Send ether from one account to the other.", | ||
command: "sendTransaction", | ||
parameters: [{el: "input", name:"From address", required: true},{el: "input", name: "To address", required: true},{el: "input", name: "Value in ether", required: true}] | ||
}, | ||
{ | ||
name: "View Pending Transactions", | ||
description: "View a list of pending transactions in the network.", | ||
command: "viewPendingTransactions", | ||
parameters: [] | ||
} | ||
] | ||
|
||
module.exports = apis; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
const helpers = require('./common/helpers.ts') | ||
|
||
// @todo use the castGethParameters for all other commands | ||
const commands = { | ||
getAccounts() { | ||
return "geth attach --exec eth.accounts" | ||
}, | ||
getBalance(account) { | ||
account = account || 0; | ||
return `geth attach --exec eth.getBalance(eth.accounts[${account}])` | ||
}, | ||
setDefaultAccount(account) { | ||
account = account || 0; | ||
// spaces matter here when writing the equality, remove the spaces. | ||
return `geth attach --exec eth.defaultAccount=eth.accounts[${account}]` | ||
}, | ||
getDefaultAccount() { | ||
return `geth attach --exec eth.defaultAccount` | ||
}, | ||
setEtherBase(account) { | ||
account = account || 0 | ||
return `geth attach --exec miner.setEtherbase(eth.accounts[${account}])` | ||
}, | ||
getCoinBase() { | ||
return `geth attach --exec eth.coinbase` | ||
}, | ||
startMiner(threads) { | ||
threads = threads || 20; | ||
return `geth attach --exec miner.start(${threads})` | ||
}, | ||
stopMiner() { | ||
return `geth attach --exec miner.stop()` | ||
}, | ||
sendTransaction(sender, receiver, amount) { | ||
return `geth attach --exec eth.sendTransaction({from:"${sender}",to:"${receiver}",value:web3.toWei(${amount},\"ether\")})` | ||
}, | ||
viewPendingTransactions() { | ||
return `geth attach --exec eth.pendingTransactions` | ||
}, | ||
deploySmartContract(account, abi, bytecode, params, value) { | ||
abi = abi.replace(" ", "\t") | ||
let base = `{from:"${account}",data:"${bytecode}",gas:1000000` | ||
if(params.length) { | ||
base = params +',' + base; | ||
} | ||
if(value) { | ||
base += `,value:${value}` | ||
} | ||
base += '}' | ||
|
||
//if(params.length) { | ||
// return `geth attach --exec eth.contract(${abi}).new(${params},{from:"${account}",data:"${bytecode}",gas:1000000})` | ||
//} else { | ||
// return `geth attach --exec eth.contract(${abi}).new()` | ||
//} | ||
return `geth attach --exec eth.contract(${abi}).new(${base})` | ||
}, | ||
getTransactionReceipt(hash) { | ||
return `geth attach --exec eth.getTransactionReceipt("${hash}")` | ||
}, | ||
getContractByAddress(abi,address) { | ||
abi = abi.replace(" ", "\t") | ||
return `geth attach --exec eth.contract(${abi}).at("${address}")` | ||
}, | ||
invokeContractFunction(funcInfo, parameters, additional=[]) { | ||
const {funcName, payable} = funcInfo | ||
const [defaultAccount, {abi, address}, value] = additional; | ||
const parameterString = this.generateCallString(parameters, {payable, value}) | ||
const tail = this.options.call ? '.call' + parameterString : parameterString; | ||
|
||
sanitizedAbi = abi.replace(" ", "\t") | ||
|
||
return `geth attach --exec eth.defaultAccount="${defaultAccount}";` + | ||
`sc=eth.contract(${sanitizedAbi}).at("${address}");` + | ||
`sc["${funcName}"]${tail}` | ||
}, | ||
generateCallString(parameters=[], options={}) { | ||
let command = "(" | ||
if(parameters.length) { | ||
let i = 0; | ||
command += `"${parameters[i].value}"` | ||
for(i = 1; i < parameters.length; i++) { | ||
command+=`,"${parameters[i].value}"`; | ||
} | ||
} | ||
if(options.payable) { | ||
const stringObj = `{value:${options.value * Math.pow(10,18)}}` | ||
command += parameters.length ?`,${stringObj}` : stringObj | ||
} | ||
command += ")" | ||
return command; | ||
} | ||
|
||
} | ||
|
||
function getCommand(name, params=[], options={}) { | ||
if(commands[name]) { | ||
commands.options = options | ||
//console.log("spread params are: ", ...params) | ||
return commands[name](...params) | ||
} | ||
} | ||
|
||
module.exports = getCommand |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
const helpers = { | ||
|
||
demuxStream(stream, output, error) { | ||
return new Promise((resolve, reject) => { | ||
let output = ''; | ||
let error = ''; | ||
let nextDataType = null; | ||
let nextDataLength = null; | ||
let buffer = Buffer.from(''); | ||
function processData(data) { | ||
if (data) { | ||
buffer = Buffer.concat([buffer, data]); | ||
} | ||
if (!nextDataType) { | ||
if (buffer.length >= 8) { | ||
let header = bufferSlice(8); | ||
nextDataType = header.readUInt8(0); | ||
nextDataLength = header.readUInt32BE(4); | ||
// It's possible we got a "data" that contains multiple messages | ||
// Process the next one | ||
processData(); | ||
} | ||
} else { | ||
if (buffer.length >= nextDataLength) { | ||
let content = bufferSlice(nextDataLength); | ||
if (nextDataType === 1) { | ||
output += content; | ||
} else { | ||
error += content | ||
} | ||
nextDataType = null; | ||
// It's possible we got a "data" that contains multiple messages | ||
// Process the next one | ||
processData(); | ||
} | ||
} | ||
} | ||
|
||
function bufferSlice(end) { | ||
let out = buffer.slice(0, end); | ||
buffer = Buffer.from(buffer.slice(end, buffer.length)); | ||
return out; | ||
} | ||
stream.on('data', (data) => { | ||
processData(data) | ||
}) | ||
stream.on('end', () => { | ||
resolve(output) | ||
}) | ||
}) | ||
}, | ||
regex: /([{,]\s*)(\S+)\s*(:)/mg, | ||
stringToJsonString(s) { | ||
console.log("converting string: ", s) | ||
return s.replace(this.regex, '$1"$2"$3') | ||
}, | ||
sanitizeGethStreamString(s) { | ||
return s.replace(/\.\.\./g, "").replace(/function\(\)/g, "\"function()\"").replace(/undefined/g, null) | ||
}, | ||
castGethParameters(value, type) { | ||
if(type === 'string' || type === 'address') { | ||
return `"${value}"` | ||
} | ||
return value | ||
} | ||
} | ||
|
||
module.exports = helpers; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
version: "3" | ||
|
||
services: | ||
seedemu-eth-client: | ||
build: . | ||
container_name: seedemu-eth-client | ||
volumes: | ||
- /var/run/docker.sock:/var/run/docker.sock | ||
ports: | ||
- 3000:3000 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
const Docker = require('dockerode') | ||
|
||
const docker = new Docker(); | ||
|
||
module.exports = docker; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
const express = require('express'); | ||
const handlebars = require('express-handlebars'); | ||
const path = require('path'); | ||
const bodyParser = require('body-parser'); | ||
|
||
const app = express(); | ||
const port = process.env.PORT; | ||
|
||
const indexRouter = require('./routes/index.ts'); | ||
const smartContractRouter = require('./routes/smartcontracts.ts'); | ||
|
||
app.engine('handlebars', handlebars()); | ||
app.set('view engine', 'handlebars'); | ||
|
||
app.use(express.static(path.join(__dirname, "/public"))); | ||
app.use(bodyParser.urlencoded({extended: false})) | ||
app.use(bodyParser.json()) | ||
|
||
app.use('/', indexRouter); | ||
app.use('/smartcontracts', smartContractRouter); | ||
|
||
|
||
app.listen(port, () => { | ||
console.log(`server started at http://localhost:${port}`) | ||
}) |
Oops, something went wrong.