Skip to content

Commit

Permalink
Merge pull request #1 from devicehive/development
Browse files Browse the repository at this point in the history
Development
  • Loading branch information
AntGrisha authored Jun 20, 2018
2 parents 8fa938e + 285e62a commit 5c23137
Show file tree
Hide file tree
Showing 22 changed files with 3,966 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/node_modules/
/contract/
128 changes: 128 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
# Devicehive plugin ethereum

This plugin allows you to manipulate your custom smart contract via devicehive.

# Before the start

You should have ethereum node running somewhere.
You also need ethereum account's address and password.
With this [guide](#Ethereum.docs) you can run ethereum node locally.

## Specify ethereum configuration

Firstly you should specify [ethereum configuration](#Ethereum.config).
Add ethereum url, account's address and account's password to config file *(path - ./src/ethereum-node/config.json)*.
<br/>
*Note* - you can use example to see how it works, just do not change other fields.

## Specify plugin configuration
In [plugin configuration](#Plugin.config) there are already [playground](https://playground.devicehive.com) urls, however you can run [devicehive](https://github.com/devicehive/devicehive-docker) locally and write your own.
Add plugin topic and access token. Also add user and password for [devicehive admin panel](https://github.com/devicehive/devicehive-admin-panel).

# Simple start

1. Create plugin (locally or on playground) and specify [plugin configuration](#Plugin.config) file
2. Specify [ethereum configuration](#Ethereum.config) file (plugin will start with contract in `example` folder)
3. Run `npm i`
4. Run `npm start`
5. Send [message](#Message.model) from device. See example [here](#Message.example).
6. Wait for plugin receives the message and sends transaction to blockchain.

Logger will notify you about results. You will see message `Transaction has been passed successfully, hash: ${transactionHash}`.

# Configuration

<a name="Plugin.config"></a>

## Plugin

You can find plugin configuration in `./config.json`
Plugin part of configuration you can find [here](https://github.com/devicehive/devicehive-plugin-core-node#configuration).

**_PLUGIN_PROPS_** - plugin's properties. There are only filters at the moment.
**_PLUGIN_PROPS.OVERRIDE_** - set it to true and plugin's filters will be updated according to config.
**_FILTERS_** - filters for your plugin.
**_LOGGER_** - logger configuration.

Examples:

"FILTERS":{
"notifications": true,
"commands": false,
"command_updates": false,
"names": "blockchain-record"
}

"LOGGER":{
"level": 0, // 0 - info + error, 1 - error
"filePath": "./dhe-log.txt"
}

<a name="Ethereum.config"></a>

## Ethereum smart contract

You can find configuration in `./src/ethereum-node/config.json`

* **_CONTRACT_PATH_** - path to your smart contract, <br />
* **_ETHEREUM_URL_** - url to ethereum node, <br />
* **_CONTRACT_INITIAL_ARGS_** - arguments for initializing smart contract, <br />
* **_ACCOUNT_ADDRESS_** - ethereum account address <br />
* **_ACCOUNT_PASSWORD_** - ethereum account password <br />
* **_GAS_LIMIT_** - maximum gas limit which can be used by device <br />
* **_TIME_PERIOD_** - time period in minutes, every `TIME_PERIOD` minutes gas limit will be updated <br />
* **_CONTRACT_ADDRESS_** - contract's address, which plugin will use <br />
* **_OVERRIDE_CONTRACT_** - set it to true, if you want to create new contract <br />
* **_ALLOWED_METHODS_** - methods, which can be used by device <br />

# Plugin parameters

After successfull creation of the contract plugin's parameters will be overwritten.<br />
They will store ethereum node url, contract's address, allowed methods and initial transaction's hash.

<a name="Message.example">

# Message example
Message name: `blockchain-record`
Parameters:
{
"method": "increase",
"args": {
"amount": 1
},
"options": {}
}

<a name="Message.model"></a>

# Message model
{
"method":*method_name*,
"args":{
"arg1",
"arg2",
...
},
"options":{
"gas", // optional
"gasPrice", // optional
"value"" // optional
}
}
*Note*: if gas or gasPrice are not specified then plugin will use min amount of gas for transaction.

<a name="Ethereum.docs"></a>

# How to run ethereum node locally

To start ethereum locally:

*Note* - with this guide you will run dev node, so you will not be working with real ethereum.

1. Download and install `geth`.
2. Open terminal and run `geth --mine --minerthreads=1 --networkid=1999 --rpc --rpcaddr "127.0.0.1" --rpcapi="admin,debug,miner,shh,txpool,personal,eth,net,web3" --dev`.
3. Open another terminal window and run `geth attach http://localhost:8545`.
4. In second window run `personal.newAccount()` and enter your password. You will get account's address.
5. Make sure you have enough ethereum. You can run `eth.accounts.forEach(function(account){if(account!==eth.coinbase){eth.sendTransaction({from:eth.coinbase,to:account,value:web3.toWei(1000000)})}})` to increase it on your account. You will see `undefined` in response. It means that transaction has been finished successfully.

*Note* - you can check your account's balance by entering `web3.fromWei(eth.getBalance(${ACCOUNT_ADDRESS}), "ether")` command.
29 changes: 29 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"DEVICE_HIVE_PLUGIN_WS_ENDPOINT": "ws://playground.devicehive.com/plugin/proxy",
"DEVICE_HIVE_AUTH_SERVICE_API_URL": "http://playground.devicehive.com/auth/rest",
"DEVICE_HIVE_MAIN_SERVICE_API_URL": "http://playground.devicehive.com/api/rest",
"PLUGIN_TOPIC": "",
"PLUGIN_TOKEN_LIFE_TIME_MIN": 60,
"USER_LOGIN": "",
"USER_PASSWORD": "",
"USER_ACCESS_TOKEN": "",
"USER_REFRESH_TOKEN": "",
"PLUGIN_ACCESS_TOKEN": "",
"PLUGIN_REFRESH_TOKEN": "",
"AUTO_SUBSCRIPTION_ON_START": true,
"SUBSCRIPTION_GROUP": "",

"PLUGIN_PROPS":{
"OVERRIDE": false,
"FILTERS":{
"notifications": true,
"commands": false,
"command_updates": false,
"names": "blockchain-record"
}
},
"LOGGER":{
"level": 0,
"filePath":"./dhe-log.txt"
}
}
4 changes: 4 additions & 0 deletions config/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
const configurator = require('json-evn-configurator');
const path = require('path');

module.exports = configurator(path.resolve(__dirname,'../config.json'));
27 changes: 27 additions & 0 deletions example/contracts/counter.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
pragma solidity ^0.4.21;

contract CounterContract {

address public owner;
int64 count;

constructor(int64 _count) public {
owner = msg.sender;
count = _count;
}
function increase() public {
count++;
}

function increase(int64 amount) public {
count += amount;
}

function getCount() public view returns( int64 ) {
return count;
}

function setCount(int64 _count) public {
count = _count;
}
}
54 changes: 54 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
const { DeviceHivePlugin } = require(`devicehive-plugin-core`);

const log = require('./src/utils/Logger');
const pluginConfig = require('./config/index');
const ethereumConfig = require('./src/ethereum-node/config.json');
const EthereumAccount = require('./src/ethereum-node/EthereumAccount');
const PluginContract = require('./src/ethereum-node/PluginContract');
const PluginEthereumService = require('./src/PluginEthereumService');
const DeviceHiveService = require('./src/service/DeviceHiveService');
const PluginEntity = require('./src/entities/plugin/PluginEntity');
const PluginFilters = require('./src/entities/plugin/PluginFilters');

const deviceHiveService = new DeviceHiveService(pluginConfig);

deviceHiveService.init().then(() => {
return deviceHiveService.getPluginByTopic(pluginConfig.PLUGIN_TOPIC);
}).then(plugin => {

if (pluginConfig.PLUGIN_PROPS.OVERRIDE || plugin.parameters.updateToConfig(ethereumConfig)){
plugin.setStatus(PluginEntity.STATUSES.DISABLED);

if (pluginConfig.PLUGIN_PROPS.OVERRIDE){
plugin.filter.setFiltersFromConfig(pluginConfig.PLUGIN_PROPS.FILTERS);
}

return deviceHiveService.updatePlugin(plugin);
}

return plugin;

}).then(plugin => {
if (plugin.status === PluginEntity.STATUSES.DISABLED) {
plugin.setStatus(PluginEntity.STATUSES.ACTIVE);
return deviceHiveService.updatePlugin(plugin);
}
return plugin;
}).then(plugin => {
const params = plugin.parameters;

const account = new EthereumAccount(params.nodeUrl, ethereumConfig.ACCOUNT_ADDRESS, ethereumConfig.ACCOUNT_PASSWORD);
const contract = new PluginContract(account);

contract.init(ethereumConfig.CONTRACT_PATH, params, ethereumConfig.CONTRACT_INITIAL_ARGS).then(() => {
if (contract.address !== params.contractAddress) {
log.info(`New contract has been created. Address: ${contract.address}`);
params.setContractAddress(contract.address);
params.setInitialTransactionHash(contract.getInitialTransactionHash());
deviceHiveService.updatePluginParameters(plugin.topicName, params);
}
const pluginEthereumService = new PluginEthereumService(contract);
DeviceHivePlugin.start(pluginEthereumService, pluginConfig);
})
.catch(err => log.error(err));
}).catch(err => log.error(err));
Loading

0 comments on commit 5c23137

Please sign in to comment.