Skip to content

Commit

Permalink
Merge branch 'development' into Master
Browse files Browse the repository at this point in the history
Naming the version as 0.1
  • Loading branch information
kevin-w-du committed Jan 18, 2022
2 parents d8a11d0 + d9b3910 commit e0d3fa0
Show file tree
Hide file tree
Showing 50 changed files with 2,683 additions and 48 deletions.
1 change: 1 addition & 0 deletions blockchain-client/src/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
46 changes: 46 additions & 0 deletions blockchain-client/src/DockerOdeWrapper.ts
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;
6 changes: 6 additions & 0 deletions blockchain-client/src/Dockerfile
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"]
51 changes: 51 additions & 0 deletions blockchain-client/src/apis.ts
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;
104 changes: 104 additions & 0 deletions blockchain-client/src/commands.ts
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
68 changes: 68 additions & 0 deletions blockchain-client/src/common/helpers.ts
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;
10 changes: 10 additions & 0 deletions blockchain-client/src/docker-compose.yml
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
5 changes: 5 additions & 0 deletions blockchain-client/src/docker/index.ts
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;
25 changes: 25 additions & 0 deletions blockchain-client/src/index.ts
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}`)
})
Loading

0 comments on commit e0d3fa0

Please sign in to comment.