forked from hyperledger-iroha/iroha-dco
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Feature/swig node (hyperledger-iroha#1098)
* First attempt to add NodeJS Swig bindings. Signed-off-by: luckychess <[email protected]> * Feature: Shared Library for NodeJS Signed-off-by: Vyacheslav Bikbaev <[email protected]> * chore: standard styleguide Signed-off-by: Vyacheslav Bikbaev <[email protected]> * Add readme for nodejs; fix .gitignore. Signed-off-by: luckychess <[email protected]> * Rename FindNodejs.cmake module * Add initial files for NPM package * Copy build configuration from example/node folder * Change base repo and add contributors to package.json * Ignore build and generated directories * Copy example code from example/node * Fix old-fashion style (as example/node) bild * Fix broken SWIG compilation * Add build dependencies * Add folder structure for binary module * Link binding.gyp targets with package.json * Add module's main js file * Ignore generated directories in Git * Return prepare.sh functionality * Add bunch of develop scripts (prebuild, generate, etc) * Fix example * Add shared_model target to build irohanode shared lib by prebuild.sh * Fix path of Iroha build dir * Autorefactor bindings.gyp * Implement prebuild.sh functionality in GYP manner * Add node-pre-gyp-github publishing. Include pb into NPM module. * Fix CMake configuration to generate irohanode as static lib Signed-off-by: Arseniy Fokin <[email protected]> * Link Iroha and third-party libs statically Signed-off-by: Arseniy Fokin <[email protected]> * Add xcode_settings for Mac Signed-off-by: Arseniy Fokin <[email protected]> * Fix SWIG target name Signed-off-by: Arseniy Fokin <[email protected]> * Unignore pb directory for packaging by NPM Signed-off-by: Arseniy Fokin <[email protected]> * Add build section to README.md Signed-off-by: Arseniy Fokin <[email protected]> * Remove publishing on prepare script Signed-off-by: Arseniy Fokin <[email protected]> * Fix .npmignore of protobuf generated files Signed-off-by: Arseniy Fokin <[email protected]> * Fix get processor configuration on Mac Signed-off-by: Arseniy Fokin <[email protected]> * Disable ccache-swig target Signed-off-by: Arseniy Fokin <[email protected]> * Increment package version Signed-off-by: Arseniy Fokin <[email protected]> * Remove user-defined PROTOBUF_INSTALL_DIR from build process Signed-off-by: Arseniy Fokin <[email protected]> * Add missing Boost headers dependency to Shared Model build system Signed-off-by: Arseniy Fokin <[email protected]> * Add README section for Mac users Signed-off-by: Arseniy Fokin <[email protected]> * Delete unnecessary local build configuration files Signed-off-by: Arseniy Fokin <[email protected]> * Fix example to use iroha-lib package Signed-off-by: Arseniy Fokin <[email protected]> * Update contributors and restrictions of the package Signed-off-by: Arseniy Fokin <[email protected]> * Generate protobufs in single line Signed-off-by: Arseniy Fokin <[email protected]> * Update READMEs Signed-off-by: Arseniy Fokin <[email protected]> * Fix NPM scripts Signed-off-by: Arseniy Fokin <[email protected]> * Start generate-protobuf.sh automatically on npm install Signed-off-by: Arseniy Fokin <[email protected]> * Fixes according Warchant's review on PR hyperledger-iroha#939 Signed-off-by: Arseniy Fokin <[email protected]> * Fix clean.sh - it needs to delete only generated content Signed-off-by: Arseniy Fokin <[email protected]> * Delete outdated prepare.sh from example folder Signed-off-by: Arseniy Fokin <[email protected]> * Add node-gyp as devDependency to allow MacOS builds Signed-off-by: Arseniy Fokin <[email protected]> * Return ccache support in FindSWIG module Signed-off-by: Arseniy Fokin <[email protected]> * Add minimal version of iroha-lib as v0.0.1 Signed-off-by: Arseniy Fokin <[email protected]> * Fix bindings.gyp after merge with new develop Signed-off-by: Arseniy Fokin <[email protected]> * Changes according @luckychess review Signed-off-by: Arseniy Fokin <[email protected]> * Changes according @laSinteZ review Signed-off-by: Arseniy Fokin <[email protected]> * Get prebuilt sources from official Hyperledger repository Signed-off-by: Arseniy Fokin <[email protected]>
- Loading branch information
1 parent
cb4ee11
commit 9b7b2ea
Showing
20 changed files
with
1,214 additions
and
1 deletion.
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
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,96 @@ | ||
# Macro to add directory to NODEJS_INCLUDE_DIRS if it exists and is not /usr/include | ||
macro(add_include_dir dir) | ||
if (IS_DIRECTORY ${dir} AND NOT ${dir} STREQUAL "/usr/include") | ||
set(NODEJS_INCLUDE_DIRS ${NODEJS_INCLUDE_DIRS} ${dir}) | ||
endif() | ||
endmacro() | ||
|
||
|
||
find_program (NODEJS_EXECUTABLE NAMES node nodejs | ||
HINTS | ||
$ENV{NODE_DIR} | ||
PATH_SUFFIXES bin | ||
DOC "Node.js interpreter" | ||
) | ||
|
||
include (FindPackageHandleStandardArgs) | ||
|
||
# If compat-libuv package exists, it must be at start of include path | ||
find_path (UV_ROOT_DIR "uv.h" PATHS /usr/include/compat-libuv010 NO_DEFAULT_PATH) | ||
if (UV_ROOT_DIR) | ||
# set (NODEJS_INCLUDE_DIRS ${UV_ROOT_DIR}) | ||
add_include_dir(${UV_ROOT_DIR}) | ||
endif() | ||
|
||
# Now look for node. Flag an error if not found | ||
find_path (NODE_ROOT_DIR "include/node/node.h" "include/src/node.h" "src/node.h" | ||
PATHS /usr/include/nodejs /usr/local/include/nodejs /usr/local/include) | ||
if (NODE_ROOT_DIR) | ||
add_include_dir(${NODE_ROOT_DIR}/include/src) | ||
add_include_dir(${NODE_ROOT_DIR}/src) | ||
add_include_dir(${NODE_ROOT_DIR}/include/node) | ||
add_include_dir(${NODE_ROOT_DIR}/include/deps/v8/include) | ||
add_include_dir(${NODE_ROOT_DIR}/deps/v8/include) | ||
add_include_dir(${NODE_ROOT_DIR}/include/deps/uv/include) | ||
add_include_dir(${NODE_ROOT_DIR}/deps/uv/include) | ||
else() | ||
unset(NODEJS_INCLUDE_DIRS) | ||
message(FATAL_ERROR " - node.h not found") | ||
endif() | ||
|
||
# Check that v8.h is in NODEJS_INCLUDE_DIRS | ||
find_path (V8_ROOT_DIR "v8.h" PATHS ${NODEJS_INCLUDE_DIRS}) | ||
if (NOT V8_ROOT_DIR) | ||
unset(NODEJS_INCLUDE_DIRS) | ||
message(FATAL_ERROR " - v8.h not found") | ||
endif() | ||
|
||
# Check that uv.h is in NODEJS_INCLUDE_DIRS | ||
find_path (UV_ROOT_DIR "uv.h" PATHS ${NODEJS_INCLUDE_DIRS}) | ||
if (NOT UV_ROOT_DIR) | ||
unset(NODEJS_INCLUDE_DIRS) | ||
message(FATAL_ERROR " - uv.h not found") | ||
endif() | ||
|
||
find_package_handle_standard_args (Nodejs DEFAULT_MSG | ||
NODEJS_EXECUTABLE | ||
NODEJS_INCLUDE_DIRS | ||
) | ||
|
||
if (NODEJS_EXECUTABLE) | ||
execute_process(COMMAND ${NODEJS_EXECUTABLE} --version | ||
OUTPUT_VARIABLE _VERSION | ||
RESULT_VARIABLE _NODE_VERSION_RESULT) | ||
execute_process(COMMAND ${NODEJS_EXECUTABLE} -e "console.log(process.versions.v8)" | ||
OUTPUT_VARIABLE _V8_VERSION | ||
RESULT_VARIABLE _V8_RESULT) | ||
if (NOT _NODE_VERSION_RESULT AND NOT _V8_RESULT) | ||
string (REPLACE "v" "" NODE_VERSION_STRING "${_VERSION}") | ||
string (REPLACE "." ";" _VERSION_LIST "${NODE_VERSION_STRING}") | ||
list (GET _VERSION_LIST 0 NODE_VERSION_MAJOR) | ||
list (GET _VERSION_LIST 1 NODE_VERSION_MINOR) | ||
list (GET _VERSION_LIST 2 NODE_VERSION_PATCH) | ||
set (V8_VERSION_STRING ${_V8_VERSION}) | ||
string (REPLACE "." ";" _V8_VERSION_LIST "${_V8_VERSION}") | ||
list (GET _V8_VERSION_LIST 0 V8_VERSION_MAJOR) | ||
list (GET _V8_VERSION_LIST 1 V8_VERSION_MINOR) | ||
list (GET _V8_VERSION_LIST 2 V8_VERSION_PATCH) | ||
# we end up with a nasty newline so strip everything that isn't a number | ||
string (REGEX MATCH "^[0-9]*" V8_VERSION_PATCH ${V8_VERSION_PATCH}) | ||
else () | ||
set (NODE_VERSION_STRING "0.10.30") | ||
set (NODE_VERSION_MAJOR "0") | ||
set (NODE_VERSION_MINOR "10") | ||
set (NODE_VERSION_PATCH "30") | ||
set (V8_VERSION_MAJOR "3") | ||
set (V8_VERSION_MINOR"14") | ||
set (V8_VERSION_PATCH "5") | ||
set (V8_VERSION_STRING "3.28.72") | ||
message (STATUS "defaulted to node 0.10.30") | ||
endif () | ||
string (REGEX REPLACE "\n" "" NODE_VERSION_STRING ${NODE_VERSION_STRING}) | ||
string (REGEX REPLACE "\n" "" V8_VERSION_STRING ${V8_VERSION_STRING}) | ||
message (STATUS "INFO - Node version is " ${NODE_VERSION_STRING}) | ||
message (STATUS "INFO - Node using v8 " ${V8_VERSION_STRING}) | ||
mark_as_advanced (NODEJS_EXECUTABLE) | ||
endif () |
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,61 @@ | ||
# Logs | ||
logs | ||
*.log | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
|
||
# Runtime data | ||
pids | ||
*.pid | ||
*.seed | ||
*.pid.lock | ||
|
||
# Directory for instrumented libs generated by jscoverage/JSCover | ||
lib-cov | ||
|
||
# Coverage directory used by tools like istanbul | ||
coverage | ||
|
||
# nyc test coverage | ||
.nyc_output | ||
|
||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) | ||
.grunt | ||
|
||
# Bower dependency directory (https://bower.io/) | ||
bower_components | ||
|
||
# node-waf configuration | ||
.lock-wscript | ||
|
||
# Compiled binary addons (http://nodejs.org/api/addons.html) | ||
build/Release | ||
|
||
# Dependency directories | ||
node_modules/ | ||
jspm_packages/ | ||
|
||
# Typescript v1 declaration files | ||
typings/ | ||
|
||
# Optional npm cache directory | ||
.npm | ||
|
||
# Optional eslint cache | ||
.eslintcache | ||
|
||
# Optional REPL history | ||
.node_repl_history | ||
|
||
# Output of 'npm pack' | ||
*.tgz | ||
|
||
# Yarn Integrity file | ||
.yarn-integrity | ||
|
||
# dotenv environment variables file | ||
.env | ||
|
||
# NPM lockfile | ||
package-lock.json |
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,30 @@ | ||
# NodeJS client library example | ||
|
||
## Prerequisites | ||
|
||
1. Make sure you have running iroha on your machine. You can follow [this](https://hyperledger.github.io/iroha-api/#run-the-daemon-irohad) guide to launch iroha daemon. Please use keys for iroha from *iroha/example* folder, since this example uses keys from there. | ||
|
||
2. If you are a lucky owner of a processor with the x64 architecture, you can install **iroha-lib** from the NPM repository with a simple command: | ||
|
||
```sh | ||
npm install iroha-lib | ||
``` | ||
|
||
In other cases, you need to download the complete Iroha repository (in which you are now), go to the *shared_model/packages/javascript* folder and build the package on your system manually using the instructions from **README.md**. | ||
In such case, you need to change the import paths in this example to *shared_model/packages/javascript*. | ||
|
||
## Launch example | ||
|
||
Script `index.js` does the following: | ||
1. Assemble transaction from several commands using tx builder | ||
2. Sign it using keys from iroha/example folder | ||
3. Send it to iroha | ||
4. Wait 5 secs and check transaction's status using its hash | ||
5. Assemble query using query builder | ||
6. Send query to iroha | ||
7. Read query response | ||
|
||
Launch it: | ||
```sh | ||
node index.js | ||
``` |
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,185 @@ | ||
/** | ||
* Copyright 2018 HUAWEI. All Rights Reserved. | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* | ||
*/ | ||
|
||
'use strict' | ||
|
||
function blob2array (blob) { | ||
var bytearray = new Uint8Array(blob.size()) | ||
for (let i = 0; i < blob.size(); ++i) { | ||
bytearray[i] = blob.get(i) | ||
} | ||
return bytearray | ||
} | ||
|
||
var iroha = require('iroha-lib') | ||
var txBuilder = new iroha.ModelTransactionBuilder() | ||
var queryBuilder = new iroha.ModelQueryBuilder() | ||
var crypto = new iroha.ModelCrypto() | ||
var protoTxHelper = new iroha.ModelProtoTransaction() | ||
var protoQueryHelper = new iroha.ModelProtoQuery() | ||
var fs = require('fs') | ||
var adminPriv = fs.readFileSync('../[email protected]').toString() | ||
var adminPub = fs.readFileSync('../[email protected]').toString() | ||
|
||
var keys = crypto.convertFromExisting(adminPub, adminPriv) | ||
|
||
var currentTime = Date.now() | ||
var startTxCounter = 1 | ||
var startQueryCounter = 1 | ||
var creator = 'admin@test' | ||
|
||
// build transaction | ||
var tx = txBuilder | ||
.creatorAccountId(creator) | ||
.txCounter(startTxCounter) | ||
.createdTime(currentTime) | ||
.createDomain('ru', 'user') | ||
.createAsset('dollar', 'ru', 2) | ||
.build() | ||
|
||
// sign transaction and get its binary representation (Blob) | ||
var txblob = protoTxHelper.signAndAddSignature(tx, keys).blob() | ||
var txArray = blob2array(txblob) | ||
// create proto object and send to iroha | ||
var blockTransaction = require('iroha-lib/pb/block_pb.js').Transaction // block_pb2.Transaction() | ||
var protoTx = blockTransaction.deserializeBinary(txArray) | ||
console.log(protoTx.getPayload().getCreatorAccountId()) | ||
|
||
var grpc = require('grpc') | ||
var endpointGrpc = require('iroha-lib/pb/endpoint_grpc_pb.js') | ||
var client = new endpointGrpc.CommandServiceClient( | ||
'localhost:50051', | ||
grpc.credentials.createInsecure() | ||
) | ||
var txHashBlob = tx.hash().blob() | ||
var txHash = blob2array(txHashBlob) | ||
var p = new Promise((resolve, reject) => { | ||
console.log('Submit transaction...') | ||
client.torii(protoTx, (err, data) => { | ||
if (err) { | ||
reject(err) | ||
} else { | ||
console.log('Submitted transaction successfully') | ||
resolve() | ||
} | ||
}) | ||
}) | ||
|
||
p | ||
.then(() => { | ||
console.log('Sleep 5 seconds...') | ||
return sleep(5000) | ||
}) | ||
.then(() => { | ||
console.log('Send transaction status request...') | ||
return new Promise((resolve, reject) => { | ||
// create status request | ||
var endpointPb = require('iroha-lib/pb/endpoint_pb.js') | ||
var request = new endpointPb.TxStatusRequest() | ||
request.setTxHash(txHash) | ||
client.status(request, (err, response) => { | ||
if (err) { | ||
reject(err) | ||
} else { | ||
let status = response.getTxStatus() | ||
let TxStatus = require('iroha-lib/pb/endpoint_pb.js').TxStatus | ||
let statusName = getProtoEnumName( | ||
TxStatus, | ||
'iroha.protocol.TxStatus', | ||
status | ||
) | ||
console.log('Got transaction status: ' + statusName) | ||
if (statusName !== 'COMMITTED') { | ||
reject(new Error("Your transaction wasn't committed")) | ||
} else { | ||
resolve() | ||
} | ||
} | ||
}) | ||
}) | ||
}) | ||
.then(() => { | ||
console.log('Query transaction...') | ||
let query = queryBuilder | ||
.creatorAccountId(creator) | ||
.createdTime(Date.now()) | ||
.queryCounter(startQueryCounter) | ||
.getAssetInfo('dollar#ru') | ||
.build() | ||
let queryBlob = protoQueryHelper.signAndAddSignature(query, keys).blob() | ||
let pbQuery = require('iroha-lib/pb/queries_pb.js').Query | ||
let queryArray = blob2array(queryBlob) | ||
let protoQuery = pbQuery.deserializeBinary(queryArray) | ||
let client = new endpointGrpc.QueryServiceClient( | ||
'localhost:50051', | ||
grpc.credentials.createInsecure() | ||
) | ||
return new Promise((resolve, reject) => { | ||
client.find(protoQuery, (err, response) => { | ||
if (err) { | ||
reject(err) | ||
} else { | ||
console.log('Submitted transaction successfully') | ||
let type = response.getResponseCase() | ||
let responsePb = require('iroha-lib/pb/responses_pb.js') | ||
let name = getProtoEnumName( | ||
responsePb.QueryResponse.ResponseCase, | ||
'iroha.protocol.QueryResponse', | ||
type | ||
) | ||
if (name !== 'ASSET_RESPONSE') { | ||
reject(new Error('Query response error')) | ||
} else { | ||
let asset = response.getAssetResponse().getAsset() | ||
console.log( | ||
'Asset Id = ' + | ||
asset.getAssetId() + | ||
' , Precision = ' + | ||
asset.getPrecision() | ||
) | ||
resolve() | ||
} | ||
} | ||
}) | ||
}) | ||
}) | ||
.then(() => { | ||
console.log('done!') | ||
}) | ||
.catch(err => { | ||
console.log(err) | ||
}) | ||
|
||
function sleep (ms) { | ||
return new Promise(resolve => setTimeout(resolve, ms)) | ||
} | ||
|
||
var protoEnumName = {} | ||
function getProtoEnumName (obj, key, value) { | ||
if (protoEnumName.hasOwnProperty(key)) { | ||
if (protoEnumName[key].length < value) { | ||
return 'unknown' | ||
} else { | ||
return protoEnumName[key][value] | ||
} | ||
} else { | ||
protoEnumName[key] = [] | ||
for (var k in obj) { | ||
let idx = obj[k] | ||
if (isNaN(idx)) { | ||
console.log( | ||
'getProtoEnumName:wrong enum value, now is type of ' + | ||
typeof idx + | ||
' should be integer' | ||
) | ||
} else { | ||
protoEnumName[key][idx] = k | ||
} | ||
} | ||
return getProtoEnumName(obj, key, value) | ||
} | ||
} |
Oops, something went wrong.