├── .cfignore
├── .gitignore
├── .project
├── README.md
├── app.js
├── build
├── binding.sln
├── binding.vcxproj
├── binding.vcxproj.filters
└── config.gypi
├── chaincodes
├── chaincodes.zip
└── query.go
├── config
├── express.js
├── hyperledgerfc.js
├── ibm-blockchain.js
└── setup.js
├── docs
├── contractviolated.png
├── creatingAsset.png
├── dashboard.png
├── events.png
├── history.png
├── intro.png
├── payloads.png
└── smartcontract.png
├── env
├── env.json
├── local_env.json
├── server_env.json
└── uk_env.json
├── manifest.yml
├── package.json
├── public
├── images
│ ├── CatToast1.gif
│ ├── CatToast2.gif
│ ├── Underground.png
│ ├── blockchain.png
│ ├── blockchain_icon.png
│ ├── error.png
│ ├── gears.gif
│ ├── pallete.png
│ ├── player1.png
│ ├── player2.png
│ └── player3.png
├── index.html
├── js
│ ├── animation.js
│ ├── demo.js
│ └── mqttClient.js
└── stylesheets
│ └── style.css
├── rest
├── api.js
├── blockchain.js
└── listener.js
└── routes
└── events.js
/.cfignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | build/
3 | .vscode/
4 | .project
5 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | build/
3 | .vscode/
4 | .project
5 | env/
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | nodejshelloworld
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | org.nodeclipse.ui.NodeNature
13 | org.eclipse.wst.jsdt.core.jsNature
14 |
15 |
16 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Blockchain Go Demo
2 |
3 | ## About Blockchain Go
4 | - The underlying network for this application is the [Hyperledger Fabric](https://github.com/hyperledger/fabric/tree/master/docs), a Linux Foundation project. You may want to review these instructions to understand a bit about the Hyperledger Fabric.
5 | - **This demo purpose is to basically aid to any people to comprehend about how a blockchain network can be addressed into an existing business process model.**
6 | - **This demo uses Hyperledger Fabric v0.6 (Not supported anymore in bluemix).**
7 |
8 | # Application Background
9 |
10 | We have three companies whose handles the same package (asset) through their supply chains and, all of those agreed to comply with terms and rules
11 | to handle that asset.
12 |
13 | The challenge is on ensuring the integrity of these package through all the supply chain process, since it's hard to tell accuratelly who's the responsible party at real time, but we have a solution!
14 |
15 | 
16 |
17 | First we create a new package for transport and eventual transfers:
18 |
19 | 
20 |
21 | So getting hand over a "smart contract" adhered by all the participants companies (Industry, Shipping Company and the Customer) we apply the rules:
22 |
23 | 
24 |
25 | With simulated temperature sensors in our virtual package (We could - and did so - run it on real devices), we're publishing payloads to the subscriber application (You're watching the demo through it ):
26 |
27 | 
28 |
29 | This application perform requests to the service that holds communication with our blockchain network:
30 |
31 |  
32 |
33 | As our "Chain Participants" share the visibility about those information, our application notifies all of the participants about the events from the blockchain network:
34 |
35 | 
36 |
37 | We have available an immutable history about the transactions from the blockchain ledger:
38 |
39 | 
40 |
41 |
42 | Powered by IBM Blockchain
43 |
44 | Author: Vitor Diego
45 | - IBM Garage São Paulo
46 |
47 |
48 |
--------------------------------------------------------------------------------
/app.js:
--------------------------------------------------------------------------------
1 | /*------------------------------------------------------------------------------
2 | * Copyright 2016 IBM Corp. All Rights Reserved.
3 | * Node.js server for Blockchain-Go demo
4 | * first implementation by Vitor Diego
5 | *------------------------------------------------------------------------------*/
6 |
7 | 'use strict'
8 |
9 | const app = require('./config/express')();
10 | const rest = require('./rest/blockchain');
11 | const start = require('./config/setup').startNetwork();
12 | const cfenv = require('cfenv');
13 | const appEnv = cfenv.getAppEnv();
14 | //const start = require('./config/ibm-blockchain.js').startNetwork();
15 | //const start = require('./config/hyperledgerfc.js').startNetwork();
16 |
17 | app.get('/', function(req, res) {
18 | res.render("index");
19 | });
20 |
21 | app.post('/request', function(req, res) {
22 | if (req.body !== null && req.body !== undefined) {
23 | console.log(`[app] handling request: ${req}`);
24 | rest.action(req.body, res);
25 | } else {
26 | res.send('invalid request');
27 | }
28 | });
29 |
30 | //temporary way(without routes)
31 | setTimeout(function() {
32 | let deploy = 0;
33 | app.get('/blockchain', function(req, res) {
34 | let blockchain = require('./rest/listener').blockdata();
35 | if (deploy < 1) {
36 | console.log(`isInit ${deploy}`);
37 | blockchain.isInit = true;
38 | deploy = 1;
39 | }
40 | res.send(blockchain);
41 | });
42 |
43 | let genesis = require('./rest/listener').deployed();
44 | app.get('/genesis', function(req, res) {
45 | genesis.isDeploy = true;
46 | res.send(genesis);
47 | });
48 | }, 10000);
49 |
50 | // start server on the specified port and binding host appEnv.port
51 | app.listen(appEnv.port, '0.0.0.0', function() {
52 | // print a message when the server starts listening
53 | console.log("server starting on " + appEnv.url);
54 | });
55 |
56 |
--------------------------------------------------------------------------------
/build/binding.sln:
--------------------------------------------------------------------------------
1 | Microsoft Visual Studio Solution File, Format Version 12.00
2 | # Visual Studio 2015
3 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "binding", "binding.vcxproj", "{93A34A77-B429-D1D5-D79D-88D2D03365AC}"
4 | EndProject
5 | Global
6 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
7 | Debug|x64 = Debug|x64
8 | Release|x64 = Release|x64
9 | EndGlobalSection
10 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
11 | {93A34A77-B429-D1D5-D79D-88D2D03365AC}.Debug|x64.ActiveCfg = Debug|x64
12 | {93A34A77-B429-D1D5-D79D-88D2D03365AC}.Debug|x64.Build.0 = Debug|x64
13 | {93A34A77-B429-D1D5-D79D-88D2D03365AC}.Release|x64.ActiveCfg = Release|x64
14 | {93A34A77-B429-D1D5-D79D-88D2D03365AC}.Release|x64.Build.0 = Release|x64
15 | EndGlobalSection
16 | GlobalSection(SolutionProperties) = preSolution
17 | HideSolutionNode = FALSE
18 | EndGlobalSection
19 | EndGlobal
20 |
--------------------------------------------------------------------------------
/build/binding.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | x64
7 |
8 |
9 | Release
10 | x64
11 |
12 |
13 |
14 | {93A34A77-B429-D1D5-D79D-88D2D03365AC}
15 | Win32Proj
16 | binding
17 | true
18 | x64
19 |
20 |
21 |
22 | DynamicLibrary
23 |
24 |
25 | v140
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | $(ExecutablePath);$(MSBuildProjectDirectory)\..\bin\;$(MSBuildProjectDirectory)\..\bin\
36 | true
37 | $(Configuration)\obj\$(ProjectName)\
38 | false
39 | true
40 | $(SolutionDir)$(Configuration)\
41 | .node
42 | .node
43 | .node
44 | .node
45 | $(ProjectName)
46 | $(OutDir)\$(ProjectName).node
47 |
48 |
49 |
50 | C:\Users\IBM_ADMIN\.node-gyp\6.9.1\include\node;C:\Users\IBM_ADMIN\.node-gyp\6.9.1\src;C:\Users\IBM_ADMIN\.node-gyp\6.9.1\deps\uv\include;C:\Users\IBM_ADMIN\.node-gyp\6.9.1\deps\v8\include;%(AdditionalIncludeDirectories)
51 | EnableFastChecks
52 | true
53 | false
54 | ProgramDatabase
55 | 4351;4355;4800;4251;%(DisableSpecificWarnings)
56 | false
57 | false
58 | false
59 | Disabled
60 | NotUsing
61 | NODE_GYP_MODULE_NAME=binding;USING_UV_SHARED=1;USING_V8_SHARED=1;V8_DEPRECATION_WARNINGS=1;WIN32;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_HAS_EXCEPTIONS=0;BUILDING_NODE_EXTENSION;DEBUG;_DEBUG;%(PreprocessorDefinitions)
62 | MultiThreadedDebug
63 | true
64 | true
65 | false
66 | Level3
67 |
68 |
69 | kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;DelayImp.lib;"C:\Users\IBM_ADMIN\.node-gyp\6.9.1\$(Configuration)\node.lib"
70 | /ignore:4199 %(AdditionalOptions)
71 | true
72 | true
73 | iojs.exe;node.exe;%(DelayLoadDLLs)
74 | true
75 | true
76 | true
77 | $(OutDir)$(ProjectName).node
78 | true
79 | true
80 | .node
81 | MachineX64
82 |
83 |
84 | C:\Users\IBM_ADMIN\.node-gyp\6.9.1\include\node;C:\Users\IBM_ADMIN\.node-gyp\6.9.1\src;C:\Users\IBM_ADMIN\.node-gyp\6.9.1\deps\uv\include;C:\Users\IBM_ADMIN\.node-gyp\6.9.1\deps\v8\include;%(AdditionalIncludeDirectories)
85 | NODE_GYP_MODULE_NAME=binding;USING_UV_SHARED=1;USING_V8_SHARED=1;V8_DEPRECATION_WARNINGS=1;WIN32;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_HAS_EXCEPTIONS=0;BUILDING_NODE_EXTENSION;DEBUG;_DEBUG;%(PreprocessorDefinitions);%(PreprocessorDefinitions)
86 |
87 |
88 |
89 |
90 | C:\Users\IBM_ADMIN\.node-gyp\6.9.1\include\node;C:\Users\IBM_ADMIN\.node-gyp\6.9.1\src;C:\Users\IBM_ADMIN\.node-gyp\6.9.1\deps\uv\include;C:\Users\IBM_ADMIN\.node-gyp\6.9.1\deps\v8\include;%(AdditionalIncludeDirectories)
91 | /MP %(AdditionalOptions)
92 | true
93 | false
94 | ProgramDatabase
95 | 4351;4355;4800;4251;%(DisableSpecificWarnings)
96 | false
97 | Speed
98 | true
99 | AnySuitable
100 | true
101 | true
102 | Full
103 | NotUsing
104 | NODE_GYP_MODULE_NAME=binding;USING_UV_SHARED=1;USING_V8_SHARED=1;V8_DEPRECATION_WARNINGS=1;WIN32;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_HAS_EXCEPTIONS=0;BUILDING_NODE_EXTENSION;%(PreprocessorDefinitions)
105 | MultiThreaded
106 | false
107 | true
108 | true
109 | false
110 | Level3
111 | true
112 |
113 |
114 | /LTCG %(AdditionalOptions)
115 |
116 |
117 | kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;DelayImp.lib;"C:\Users\IBM_ADMIN\.node-gyp\6.9.1\$(Configuration)\node.lib"
118 | /ignore:4199 %(AdditionalOptions)
119 | true
120 | true
121 | iojs.exe;node.exe;%(DelayLoadDLLs)
122 | true
123 | true
124 | true
125 | UseLinkTimeCodeGeneration
126 | true
127 | true
128 | $(OutDir)$(ProjectName).node
129 | true
130 | true
131 | .node
132 | MachineX64
133 |
134 |
135 | C:\Users\IBM_ADMIN\.node-gyp\6.9.1\include\node;C:\Users\IBM_ADMIN\.node-gyp\6.9.1\src;C:\Users\IBM_ADMIN\.node-gyp\6.9.1\deps\uv\include;C:\Users\IBM_ADMIN\.node-gyp\6.9.1\deps\v8\include;%(AdditionalIncludeDirectories)
136 | NODE_GYP_MODULE_NAME=binding;USING_UV_SHARED=1;USING_V8_SHARED=1;V8_DEPRECATION_WARNINGS=1;WIN32;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_HAS_EXCEPTIONS=0;BUILDING_NODE_EXTENSION;%(PreprocessorDefinitions);%(PreprocessorDefinitions)
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
--------------------------------------------------------------------------------
/build/binding.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {739DB09A-CC57-A953-A6CF-F64FA08E4FA7}
6 |
7 |
8 | {7B735499-E5DD-1C2B-6C26-70023832A1CF}
9 |
10 |
11 | {92EF4BA8-6BC2-65D1-451F-28EBD4AE726A}
12 |
13 |
14 | {A3C8E949-BCF6-0C67-6656-340A2A097708}
15 |
16 |
17 | {56DF7A98-063D-FB9D-485C-089023B4C16A}
18 |
19 |
20 | {741E0E76-39B2-B1AB-9FA1-F1A20B16F295}
21 |
22 |
23 | {56DF7A98-063D-FB9D-485C-089023B4C16A}
24 |
25 |
26 | {77348C0E-2034-7791-74D5-63C077DF5A3B}
27 |
28 |
29 | {8CDEE807-BC53-E450-C8B8-4DEBB66742D4}
30 |
31 |
32 | {739DB09A-CC57-A953-A6CF-F64FA08E4FA7}
33 |
34 |
35 |
36 |
37 | ..
38 |
39 |
40 | C:\Program Files\nodejs\node_modules\npm\node_modules\node-gyp\src
41 |
42 |
43 | ..
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/build/config.gypi:
--------------------------------------------------------------------------------
1 | # Do not edit. File was generated by node-gyp's "configure" step
2 | {
3 | "target_defaults": {
4 | "cflags": [],
5 | "default_configuration": "Release",
6 | "defines": [],
7 | "include_dirs": [],
8 | "libraries": []
9 | },
10 | "variables": {
11 | "asan": 0,
12 | "debug_devtools": "node",
13 | "force_dynamic_crt": 0,
14 | "host_arch": "x64",
15 | "icu_data_file": "icudt57l.dat",
16 | "icu_data_in": "..\\..\\deps/icu-small\\source/data/in\\icudt57l.dat",
17 | "icu_endianness": "l",
18 | "icu_gyp_path": "tools/icu/icu-generic.gyp",
19 | "icu_locales": "en,root",
20 | "icu_path": "deps/icu-small",
21 | "icu_small": "true",
22 | "icu_ver_major": "57",
23 | "node_byteorder": "little",
24 | "node_enable_d8": "false",
25 | "node_enable_v8_vtunejit": "false",
26 | "node_install_npm": "true",
27 | "node_module_version": 48,
28 | "node_no_browser_globals": "false",
29 | "node_prefix": "/usr/local",
30 | "node_release_urlbase": "https://nodejs.org/download/release/",
31 | "node_shared": "false",
32 | "node_shared_cares": "false",
33 | "node_shared_http_parser": "false",
34 | "node_shared_libuv": "false",
35 | "node_shared_openssl": "false",
36 | "node_shared_zlib": "false",
37 | "node_tag": "",
38 | "node_use_bundled_v8": "true",
39 | "node_use_dtrace": "false",
40 | "node_use_etw": "true",
41 | "node_use_lttng": "false",
42 | "node_use_openssl": "true",
43 | "node_use_perfctr": "true",
44 | "node_use_v8_platform": "true",
45 | "openssl_fips": "",
46 | "openssl_no_asm": 0,
47 | "shlib_suffix": "so.48",
48 | "target_arch": "x64",
49 | "v8_enable_gdbjit": 0,
50 | "v8_enable_i18n_support": 1,
51 | "v8_inspector": "true",
52 | "v8_no_strict_aliasing": 1,
53 | "v8_optimized_debug": 0,
54 | "v8_random_seed": 0,
55 | "v8_use_snapshot": "true",
56 | "want_separate_host_toolset": 0,
57 | "nodedir": "C:\\Users\\IBM_ADMIN\\.node-gyp\\6.9.1",
58 | "copy_dev_lib": "true",
59 | "standalone_static_library": 1,
60 | "access": "",
61 | "also": "",
62 | "always_auth": "",
63 | "bin_links": "true",
64 | "browser": "",
65 | "ca": "",
66 | "cache": "C:\\Users\\IBM_ADMIN\\AppData\\Roaming\\npm-cache",
67 | "cache_lock_retries": "10",
68 | "cache_lock_stale": "60000",
69 | "cache_lock_wait": "10000",
70 | "cache_max": "Infinity",
71 | "cache_min": "10",
72 | "cert": "",
73 | "color": "true",
74 | "depth": "Infinity",
75 | "description": "true",
76 | "dev": "",
77 | "dry_run": "",
78 | "editor": "notepad.exe",
79 | "engine_strict": "",
80 | "fetch_retries": "2",
81 | "fetch_retry_factor": "10",
82 | "fetch_retry_maxtimeout": "60000",
83 | "fetch_retry_mintimeout": "10000",
84 | "force": "",
85 | "git": "git",
86 | "git_tag_version": "true",
87 | "global": "",
88 | "globalconfig": "C:\\Users\\IBM_ADMIN\\AppData\\Roaming\\npm\\etc\\npmrc",
89 | "globalignorefile": "C:\\Users\\IBM_ADMIN\\AppData\\Roaming\\npm\\etc\\npmignore",
90 | "global_style": "",
91 | "group": "",
92 | "heading": "npm",
93 | "https_proxy": "",
94 | "if_present": "",
95 | "ignore_scripts": "",
96 | "init_author_email": "",
97 | "init_author_name": "",
98 | "init_author_url": "",
99 | "init_license": "ISC",
100 | "init_module": "C:\\Users\\IBM_ADMIN\\.npm-init.js",
101 | "init_version": "1.0.0",
102 | "json": "",
103 | "key": "",
104 | "legacy_bundling": "",
105 | "link": "",
106 | "local_address": "",
107 | "long": "",
108 | "maxsockets": "50",
109 | "message": "%s",
110 | "node_version": "6.9.1",
111 | "npat": "",
112 | "onload_script": "",
113 | "only": "",
114 | "optional": "true",
115 | "parseable": "",
116 | "prefix": "C:\\Users\\IBM_ADMIN\\AppData\\Roaming\\npm",
117 | "production": "",
118 | "progress": "true",
119 | "proprietary_attribs": "true",
120 | "rebuild_bundle": "true",
121 | "registry": "https://registry.npmjs.org/",
122 | "rollback": "true",
123 | "save": "",
124 | "save_bundle": "",
125 | "save_dev": "",
126 | "save_exact": "",
127 | "save_optional": "",
128 | "save_prefix": "^",
129 | "scope": "",
130 | "searchexclude": "",
131 | "searchopts": "",
132 | "searchsort": "name",
133 | "shell": "C:\\windows\\system32\\cmd.exe",
134 | "shrinkwrap": "true",
135 | "sign_git_tag": "",
136 | "strict_ssl": "true",
137 | "tag": "latest",
138 | "tag_version_prefix": "v",
139 | "tmp": "C:\\windows\\TEMP",
140 | "umask": "0000",
141 | "unicode": "",
142 | "unsafe_perm": "true",
143 | "usage": "",
144 | "user": "",
145 | "userconfig": "C:\\Users\\IBM_ADMIN\\.npmrc",
146 | "user_agent": "npm/3.10.8 node/v6.9.1 win32 x64",
147 | "version": "",
148 | "versions": "",
149 | "viewer": "browser"
150 | }
151 | }
152 |
--------------------------------------------------------------------------------
/chaincodes/chaincodes.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diego-blockchain/blockchain-go/93d8aad7e29c73e1cda4d7fed3cde4e0b671f611/chaincodes/chaincodes.zip
--------------------------------------------------------------------------------
/chaincodes/query.go:
--------------------------------------------------------------------------------
1 | /*
2 | Licensed to the Apache Software Foundation (ASF) under one
3 | or more contributor license agreements. See the NOTICE file
4 | distributed with this work for additional information
5 | regarding copyright ownership. The ASF licenses this file
6 | to you under the Apache License, Version 2.0 (the
7 | "License"); you may not use this file except in compliance
8 | with the License. You may obtain a copy of the License at
9 | http://www.apache.org/licenses/LICENSE-2.0
10 | Unless required by applicable law or agreed to in writing,
11 | software distributed under the License is distributed on an
12 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
13 | KIND, either express or implied. See the License for the
14 | specific language governing permissions and limitations
15 | under the License.
16 | */
17 |
18 | package main
19 |
20 | import (
21 | "encoding/json"
22 | "errors"
23 | "fmt"
24 | "strconv"
25 | "strings"
26 | "time"
27 |
28 | "github.com/hyperledger/fabric/core/chaincode/shim"
29 | )
30 |
31 | // SimpleChaincode example simple Chaincode implementation
32 | type SimpleChaincode struct {
33 | }
34 |
35 | var assetIndexStr = "_assetindex" //Description for the key/value that will store a list of all known Assets
36 | var openTradesStr = "_opentrades" //Description for the key/value that will store all open trades
37 |
38 | type Asset struct {
39 | Description string `json:"description"` //the fieldtags are needed to keep case from bouncing around
40 | LastTransaction string `json:"lastTransaction"`
41 | Temperature int `json:"temperature"`
42 | Status bool `json:"status"`
43 | ID int `json:"id"`
44 | User string `json:"user"`
45 | }
46 |
47 | type Description struct {
48 | LastTransaction string `json:"lastTransaction"`
49 | ID int `json:"id"`
50 | }
51 |
52 | type AnOpenTrade struct {
53 | User string `json:"user"` //user who created the open trade order
54 | Timestamp int64 `json:"timestamp"` //utc timestamp of creation
55 | Want Description `json:"want"` //description of desired Asset
56 | Willing []Description `json:"willing"` //array of Assets willing to trade away
57 | }
58 |
59 | type AllTrades struct {
60 | OpenTrades []AnOpenTrade `json:"open_trades"`
61 | }
62 |
63 | // =========================================================================================================== =================
64 | // Main
65 | // =========================================================================================================== =================
66 | func main() {
67 | err := shim.Start(new(SimpleChaincode))
68 | if err != nil {
69 | fmt.Printf("Error starting Simple chaincode: %s", err)
70 | }
71 | }
72 |
73 | // =========================================================================================================== =================
74 | // Init - reset all the things
75 | // =========================================================================================================== =================
76 | func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
77 | var Aval int
78 | var err error
79 |
80 | if len(args) != 1 {
81 | return nil, errors.New("Incorrect number of arguments. Expecting 1")
82 | }
83 |
84 | // Initialize the chaincode
85 | Aval, err = strconv.Atoi(args[0])
86 | if err != nil {
87 | return nil, errors.New("Expecting integer value for asset holding")
88 | }
89 |
90 | // Write the state to the ledger
91 | err = stub.PutState("abc", []byte(strconv.Itoa(Aval))) //making a test var "abc", I find it handy to read/write to it right away to test the network
92 | if err != nil {
93 | return nil, err
94 | }
95 |
96 | var empty []string
97 | jsonAsBytes, _ := json.Marshal(empty) //marshal an emtpy array of strings to clear the index
98 | err = stub.PutState(assetIndexStr, jsonAsBytes)
99 | if err != nil {
100 | return nil, err
101 | }
102 |
103 | var trades AllTrades
104 | jsonAsBytes, _ = json.Marshal(trades) //clear the open trade struct
105 | err = stub.PutState(openTradesStr, jsonAsBytes)
106 | if err != nil {
107 | return nil, err
108 | }
109 |
110 | return nil, nil
111 | }
112 |
113 | // =========================================================================================================== =================
114 | // Run - Our entry point for Invocations - [LEGACY] obc-peer 4/25/2016
115 | // =========================================================================================================== =================
116 | func (t *SimpleChaincode) Run(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
117 | fmt.Println("run is running " + function)
118 | return t.Invoke(stub, function, args)
119 | }
120 |
121 | // =========================================================================================================== =================
122 | // Invoke - Our entry point for Invocations
123 | // =========================================================================================================== =================
124 | func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
125 | fmt.Println("invoke is running " + function)
126 |
127 | // Handle different functions
128 | if function == "init" { //initialize the chaincode state, used as reset
129 | return t.Init(stub, "init", args)
130 | } else if function == "delete" { //deletes an entity from its state
131 | res, err := t.Delete(stub, args)
132 | cleanTrades(stub) //lets make sure all open trades are still valid
133 | return res, err
134 | } else if function == "write" { //writes a value to the chaincode state
135 | return t.Write(stub, args)
136 | } else if function == "init_asset" { //create a new Asset
137 | return t.init_Asset(stub, args)
138 | } else if function == "set_user" { //change owner of a Asset
139 | res, err := t.set_user(stub, args)
140 | cleanTrades(stub) //lets make sure all open trades are still valid
141 | return res, err
142 | } else if function == "open_trade" { //create a new trade order
143 | return t.open_trade(stub, args)
144 | } else if function == "perform_trade" { //forfill an open trade order
145 | res, err := t.perform_trade(stub, args)
146 | cleanTrades(stub) //lets clean just in case
147 | return res, err
148 | } else if function == "remove_trade" { //cancel an open trade order
149 | return t.remove_trade(stub, args)
150 | }
151 | fmt.Println("invoke did not find func: " + function) //error
152 |
153 | return nil, errors.New("Received unknown function invocation")
154 | }
155 |
156 | // =========================================================================================================== =================
157 | // Query - Our entry point for Queries
158 | // =========================================================================================================== =================
159 | func (t *SimpleChaincode) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
160 | fmt.Println("query is running " + function)
161 |
162 | // Handle different functions
163 | if function == "read" { //read a variable
164 | return t.read(stub, args)
165 | }
166 | fmt.Println("query did not find func: " + function) //error
167 |
168 | return nil, errors.New("Received unknown function query")
169 | }
170 |
171 | // =========================================================================================================== =================
172 | // Read - read a variable from chaincode state
173 | // =========================================================================================================== =================
174 | func (t *SimpleChaincode) read(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {
175 | var Description, jsonResp string
176 | var err error
177 |
178 | if len(args) != 1 {
179 | return nil, errors.New("Incorrect number of arguments. Expecting Description of the var to query")
180 | }
181 |
182 | Description = args[0]
183 | fmt.Print("Description " + Description)
184 | valAsbytes, err := stub.GetState(Description) //get the var from chaincode state
185 | if err != nil {
186 | jsonResp = "{\"Error\":\"Failed to get state for " + Description + "\"}"
187 | return nil, errors.New(jsonResp)
188 | }
189 |
190 | var infoIndex []string
191 | json.Unmarshal(valAsbytes, &infoIndex)
192 |
193 | for i, val := range infoIndex {
194 | fmt.Println("got: " + infoIndex[i] + " " + val)
195 | }
196 |
197 | return valAsbytes, nil //send it onward
198 | }
199 |
200 | // =========================================================================================================== =================
201 | // Delete - remove a key/value pair from state
202 | // =========================================================================================================== =================
203 | func (t *SimpleChaincode) Delete(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {
204 | if len(args) != 1 {
205 | return nil, errors.New("Incorrect number of arguments. Expecting 1")
206 | }
207 |
208 | Description := args[0]
209 | err := stub.DelState(Description) //remove the key from chaincode state
210 | if err != nil {
211 | return nil, errors.New("Failed to delete state")
212 | }
213 |
214 | //get the Asset index
215 | AssetsAsBytes, err := stub.GetState(assetIndexStr)
216 | if err != nil {
217 | return nil, errors.New("Failed to get Asset index")
218 | }
219 | var AssetIndex []string
220 | json.Unmarshal(AssetsAsBytes, &AssetIndex) //un stringify it aka JSON.parse()
221 |
222 | //remove Asset from index
223 | for i, val := range AssetIndex {
224 | fmt.Println(strconv.Itoa(i) + " - looking at " + val + " for " + Description)
225 | if val == Description { //find the correct Asset
226 | fmt.Println("found Asset")
227 | AssetIndex = append(AssetIndex[:i], AssetIndex[i+1:]...) //remove it
228 | for x := range AssetIndex { //debug prints...
229 | fmt.Println(string(x) + " - " + AssetIndex[x])
230 | }
231 | break
232 | }
233 | }
234 | jsonAsBytes, _ := json.Marshal(AssetIndex) //save new index
235 | err = stub.PutState(assetIndexStr, jsonAsBytes)
236 | return nil, nil
237 | }
238 |
239 | // =========================================================================================================== =================
240 | // Write - write variable into chaincode state
241 | // =========================================================================================================== =================
242 | func (t *SimpleChaincode) Write(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {
243 | var description, value string // Entities
244 | var err error
245 | fmt.Println("running write()")
246 |
247 | if len(args) != 2 {
248 | return nil, errors.New("Incorrect number of arguments. Expecting 2. Description of the variable and value to set")
249 | }
250 |
251 | description = args[0] //reDescription for funsies
252 | value = args[1]
253 | err = stub.PutState(description, []byte(value)) //write the variable into the chaincode state
254 | if err != nil {
255 | return nil, err
256 | }
257 | return nil, nil
258 | }
259 |
260 | // =========================================================================================================== =================
261 | // Init Asset - create a new Asset, store into chaincode state
262 | // =========================================================================================================== =================
263 | func (t *SimpleChaincode) init_Asset(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {
264 | var err error
265 |
266 | // 0 1 2 3
267 | // "asdf", "blue", "35", "bob"
268 | if len(args) != 5 {
269 | fmt.Println("- Incorrect number of arguments. Expecting 5")
270 | return nil, errors.New("Incorrect number of arguments. Expecting 5")
271 | }
272 |
273 | //input sanitation
274 | fmt.Println("- start init Asset")
275 | if len(args[0]) <= 0 {
276 | return nil, errors.New("1st argument must be a non-empty string")
277 | }
278 | if len(args[1]) <= 0 {
279 | return nil, errors.New("2nd argument must be a non-empty string")
280 | }
281 | if len(args[2]) <= 0 {
282 | return nil, errors.New("3rd argument must be a non-empty string")
283 | }
284 | if len(args[3]) <= 0 {
285 | return nil, errors.New("4th argument must be a non-empty string")
286 | }
287 | if len(args[4]) <= 0 {
288 | return nil, errors.New("5th argument must be a non-empty string")
289 | }
290 |
291 | //fmt.Print("Assigning first values...")
292 | description := args[0]
293 | lastTransaction := strings.ToLower(args[1])
294 | user := strings.ToLower(args[2])
295 | temperature := strings.ToLower(args[3])
296 | id := strings.ToLower(args[4])
297 | status := strings.ToLower("false")
298 |
299 | //check if Asset already exists
300 | AssetAsBytes, err := stub.GetState(description)
301 | if err != nil {
302 | fmt.Println("Failed to get Asset Description")
303 | return nil, errors.New("Failed to get Asset Description")
304 | }
305 | res := Asset{}
306 | json.Unmarshal(AssetAsBytes, &res)
307 | if res.Description == description {
308 | fmt.Println("This Asset arleady exists: " + description)
309 | fmt.Println(res)
310 | return nil, errors.New("This Asset already exists") //all stop a Asset by this Description exists
311 | }
312 |
313 | //build the Asset json string manually
314 | str := `{"description": "` + description + `", "lastTransaction": "` + lastTransaction + `", "temperature": "` + temperature + `", "status": "` + status + `", "id": "` + id + `", "user": "` + user + `"}`
315 | err = stub.PutState(description, []byte(str)) //store Asset with id as key
316 | if err != nil {
317 | fmt.Println("error [init_asset] str.PutState! ")
318 | return nil, err
319 | }
320 |
321 | //get the Asset index
322 | AssetsAsBytes, err := stub.GetState(assetIndexStr)
323 | if err != nil {
324 | return nil, errors.New("Failed to get Asset index")
325 | }
326 | var AssetIndex []string
327 | json.Unmarshal(AssetsAsBytes, &AssetIndex) //un stringify it aka JSON.parse()
328 |
329 | //append
330 | AssetIndex = append(AssetIndex, description) //add Asset Description to index list
331 | fmt.Println("! Asset index: ", AssetIndex)
332 | jsonAsBytes, _ := json.Marshal(AssetIndex)
333 | err = stub.PutState(assetIndexStr, jsonAsBytes) //store Description of Asset
334 |
335 | fmt.Println("- end init Asset")
336 | return nil, nil
337 | }
338 |
339 | // =========================================================================================================== =================
340 | // Set User Permission on Asset
341 | // =========================================================================================================== =================
342 | func (t *SimpleChaincode) set_user(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {
343 | var err error
344 |
345 | // 0 1
346 | // "Description", "bob"
347 | if len(args) < 3 {
348 | return nil, errors.New("Incorrect number of arguments. Expecting 2")
349 | }
350 |
351 | fmt.Println("- start set user")
352 | fmt.Println(args[0] + " - " + args[1] + " - " + args[2])
353 | AssetAsBytes, err := stub.GetState(args[0])
354 | if err != nil {
355 | return nil, errors.New("Failed to get thing")
356 | }
357 |
358 | res := Asset{}
359 | json.Unmarshal(AssetAsBytes, &res) //un stringify it aka JSON.parse()
360 | temp, err := strconv.Atoi(args[2])
361 | if err != nil {
362 | msg := "Temperature needs to be a numeric string " + args[2]
363 | fmt.Println(msg)
364 | return nil, errors.New(msg)
365 | }
366 |
367 | fmt.Println("Current temperature " + strconv.Itoa(temp))
368 | if temp > 24 {
369 | fmt.Println("[Smart Contract] Asset need to be verified " + strconv.Itoa(temp))
370 | res.Status = true
371 | } else {
372 | fmt.Println("[Smart Contract] Satisfied! " + strconv.Itoa(temp))
373 | tmp, err := strconv.Atoi(args[2])
374 | if err != nil {
375 | msg := "Temperature needs to be a numeric string " + args[2]
376 | fmt.Println(msg)
377 | return nil, errors.New(msg)
378 | }
379 |
380 | res.Status = false
381 | res.Temperature = tmp
382 | res.User = args[1] //change the user
383 |
384 | jsonAsBytes, _ := json.Marshal(res)
385 | err = stub.PutState(args[0], jsonAsBytes) //rewrite the Asset with id as key
386 | if err != nil {
387 | return nil, err
388 | }
389 |
390 | fmt.Println("- end set user")
391 | return nil, nil
392 | }
393 |
394 | jsonAsBytes, _ := json.Marshal(res)
395 | err = stub.PutState(args[0], jsonAsBytes) //rewrite the Asset with id as key
396 | if err != nil {
397 | return nil, err
398 | }
399 |
400 | fmt.Println("- infraction applied to the ledger state")
401 | return nil, nil
402 | }
403 |
404 | // =========================================================================================================== =================
405 | // Open Trade - create an open trade for a Asset you want with Assets you have
406 | // =========================================================================================================== =================
407 | func (t *SimpleChaincode) open_trade(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {
408 | var err error
409 | var will_id int
410 | var trade_away Description
411 |
412 | // 0 1 2 3 4 5 6
413 | //["bob", "blue", "16", "red", "16"] *"blue", "35*
414 | if len(args) < 5 {
415 | return nil, errors.New("Incorrect number of arguments. Expecting like 5?")
416 | }
417 | if len(args)%2 == 0 {
418 | return nil, errors.New("Incorrect number of arguments. Expecting an odd number")
419 | }
420 |
421 | id, err := strconv.Atoi(args[2])
422 | if err != nil {
423 | return nil, errors.New("3rd argument must be a numeric string")
424 | }
425 |
426 | open := AnOpenTrade{}
427 | open.User = args[0]
428 | open.Timestamp = makeTimestamp() //use timestamp as an ID
429 | open.Want.LastTransaction = args[1]
430 | open.Want.ID = id
431 | fmt.Println("- start open trade")
432 | jsonAsBytes, _ := json.Marshal(open)
433 | err = stub.PutState("_debug1", jsonAsBytes)
434 |
435 | for i := 3; i < len(args); i++ { //create and append each willing trade
436 | will_id, err = strconv.Atoi(args[i+1])
437 | if err != nil {
438 | msg := "is not a numeric string " + args[i+1]
439 | fmt.Println(msg)
440 | return nil, errors.New(msg)
441 | }
442 |
443 | trade_away = Description{}
444 | trade_away.LastTransaction = args[i]
445 | trade_away.ID = will_id
446 | fmt.Println("! created trade_away: " + args[i])
447 | jsonAsBytes, _ = json.Marshal(trade_away)
448 | err = stub.PutState("_debug2", jsonAsBytes)
449 |
450 | open.Willing = append(open.Willing, trade_away)
451 | fmt.Println("! appended willing to open")
452 | i++
453 | }
454 |
455 | //get the open trade struct
456 | tradesAsBytes, err := stub.GetState(openTradesStr)
457 | if err != nil {
458 | return nil, errors.New("Failed to get opentrades")
459 | }
460 | var trades AllTrades
461 | json.Unmarshal(tradesAsBytes, &trades) //un stringify it aka JSON.parse()
462 |
463 | trades.OpenTrades = append(trades.OpenTrades, open) //append to open trades
464 | fmt.Println("! appended open to trades")
465 | jsonAsBytes, _ = json.Marshal(trades)
466 | err = stub.PutState(openTradesStr, jsonAsBytes) //rewrite open orders
467 | if err != nil {
468 | return nil, err
469 | }
470 | fmt.Println("- end open trade")
471 | return nil, nil
472 | }
473 |
474 | // =========================================================================================================== =================
475 | // Perform Trade - close an open trade and move ownership
476 | // =========================================================================================================== =================
477 | func (t *SimpleChaincode) perform_trade(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {
478 | var err error
479 |
480 | // 0 1 2 3 4 5
481 | //[data.id, data.closer.user, data.closer.Description, data.opener.user, data.opener.LastTransaction, data.opener.Weight]
482 | if len(args) < 6 {
483 | return nil, errors.New("Incorrect number of arguments. Expecting 6")
484 | }
485 |
486 | fmt.Println("- start close trade")
487 | timestamp, err := strconv.ParseInt(args[0], 10, 64)
488 | if err != nil {
489 | return nil, errors.New("1st argument must be a numeric string")
490 | }
491 |
492 | id, err := strconv.Atoi(args[5])
493 | if err != nil {
494 | return nil, errors.New("6th argument must be a numeric string")
495 | }
496 |
497 | //get the open trade struct
498 | tradesAsBytes, err := stub.GetState(openTradesStr)
499 | if err != nil {
500 | return nil, errors.New("Failed to get opentrades")
501 | }
502 | var trades AllTrades
503 | json.Unmarshal(tradesAsBytes, &trades) //un stringify it aka JSON.parse()
504 |
505 | for i := range trades.OpenTrades { //look for the trade
506 | fmt.Println("looking at " + strconv.FormatInt(trades.OpenTrades[i].Timestamp, 10) + " for " + strconv.FormatInt(timestamp, 10))
507 | if trades.OpenTrades[i].Timestamp == timestamp {
508 | fmt.Println("found the trade")
509 |
510 | AssetAsBytes, err := stub.GetState(args[2])
511 | if err != nil {
512 | return nil, errors.New("Failed to get thing")
513 | }
514 | closersAsset := Asset{}
515 | json.Unmarshal(AssetAsBytes, &closersAsset) //un stringify it aka JSON.parse()
516 |
517 | //verify if Asset meets trade requirements
518 | if closersAsset.LastTransaction != trades.OpenTrades[i].Want.LastTransaction || closersAsset.ID != trades.OpenTrades[i].Want.ID {
519 | msg := "Asset in input does not meet trade requriements"
520 | fmt.Println(msg)
521 | return nil, errors.New(msg)
522 | }
523 |
524 | Asset, e := findAsset4Trade(stub, trades.OpenTrades[i].User, args[4], id) //find a Ass et that is suitable from opener
525 | if e == nil {
526 | fmt.Println("! no errors, proceeding")
527 |
528 | t.set_user(stub, []string{args[2], trades.OpenTrades[i].User}) //change owner of selected Asset, closer -> opener
529 | t.set_user(stub, []string{Asset.Description, args[1]}) //change owner of selected Asset, opener -> closer
530 |
531 | trades.OpenTrades = append(trades.OpenTrades[:i], trades.OpenTrades[i+1:]...) //remove trade
532 | jsonAsBytes, _ := json.Marshal(trades)
533 | err = stub.PutState(openTradesStr, jsonAsBytes) //rewrite open orders
534 | if err != nil {
535 | return nil, err
536 | }
537 | }
538 | }
539 | }
540 | fmt.Println("- end close trade")
541 | return nil, nil
542 | }
543 |
544 | // =========================================================================================================== =================
545 | // findAsset4Trade - look for a matching Asset that this user owns and return it
546 | // =========================================================================================================== =================
547 | func findAsset4Trade(stub shim.ChaincodeStubInterface, user string, LastTransaction string, id int) (m Asset, err error) {
548 | var fail Asset
549 | fmt.Println("- start find Asset 4 trade")
550 | fmt.Println("looking for " + user + ", " + LastTransaction + ", " + strconv.Itoa(id))
551 |
552 | //get the Asset index
553 | AssetsAsBytes, err := stub.GetState(assetIndexStr)
554 | if err != nil {
555 | return fail, errors.New("Failed to get Asset index")
556 | }
557 | var AssetIndex []string
558 | json.Unmarshal(AssetsAsBytes, &AssetIndex) //un stringify it aka JSON.parse()
559 |
560 | for i := range AssetIndex { //iter through all the Assets
561 | //fmt.Println("looking @ Asset Description: " + AssetIndex[i]);
562 |
563 | AssetAsBytes, err := stub.GetState(AssetIndex[i]) //grab this Asset
564 | if err != nil {
565 | return fail, errors.New("Failed to get Asset")
566 | }
567 | res := Asset{}
568 | json.Unmarshal(AssetAsBytes, &res) //un stringify it aka JSON.parse()
569 | //fmt.Println("looking @ " + res.User + ", " + res.LastTransaction + ", " + strconv.Itoa(res.W eight));
570 |
571 | //check for user && LastTransaction && Weight
572 | if strings.ToLower(res.User) == strings.ToLower(user) && strings.ToLower(res.LastTransaction) == strings.ToLower(LastTransaction) && res.ID == id {
573 | fmt.Println("found a Asset: " + res.Description)
574 | fmt.Println("! end find Asset 4 trade")
575 | return res, nil
576 | }
577 | }
578 |
579 | fmt.Println("- end find Asset 4 trade - error")
580 | return fail, errors.New("Did not find Asset to use in this trade")
581 | }
582 |
583 | // =========================================================================================================== =================
584 | // Make Timestamp - create a timestamp in ms
585 | // =========================================================================================================== =================
586 | func makeTimestamp() int64 {
587 | return time.Now().UnixNano() / (int64(time.Millisecond) / int64(time.Nanosecond))
588 | }
589 |
590 | // =========================================================================================================== =================
591 | // Remove Open Trade - close an open trade
592 | // =========================================================================================================== =================
593 | func (t *SimpleChaincode) remove_trade(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {
594 | var err error
595 |
596 | // 0
597 | //[data.id]
598 | if len(args) < 1 {
599 | return nil, errors.New("Incorrect number of arguments. Expecting 1")
600 | }
601 |
602 | fmt.Println("- start remove trade")
603 | timestamp, err := strconv.ParseInt(args[0], 10, 64)
604 | if err != nil {
605 | return nil, errors.New("1st argument must be a numeric string")
606 | }
607 |
608 | //get the open trade struct
609 | tradesAsBytes, err := stub.GetState(openTradesStr)
610 | if err != nil {
611 | return nil, errors.New("Failed to get opentrades")
612 | }
613 | var trades AllTrades
614 | json.Unmarshal(tradesAsBytes, &trades) //un stringify it aka JSON.parse()
615 |
616 | for i := range trades.OpenTrades { //look for the trade
617 | //fmt.Println("looking at " + strconv.FormatInt(trades.OpenTrades[i].Timestamp, 10) + " for " + strconv.FormatInt(timestamp, 10))
618 | if trades.OpenTrades[i].Timestamp == timestamp {
619 | fmt.Println("found the trade")
620 | trades.OpenTrades = append(trades.OpenTrades[:i], trades.OpenTrades[i+1:]...) //remove this trade
621 | jsonAsBytes, _ := json.Marshal(trades)
622 | err = stub.PutState(openTradesStr, jsonAsBytes) //rewrite open orders
623 | if err != nil {
624 | return nil, err
625 | }
626 | break
627 | }
628 | }
629 |
630 | fmt.Println("- end remove trade")
631 | return nil, nil
632 | }
633 |
634 | // =========================================================================================================== =================
635 | // Clean Up Open Trades - make sure open trades are still possible, remove choices that are no longer possible , remove trades that have no valid choices
636 | // =========================================================================================================== =================
637 | func cleanTrades(stub shim.ChaincodeStubInterface) (err error) {
638 | var didWork = false
639 | fmt.Println("- start clean trades")
640 |
641 | //get the open trade struct
642 | tradesAsBytes, err := stub.GetState(openTradesStr)
643 | if err != nil {
644 | return errors.New("Failed to get opentrades")
645 | }
646 | var trades AllTrades
647 | json.Unmarshal(tradesAsBytes, &trades) //un stringify it aka JSON.parse()
648 |
649 | fmt.Println("# trades " + strconv.Itoa(len(trades.OpenTrades)))
650 | for i := 0; i < len(trades.OpenTrades); { //iter over all the known open trades
651 | fmt.Println(strconv.Itoa(i) + ": looking at trade " + strconv.FormatInt(trades.OpenTrades[i].Timestamp, 10))
652 |
653 | fmt.Println("# options " + strconv.Itoa(len(trades.OpenTrades[i].Willing)))
654 | for x := 0; x < len(trades.OpenTrades[i].Willing); { //find a Asset that is suitable
655 | fmt.Println("! on next option " + strconv.Itoa(i) + ":" + strconv.Itoa(x))
656 | _, e := findAsset4Trade(stub, trades.OpenTrades[i].User, trades.OpenTrades[i].Willing[x].LastTransaction, trades.OpenTrades[i].Willing[x].ID)
657 | if e != nil {
658 | fmt.Println("! errors with this option, removing option")
659 | didWork = true
660 | trades.OpenTrades[i].Willing = append(trades.OpenTrades[i].Willing[:x], trades.OpenTrades[i].Willing[x+1:]...) //remove this option
661 | x--
662 | } else {
663 | fmt.Println("! this option is fine")
664 | }
665 |
666 | x++
667 | fmt.Println("! x:" + strconv.Itoa(x))
668 | if x >= len(trades.OpenTrades[i].Willing) { //things might have shifted, recalcuate
669 | break
670 | }
671 | }
672 |
673 | if len(trades.OpenTrades[i].Willing) == 0 {
674 | fmt.Println("! no more options for this trade, removing trade")
675 | didWork = true
676 | trades.OpenTrades = append(trades.OpenTrades[:i], trades.OpenTrades[i+1:]...) //remove this trade
677 | i--
678 | }
679 |
680 | i++
681 | fmt.Println("! i:" + strconv.Itoa(i))
682 | if i >= len(trades.OpenTrades) { //things might have shifted, recalcuate
683 | break
684 | }
685 | }
686 |
687 | if didWork {
688 | fmt.Println("! saving open trade changes")
689 | jsonAsBytes, _ := json.Marshal(trades)
690 | err = stub.PutState(openTradesStr, jsonAsBytes) //rewrite open orders
691 | if err != nil {
692 | return err
693 | }
694 | } else {
695 | fmt.Println("! all open trades are fine")
696 | }
697 |
698 | fmt.Println("- end clean trades")
699 | return nil
700 | }
701 |
--------------------------------------------------------------------------------
/config/express.js:
--------------------------------------------------------------------------------
1 | /*Express basic configuration as module */
2 |
3 | module.exports = function () {
4 | 'use strict'
5 |
6 | const express = require('express');
7 | const app = express();
8 | const bodyParser = require('body-parser');
9 | const logger = require('morgan');
10 | let listen = require('../routes/events');
11 |
12 | app.use(logger('dev'));
13 | app.use(bodyParser.json());
14 | app.use(express.static('public'));//__dirname +
15 | app.use(bodyParser.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded
16 | /*routes - not working yet**/
17 | //app.get('/events/:id', listen);
18 |
19 | return app;
20 |
21 | }
--------------------------------------------------------------------------------
/config/hyperledgerfc.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright IBM Corp 2016 All Rights Reserved.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | /*
18 | * A simple application utilizing the Node.js Client SDK to:
19 | * 1) Enroll a user
20 | * 2) User deploys chaincode
21 | * 3) User queries chaincode
22 | */
23 | // "HFC" stands for "Hyperledger Fabric Client"
24 | var hfc = require("hfc");
25 |
26 | //const env = require('../rest/local_env.json');
27 | const env = require('../env.json');
28 | console.log(`getting environment variables \n ${env.peers[0].api_port_tls}`);
29 |
30 | // get the addresses from the docker-compose environment
31 | var PEER_ADDRESS = env.peers;//process.env.CORE_PEER_ADDRESS;
32 | var MEMBERSRVC_ADDRESS = env.ca;//process.env.MEMBERSRVC_ADDRESS;
33 | console.log(JSON.stringify(MEMBERSRVC_ADDRESS));
34 |
35 | var chain, chaincodeID;
36 |
37 | function configureHfc() {
38 |
39 | // Create a chain object used to interact with the chain.
40 | // You can name it anything you want as it is only used by client.
41 | chain = hfc.newChain("mySpecialChain");
42 | // Initialize the place to store sensitive private key information
43 | //chain.setKeyValStore(hfc.newFileKeyValStore('/tmp/keyValStore'));
44 | // Set the URL to membership services and to the peer
45 | console.log("member services address =" + MEMBERSRVC_ADDRESS.type);
46 | console.log("peer address =" + PEER_ADDRESS);
47 | chain.setMemberServicesUrl("grpc://" + MEMBERSRVC_ADDRESS);
48 | chain.setKeyValStore(hfc.newFileKeyValStore('./keyValStore'));
49 | chain.addPeer("grpc://" + PEER_ADDRESS);
50 |
51 | // The following is required when the peer is started in dev mode
52 | // (i.e. with the '--peer-chaincodedev' option)
53 | var mode = process.env['DEPLOY_MODE'];
54 | console.log("DEPLOY_MODE=" + mode);
55 | if (mode === 'dev') {
56 | chain.setDevMode(true);
57 | //Deploy will not take long as the chain should already be running
58 | chain.setDeployWaitTime(10);
59 | } else {
60 | chain.setDevMode(false);
61 | //Deploy will take much longer in network mode
62 | chain.setDeployWaitTime(60);
63 | }
64 |
65 | chain.setInvokeWaitTime(10);
66 |
67 | // Begin by enrolling the user
68 | enroll();
69 |
70 | // Enroll a user.
71 | function enroll() {
72 | console.log("enrolling user admin ...");
73 | // Enroll "admin" which is preregistered in the membersrvc.yaml
74 | chain.enroll("WebAppAdmin", "DJY27pEnl16d", function (err, admin) {
75 | if (err) {
76 | console.log("ERROR: failed to register admin: %s", err);
77 | process.exit(1);
78 | }
79 | // Set this user as the chain's registrar which is authorized to register other users.
80 | chain.setRegistrar(admin);
81 |
82 | var userName = "bob";
83 | // registrationRequest
84 | var registrationRequest = {
85 | enrollmentID: userName,
86 | affiliation: "bank_a"
87 | };
88 | chain.registerAndEnroll(registrationRequest, function (error, user) {
89 | if (error) throw Error(" Failed to register and enroll " + userName + ": " + error);
90 | console.log("Enrolled %s successfully\n", userName);
91 | deploy(user);
92 | });
93 | });
94 | }
95 |
96 | // Deploy chaincode
97 | function deploy(user) {
98 | console.log("deploying chaincode; please wait ...");
99 | // Construct the deploy request
100 | var deployRequest = {
101 | chaincodeName: process.env.CORE_CHAINCODE_ID_NAME,
102 | fcn: "init",
103 | args: ["99"]
104 | };
105 | // where is the chain code, ignored in dev mode
106 | deployRequest.chaincodePath = "github.com/VitorSousaCode/chaincodes/experimental";
107 |
108 | // Issue the deploy request and listen for events
109 | var tx = user.deploy(deployRequest);
110 | tx.on('complete', function (results) {
111 | // Deploy request completed successfully
112 | console.log("deploy complete; results: %j", results);
113 | // Set the testChaincodeID for subsequent tests
114 | chaincodeID = results.chaincodeID;
115 | invoke(user);
116 | });
117 | tx.on('error', function (error) {
118 | console.log("Failed to deploy chaincode: request=%j, error=%k", deployRequest, error);
119 | process.exit(1);
120 | });
121 |
122 | }
123 |
124 | // Query chaincode
125 | function query(user) {
126 | console.log("querying chaincode ...");
127 | // Construct a query request
128 | var queryRequest = {
129 | chaincodeID: chaincodeID,
130 | fcn: "query",
131 | args: ["99"]
132 | };
133 | // Issue the query request and listen for events
134 | var tx = user.query(queryRequest);
135 | tx.on('complete', function (results) {
136 | console.log("query completed successfully; results=%j", results);
137 | process.exit(0);
138 | });
139 | tx.on('error', function (error) {
140 | console.log("Failed to query chaincode: request=%j, error=%k", queryRequest, error);
141 | process.exit(1);
142 | });
143 | }
144 |
145 | //Invoke chaincode
146 | function invoke(user) {
147 | console.log("invoke chaincode ...");
148 | // Construct a query request
149 | var invokeRequest = {
150 | chaincodeID: chaincodeID,
151 | fcn: "invoke",
152 | args: ["a", "b", "1"]
153 | };
154 | // Issue the invoke request and listen for events
155 | var tx = user.invoke(invokeRequest);
156 | tx.on('submitted', function (results) {
157 | console.log("invoke submitted successfully; results=%j", results);
158 | });
159 | tx.on('complete', function (results) {
160 | console.log("invoke completed successfully; results=%j", results);
161 | query(user);
162 | });
163 | tx.on('error', function (error) {
164 | console.log("Failed to invoke chaincode: request=%j, error=%k", invokeRequest, error);
165 | process.exit(1);
166 | });
167 | }
168 | }
169 |
170 | module.exports.startNetwork = function () {
171 | return configureHfc();
172 | }
173 |
--------------------------------------------------------------------------------
/config/ibm-blockchain.js:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | /* Copyright 2016 IBM Corp. All Rights Reserved.
3 | * blockchain instance setup using ibc-js sdk
4 | * first implementation by Vitor Diego
5 | */
6 | //------------------------------------------------------------------------------
7 | 'use strict'
8 |
9 | //loads environment variables for blockchain setup (USA server - blockchain-go)
10 | //const env = require('../env.json'); //env.json(for usa servers)
11 | //const env = require('../rest/local_env.json');
12 | const env = require('../rest/server_env.json');
13 | console.log(`getting environment variables \n ${env.peers[0].api_port_tls}`);
14 | const peers = env.peers;
15 | const users = env.users;
16 | const django = env.chaincodepath;
17 | const Ibc1 = require('ibm-blockchain-js');
18 | const ibc = new Ibc1();
19 | var chaincode;
20 |
21 | // ==================================
22 | // configure ibc-js sdk
23 | // ==================================
24 | function configureIbcJs() {
25 | let options = {
26 | network: {
27 | peers: [peers[0]], //2
28 | users: users, //3 [users[1]]
29 | options: { //this is optional
30 | quiet: false, //detailed debug messages on/off true/false
31 | tls: false, //should app to peer communication use tls?
32 | maxRetry: 2 //how many times should we retry register before giving up
33 | }
34 | },
35 | chaincode: {
36 | zip_url: 'https://github.com/VitorSousaCode/chaincodes/archive/master.zip',
37 | unzip_dir: 'chaincodes-master/experimental',
38 | git_url: 'https://github.com/VitorSousaCode/chaincodes/experimental'
39 | }
40 | };
41 |
42 | ibc.network(peers, { quiet: false, timeout: 120000 });
43 | //if the peer has stoped we can use: ibc.switchPeer(peers[x]);
44 | //loads chaincode with options above
45 | ibc.load(options, cb_ready);
46 |
47 | /* function cb_ready(err,cc)
48 | * @param {Object} err - error object for handling
49 | * @param {Object} cc - chaincode object deployed Successfully */
50 | function cb_ready(err, cc) {
51 | if (err != null) {
52 | console.log('! looks like an error loading the chaincode, app will fail\n', err);
53 | if (!process.error) process.error = { type: 'load', msg: err.details }; //if it already exist, keep the last error
54 | }
55 | else {
56 | chaincode = cc;
57 | //decide if I need to deploy or not - fix
58 | if (!cc.details.deployed_name || cc.details.deployed_name === "") {
59 | cc.deploy('init', ['99'], { delay_ms: 40000 }, function (err, success) {
60 | if (err) return;
61 | }); //{delay_ms: 60000}
62 | console.log("deploying chaincode...");
63 | console.log(JSON.stringify(cc));
64 | }
65 | else {
66 | console.log('chaincode summary file indicates chaincode has been previously deployed');
67 | }
68 | console.log("chaincode " + JSON.stringify(chaincode));
69 | return chaincode;
70 | }
71 | }
72 | }
73 |
74 | module.exports.chain = function () {
75 | console.log(`chaincode ${chaincode}`);
76 | return chaincode;
77 | };
78 |
79 | module.exports.startNetwork = function () {
80 | return configureIbcJs();
81 | }
82 |
83 | module.exports.monitor = {
84 | stats: ibc
85 | }
--------------------------------------------------------------------------------
/config/setup.js:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | /* Copyright 2016 IBM Corp. All Rights Reserved.
3 | * blockchain instance setup using ibc-js sdk
4 | * first implementation by Vitor Diego
5 | */
6 | //------------------------------------------------------------------------------
7 | 'use strict'
8 |
9 | //loads environment variables for blockchain setup (USA server - blockchain-go)
10 | const env = require('../env/uk_env.json'); //env.json(for usa servers)
11 | //const env = require('../env/local_env.json');
12 | const api = require('../rest/api.js');
13 | console.log(`getting environment variables \n ${env.peers[0].api_port_tls}`);
14 | const peers = env.peers;
15 | const users = env.users;
16 | var chaincode;
17 |
18 | function runNetwork() {
19 |
20 | //index of users[] to be registered
21 | let x = 4;
22 | let rest = api(peers[0].api_host, peers[0].api_port_tls);
23 | let admin = {
24 | user: env.users[x].enrollId,
25 | secret: env.users[x].enrollSecret
26 | };
27 |
28 | let getRegistrar = function (req) {
29 | rest.invoke.registrar(req.user, req.secret);
30 | chaincode = rest;
31 | }
32 |
33 | getRegistrar(admin);
34 |
35 | }
36 |
37 |
38 | module.exports.chain = function () {
39 | console.log(`chaincode ${chaincode}`);
40 | return chaincode;
41 | };
42 |
43 | module.exports.startNetwork = function () {
44 | return runNetwork();
45 | }
--------------------------------------------------------------------------------
/docs/contractviolated.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diego-blockchain/blockchain-go/93d8aad7e29c73e1cda4d7fed3cde4e0b671f611/docs/contractviolated.png
--------------------------------------------------------------------------------
/docs/creatingAsset.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diego-blockchain/blockchain-go/93d8aad7e29c73e1cda4d7fed3cde4e0b671f611/docs/creatingAsset.png
--------------------------------------------------------------------------------
/docs/dashboard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diego-blockchain/blockchain-go/93d8aad7e29c73e1cda4d7fed3cde4e0b671f611/docs/dashboard.png
--------------------------------------------------------------------------------
/docs/events.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diego-blockchain/blockchain-go/93d8aad7e29c73e1cda4d7fed3cde4e0b671f611/docs/events.png
--------------------------------------------------------------------------------
/docs/history.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diego-blockchain/blockchain-go/93d8aad7e29c73e1cda4d7fed3cde4e0b671f611/docs/history.png
--------------------------------------------------------------------------------
/docs/intro.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diego-blockchain/blockchain-go/93d8aad7e29c73e1cda4d7fed3cde4e0b671f611/docs/intro.png
--------------------------------------------------------------------------------
/docs/payloads.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diego-blockchain/blockchain-go/93d8aad7e29c73e1cda4d7fed3cde4e0b671f611/docs/payloads.png
--------------------------------------------------------------------------------
/docs/smartcontract.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diego-blockchain/blockchain-go/93d8aad7e29c73e1cda4d7fed3cde4e0b671f611/docs/smartcontract.png
--------------------------------------------------------------------------------
/env/env.json:
--------------------------------------------------------------------------------
1 | {
2 | "peers": [
3 | {
4 | "discovery_host": "eaab7b0654764c6bae29701bde20c887-vp1.us.blockchain.ibm.com",
5 | "discovery_port": 30002,
6 | "api_host": "eaab7b0654764c6bae29701bde20c887-vp1.us.blockchain.ibm.com",
7 | "api_port_tls": 5002,
8 | "api_port": 5002,
9 | "event_host": "eaab7b0654764c6bae29701bde20c887-vp1.us.blockchain.ibm.com",
10 | "event_port": 31002,
11 | "type": "peer",
12 | "network_id": "eaab7b0654764c6bae29701bde20c887",
13 | "container_id": "fd3153c7c26cf26eb731c6fccec046651c27fc4b1e815b6fd4b55180ff05b362",
14 | "id": "eaab7b0654764c6bae29701bde20c887-vp1",
15 | "api_url": "http://eaab7b0654764c6bae29701bde20c887-vp1.us.blockchain.ibm.com:5002"
16 | },
17 | {
18 | "discovery_host": "eaab7b0654764c6bae29701bde20c887-vp2.us.blockchain.ibm.com",
19 | "discovery_port": 30002,
20 | "api_host": "eaab7b0654764c6bae29701bde20c887-vp2.us.blockchain.ibm.com",
21 | "api_port_tls": 5002,
22 | "api_port": 5002,
23 | "event_host": "eaab7b0654764c6bae29701bde20c887-vp2.us.blockchain.ibm.com",
24 | "event_port": 31002,
25 | "type": "peer",
26 | "network_id": "eaab7b0654764c6bae29701bde20c887",
27 | "container_id": "34f01b72dc5fcd2f4b2d0f07f2e2bd085876ee5ee22faa46f4e5709d4210d826",
28 | "id": "eaab7b0654764c6bae29701bde20c887-vp2",
29 | "api_url": "http://eaab7b0654764c6bae29701bde20c887-vp2.us.blockchain.ibm.com:5002"
30 | },
31 | {
32 | "discovery_host": "eaab7b0654764c6bae29701bde20c887-vp0.us.blockchain.ibm.com",
33 | "discovery_port": 30002,
34 | "api_host": "eaab7b0654764c6bae29701bde20c887-vp0.us.blockchain.ibm.com",
35 | "api_port_tls": 5002,
36 | "api_port": 5002,
37 | "event_host": "eaab7b0654764c6bae29701bde20c887-vp0.us.blockchain.ibm.com",
38 | "event_port": 31002,
39 | "type": "peer",
40 | "network_id": "eaab7b0654764c6bae29701bde20c887",
41 | "container_id": "2f73d4d5eceff20c41b6a741d22e31324522d22b5a8069332f9f38d79c38fc28",
42 | "id": "eaab7b0654764c6bae29701bde20c887-vp0",
43 | "api_url": "http://eaab7b0654764c6bae29701bde20c887-vp0.us.blockchain.ibm.com:5002"
44 | },
45 | {
46 | "discovery_host": "eaab7b0654764c6bae29701bde20c887-vp3.us.blockchain.ibm.com",
47 | "discovery_port": 30002,
48 | "api_host": "eaab7b0654764c6bae29701bde20c887-vp3.us.blockchain.ibm.com",
49 | "api_port_tls": 5002,
50 | "api_port": 5002,
51 | "event_host": "eaab7b0654764c6bae29701bde20c887-vp3.us.blockchain.ibm.com",
52 | "event_port": 31002,
53 | "type": "peer",
54 | "network_id": "eaab7b0654764c6bae29701bde20c887",
55 | "container_id": "22072968211ddd579f7585512b66eb20bf284b3cad691b1095b2cc02b1746c20",
56 | "id": "eaab7b0654764c6bae29701bde20c887-vp3",
57 | "api_url": "http://eaab7b0654764c6bae29701bde20c887-vp3.us.blockchain.ibm.com:5002"
58 | }
59 | ],
60 | "ca": {
61 | "eaab7b0654764c6bae29701bde20c887-ca": {
62 | "url": "eaab7b0654764c6bae29701bde20c887-ca.us.blockchain.ibm.com:30002",
63 | "discovery_host": "eaab7b0654764c6bae29701bde20c887-ca.us.blockchain.ibm.com",
64 | "discovery_port": 30002,
65 | "api_host": "eaab7b0654764c6bae29701bde20c887-ca.us.blockchain.ibm.com",
66 | "api_port_tls": 30002,
67 | "api_port": 30002,
68 | "type": "ca",
69 | "network_id": "eaab7b0654764c6bae29701bde20c887",
70 | "container_id": "da1d4223aa99ae2249b059e67f07ba1c99593bd5144d37288d0f22ea5bd34c2e"
71 | }
72 | },
73 | "users": [
74 | {
75 | "enrollId": "admin",
76 | "enrollSecret": "b070ab4061",
77 | "affiliation": "group1",
78 | "username": "admin",
79 | "secret": "b070ab4061"
80 | },
81 | {
82 | "enrollId": "WebAppAdmin",
83 | "enrollSecret": "0c23acff41",
84 | "affiliation": "group1",
85 | "username": "WebAppAdmin",
86 | "secret": "0c23acff41"
87 | },
88 | {
89 | "enrollId": "user_type1_0",
90 | "enrollSecret": "cd32958ec5",
91 | "affiliation": "group1",
92 | "username": "user_type1_0",
93 | "secret": "cd32958ec5"
94 | },
95 | {
96 | "enrollId": "user_type1_1",
97 | "enrollSecret": "c9461e186a",
98 | "affiliation": "group1",
99 | "username": "user_type1_1",
100 | "secret": "c9461e186a"
101 | },
102 | {
103 | "enrollId": "user_type1_2",
104 | "enrollSecret": "9427f90f09",
105 | "affiliation": "group1",
106 | "username": "user_type1_2",
107 | "secret": "9427f90f09"
108 | },
109 | {
110 | "enrollId": "user_type1_3",
111 | "enrollSecret": "b968f6223a",
112 | "affiliation": "group1",
113 | "username": "user_type1_3",
114 | "secret": "b968f6223a"
115 | },
116 | {
117 | "enrollId": "user_type1_4",
118 | "enrollSecret": "51716ba5a9",
119 | "affiliation": "group1",
120 | "username": "user_type1_4",
121 | "secret": "51716ba5a9"
122 | },
123 | {
124 | "enrollId": "user_type2_0",
125 | "enrollSecret": "578bcbc53c",
126 | "affiliation": "group1",
127 | "username": "user_type2_0",
128 | "secret": "578bcbc53c"
129 | },
130 | {
131 | "enrollId": "user_type2_1",
132 | "enrollSecret": "ef7a68fc4e",
133 | "affiliation": "group1",
134 | "username": "user_type2_1",
135 | "secret": "ef7a68fc4e"
136 | },
137 | {
138 | "enrollId": "user_type2_2",
139 | "enrollSecret": "4cef77b2af",
140 | "affiliation": "group1",
141 | "username": "user_type2_2",
142 | "secret": "4cef77b2af"
143 | },
144 | {
145 | "enrollId": "user_type2_3",
146 | "enrollSecret": "8878710f86",
147 | "affiliation": "group1",
148 | "username": "user_type2_3",
149 | "secret": "8878710f86"
150 | },
151 | {
152 | "enrollId": "user_type2_4",
153 | "enrollSecret": "79e226a2d4",
154 | "affiliation": "group1",
155 | "username": "user_type2_4",
156 | "secret": "79e226a2d4"
157 | },
158 | {
159 | "enrollId": "user_type4_0",
160 | "enrollSecret": "cb37a3595f",
161 | "affiliation": "group1",
162 | "username": "user_type4_0",
163 | "secret": "cb37a3595f"
164 | },
165 | {
166 | "enrollId": "user_type4_1",
167 | "enrollSecret": "475e900687",
168 | "affiliation": "group1",
169 | "username": "user_type4_1",
170 | "secret": "475e900687"
171 | },
172 | {
173 | "enrollId": "user_type4_2",
174 | "enrollSecret": "3884f9e3c7",
175 | "affiliation": "group1",
176 | "username": "user_type4_2",
177 | "secret": "3884f9e3c7"
178 | },
179 | {
180 | "enrollId": "user_type4_3",
181 | "enrollSecret": "daa8e51a62",
182 | "affiliation": "group1",
183 | "username": "user_type4_3",
184 | "secret": "daa8e51a62"
185 | },
186 | {
187 | "enrollId": "user_type4_4",
188 | "enrollSecret": "8d9dacbaa7",
189 | "affiliation": "group1",
190 | "username": "user_type4_4",
191 | "secret": "8d9dacbaa7"
192 | },
193 | {
194 | "enrollId": "user_type8_0",
195 | "enrollSecret": "95faa6fc14",
196 | "affiliation": "group1",
197 | "username": "user_type8_0",
198 | "secret": "95faa6fc14"
199 | },
200 | {
201 | "enrollId": "user_type8_1",
202 | "enrollSecret": "8c93138916",
203 | "affiliation": "group1",
204 | "username": "user_type8_1",
205 | "secret": "8c93138916"
206 | },
207 | {
208 | "enrollId": "user_type8_2",
209 | "enrollSecret": "eb4db1d75d",
210 | "affiliation": "group1",
211 | "username": "user_type8_2",
212 | "secret": "eb4db1d75d"
213 | },
214 | {
215 | "enrollId": "user_type8_3",
216 | "enrollSecret": "57e801a1c3",
217 | "affiliation": "group1",
218 | "username": "user_type8_3",
219 | "secret": "57e801a1c3"
220 | },
221 | {
222 | "enrollId": "user_type8_4",
223 | "enrollSecret": "888a70c1a8",
224 | "affiliation": "group1",
225 | "username": "user_type8_4",
226 | "secret": "888a70c1a8"
227 | }
228 | ],
229 | "cert": "https://blockchain-certs.mybluemix.net/us.blockchain.ibm.com.cert",
230 | "cert_path": "/certs/peer/cert.pem"
231 | }
--------------------------------------------------------------------------------
/env/local_env.json:
--------------------------------------------------------------------------------
1 | {
2 | "peers": [
3 | {
4 | "discovery_port": 7051,
5 | "api_host": "localhost",
6 | "api_port": 7050,
7 | "api_port_tls": 7050,
8 | "type": "peer",
9 | "network_id": "dev",
10 | "id": "jdoe",
11 | "api_url": "http://localhost:7050"
12 | }
13 | ],
14 | "ca": {
15 | "discovery_port": 7051,
16 | "api_host": "localhost",
17 | "api_port_tls": 7051,
18 | "api_port": 7051,
19 | "type": "ca",
20 | "network_id": "dev",
21 | "url": "http://localhost:7051"
22 | },
23 | "users": [
24 | {
25 | "enrollId": "test_user3",
26 | "enrollSecret": "vWdLCE00vJy0"
27 | }
28 | ],
29 | "cert": "https://blockchain-certs.mybluemix.net/us.blockchain.ibm.com.cert",
30 | "chaincodepath": "./chaincodes/query.go"
31 | }
--------------------------------------------------------------------------------
/env/server_env.json:
--------------------------------------------------------------------------------
1 | {
2 | "peers": [
3 | {
4 | "discovery_port": 7056,
5 | "api_host": "10.17.1.100",
6 | "api_port": 7055,
7 | "api_port_tls": 7055,
8 | "type": "peer",
9 | "network_id": "dev",
10 | "id": "jdoe",
11 | "api_url": "10.17.1.100:7055"
12 | }
13 | ],
14 | "ca": {
15 | "discovery_port": 7056,
16 | "api_host": "10.17.1.100",
17 | "api_port_tls": 7056,
18 | "api_port": 7056,
19 | "type": "ca",
20 | "network_id": "dev",
21 | "url": "10.17.1.100:7056"
22 | },
23 | "users": [
24 | {
25 | "enrollId": "bob",
26 | "enrollSecret": "NOE63pEQbL25"
27 | }
28 | ],
29 | "cert": "https://blockchain-certs.mybluemix.net/us.blockchain.ibm.com.cert",
30 | "chaincodepath": "./chaincodes/query.go"
31 | }
--------------------------------------------------------------------------------
/env/uk_env.json:
--------------------------------------------------------------------------------
1 | {
2 | "peers": [{
3 | "discovery_host": "d169eb482e1f43c38fe579b83da9e68f-vp0.us.blockchain.ibm.com",
4 | "discovery_port": 30003,
5 | "api_host": "d169eb482e1f43c38fe579b83da9e68f-vp0.us.blockchain.ibm.com",
6 | "api_port_tls": 5003,
7 | "api_port": 5003,
8 | "event_host": "d169eb482e1f43c38fe579b83da9e68f-vp0.us.blockchain.ibm.com",
9 | "event_port": 31003,
10 | "type": "peer",
11 | "network_id": "d169eb482e1f43c38fe579b83da9e68f",
12 | "container_id": "c43faa1fa3f8370da775419a1ac1533f23ef5d3fdad3a92169b57bdec5a0661f",
13 | "id": "d169eb482e1f43c38fe579b83da9e68f-vp0",
14 | "api_url": "http://d169eb482e1f43c38fe579b83da9e68f-vp0.us.blockchain.ibm.com:5003"
15 | },
16 | {
17 | "discovery_host": "d169eb482e1f43c38fe579b83da9e68f-vp2.us.blockchain.ibm.com",
18 | "discovery_port": 30003,
19 | "api_host": "d169eb482e1f43c38fe579b83da9e68f-vp2.us.blockchain.ibm.com",
20 | "api_port_tls": 5003,
21 | "api_port": 5003,
22 | "event_host": "d169eb482e1f43c38fe579b83da9e68f-vp2.us.blockchain.ibm.com",
23 | "event_port": 31003,
24 | "type": "peer",
25 | "network_id": "d169eb482e1f43c38fe579b83da9e68f",
26 | "container_id": "5e76e4c65679bc7fc0c26a9a45aa3f7275aff8a81e4f876d230e22763e000c17",
27 | "id": "d169eb482e1f43c38fe579b83da9e68f-vp2",
28 | "api_url": "http://d169eb482e1f43c38fe579b83da9e68f-vp2.us.blockchain.ibm.com:5003"
29 | },
30 | {
31 | "discovery_host": "d169eb482e1f43c38fe579b83da9e68f-vp1.us.blockchain.ibm.com",
32 | "discovery_port": 30003,
33 | "api_host": "d169eb482e1f43c38fe579b83da9e68f-vp1.us.blockchain.ibm.com",
34 | "api_port_tls": 5003,
35 | "api_port": 5003,
36 | "event_host": "d169eb482e1f43c38fe579b83da9e68f-vp1.us.blockchain.ibm.com",
37 | "event_port": 31003,
38 | "type": "peer",
39 | "network_id": "d169eb482e1f43c38fe579b83da9e68f",
40 | "container_id": "8676e75eedd59532b2aee26b86f7fc24391dbabd9255201e196ca9783b58e41c",
41 | "id": "d169eb482e1f43c38fe579b83da9e68f-vp1",
42 | "api_url": "http://d169eb482e1f43c38fe579b83da9e68f-vp1.us.blockchain.ibm.com:5003"
43 | },
44 | {
45 | "discovery_host": "d169eb482e1f43c38fe579b83da9e68f-vp3.us.blockchain.ibm.com",
46 | "discovery_port": 30003,
47 | "api_host": "d169eb482e1f43c38fe579b83da9e68f-vp3.us.blockchain.ibm.com",
48 | "api_port_tls": 5003,
49 | "api_port": 5003,
50 | "event_host": "d169eb482e1f43c38fe579b83da9e68f-vp3.us.blockchain.ibm.com",
51 | "event_port": 31003,
52 | "type": "peer",
53 | "network_id": "d169eb482e1f43c38fe579b83da9e68f",
54 | "container_id": "fc3de29a5c72e561722a5ff7f150f83ce1348784fd0eb06f377e2d1f511c6539",
55 | "id": "d169eb482e1f43c38fe579b83da9e68f-vp3",
56 | "api_url": "http://d169eb482e1f43c38fe579b83da9e68f-vp3.us.blockchain.ibm.com:5003"
57 | }
58 | ],
59 | "ca": {
60 | "d169eb482e1f43c38fe579b83da9e68f-ca": {
61 | "url": "d169eb482e1f43c38fe579b83da9e68f-ca.us.blockchain.ibm.com:30003",
62 | "discovery_host": "d169eb482e1f43c38fe579b83da9e68f-ca.us.blockchain.ibm.com",
63 | "discovery_port": 30003,
64 | "api_host": "d169eb482e1f43c38fe579b83da9e68f-ca.us.blockchain.ibm.com",
65 | "api_port_tls": 30003,
66 | "api_port": 30003,
67 | "type": "ca",
68 | "network_id": "d169eb482e1f43c38fe579b83da9e68f",
69 | "container_id": "df87ae92f776790c427ab07fd387b3262001943fe4ec2c3ec48c63e576d29e33"
70 | }
71 | },
72 | "users": [{
73 | "enrollId": "admin",
74 | "enrollSecret": "eb470d3f0b",
75 | "affiliation": "group1",
76 | "username": "admin",
77 | "secret": "eb470d3f0b"
78 | },
79 | {
80 | "enrollId": "WebAppAdmin",
81 | "enrollSecret": "c9ac727401",
82 | "affiliation": "group1",
83 | "username": "WebAppAdmin",
84 | "secret": "c9ac727401"
85 | },
86 | {
87 | "enrollId": "user_type1_0",
88 | "enrollSecret": "3d3aae343e",
89 | "affiliation": "group1",
90 | "username": "user_type1_0",
91 | "secret": "3d3aae343e"
92 | },
93 | {
94 | "enrollId": "user_type1_1",
95 | "enrollSecret": "d310b2f46e",
96 | "affiliation": "group1",
97 | "username": "user_type1_1",
98 | "secret": "d310b2f46e"
99 | },
100 | {
101 | "enrollId": "user_type1_2",
102 | "enrollSecret": "01b463f57d",
103 | "affiliation": "group1",
104 | "username": "user_type1_2",
105 | "secret": "01b463f57d"
106 | },
107 | {
108 | "enrollId": "user_type1_3",
109 | "enrollSecret": "69fe1f34b9",
110 | "affiliation": "group1",
111 | "username": "user_type1_3",
112 | "secret": "69fe1f34b9"
113 | },
114 | {
115 | "enrollId": "user_type1_4",
116 | "enrollSecret": "9e8dafaa6a",
117 | "affiliation": "group1",
118 | "username": "user_type1_4",
119 | "secret": "9e8dafaa6a"
120 | },
121 | {
122 | "enrollId": "user_type2_0",
123 | "enrollSecret": "521ee25192",
124 | "affiliation": "group1",
125 | "username": "user_type2_0",
126 | "secret": "521ee25192"
127 | },
128 | {
129 | "enrollId": "user_type2_1",
130 | "enrollSecret": "18fd941968",
131 | "affiliation": "group1",
132 | "username": "user_type2_1",
133 | "secret": "18fd941968"
134 | },
135 | {
136 | "enrollId": "user_type2_2",
137 | "enrollSecret": "aebecc0db6",
138 | "affiliation": "group1",
139 | "username": "user_type2_2",
140 | "secret": "aebecc0db6"
141 | },
142 | {
143 | "enrollId": "user_type2_3",
144 | "enrollSecret": "2415f86984",
145 | "affiliation": "group1",
146 | "username": "user_type2_3",
147 | "secret": "2415f86984"
148 | },
149 | {
150 | "enrollId": "user_type2_4",
151 | "enrollSecret": "3ce9bb70ba",
152 | "affiliation": "group1",
153 | "username": "user_type2_4",
154 | "secret": "3ce9bb70ba"
155 | },
156 | {
157 | "enrollId": "user_type4_0",
158 | "enrollSecret": "26e3f4d8ce",
159 | "affiliation": "group1",
160 | "username": "user_type4_0",
161 | "secret": "26e3f4d8ce"
162 | },
163 | {
164 | "enrollId": "user_type4_1",
165 | "enrollSecret": "a9e498c832",
166 | "affiliation": "group1",
167 | "username": "user_type4_1",
168 | "secret": "a9e498c832"
169 | },
170 | {
171 | "enrollId": "user_type4_2",
172 | "enrollSecret": "b9c905f7ef",
173 | "affiliation": "group1",
174 | "username": "user_type4_2",
175 | "secret": "b9c905f7ef"
176 | },
177 | {
178 | "enrollId": "user_type4_3",
179 | "enrollSecret": "3a05edfe07",
180 | "affiliation": "group1",
181 | "username": "user_type4_3",
182 | "secret": "3a05edfe07"
183 | },
184 | {
185 | "enrollId": "user_type4_4",
186 | "enrollSecret": "a8cba8d969",
187 | "affiliation": "group1",
188 | "username": "user_type4_4",
189 | "secret": "a8cba8d969"
190 | },
191 | {
192 | "enrollId": "user_type8_0",
193 | "enrollSecret": "a92650648a",
194 | "affiliation": "group1",
195 | "username": "user_type8_0",
196 | "secret": "a92650648a"
197 | },
198 | {
199 | "enrollId": "user_type8_1",
200 | "enrollSecret": "998c72714f",
201 | "affiliation": "group1",
202 | "username": "user_type8_1",
203 | "secret": "998c72714f"
204 | },
205 | {
206 | "enrollId": "user_type8_2",
207 | "enrollSecret": "6761de8ee0",
208 | "affiliation": "group1",
209 | "username": "user_type8_2",
210 | "secret": "6761de8ee0"
211 | },
212 | {
213 | "enrollId": "user_type8_3",
214 | "enrollSecret": "37c8778063",
215 | "affiliation": "group1",
216 | "username": "user_type8_3",
217 | "secret": "37c8778063"
218 | },
219 | {
220 | "enrollId": "user_type8_4",
221 | "enrollSecret": "3f84a79c79",
222 | "affiliation": "group1",
223 | "username": "user_type8_4",
224 | "secret": "3f84a79c79"
225 | }
226 | ],
227 | "cert": "https://blockchain-certs.mybluemix.net/us.blockchain.ibm.com.cert",
228 | "cert_path": "/certs/peer/cert.pem"
229 | }
--------------------------------------------------------------------------------
/manifest.yml:
--------------------------------------------------------------------------------
1 | applications:
2 | - path: .
3 | memory: 256M
4 | instances: 1
5 | domain: mybluemix.net
6 | name: Blockchain-Go
7 | host: ibm-blockchain-demo
8 | disk_quota: 1024M
9 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "BlockchainNodeApp",
3 | "version": "0.0.1",
4 | "private": true,
5 | "scripts": {
6 | "start": "node app.js"
7 | },
8 | "dependencies": {
9 | "express": "~4.13.3",
10 | "cfenv": "1.0.x",
11 | "fs": "0.0.2",
12 | "body-parser": "",
13 | "request-promise": "^2.0.1",
14 | "morgan": ""
15 | },
16 | "repository": {},
17 | "engines": {
18 | "node": "4.x"
19 | }
20 | }
--------------------------------------------------------------------------------
/public/images/CatToast1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diego-blockchain/blockchain-go/93d8aad7e29c73e1cda4d7fed3cde4e0b671f611/public/images/CatToast1.gif
--------------------------------------------------------------------------------
/public/images/CatToast2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diego-blockchain/blockchain-go/93d8aad7e29c73e1cda4d7fed3cde4e0b671f611/public/images/CatToast2.gif
--------------------------------------------------------------------------------
/public/images/Underground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diego-blockchain/blockchain-go/93d8aad7e29c73e1cda4d7fed3cde4e0b671f611/public/images/Underground.png
--------------------------------------------------------------------------------
/public/images/blockchain.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diego-blockchain/blockchain-go/93d8aad7e29c73e1cda4d7fed3cde4e0b671f611/public/images/blockchain.png
--------------------------------------------------------------------------------
/public/images/blockchain_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diego-blockchain/blockchain-go/93d8aad7e29c73e1cda4d7fed3cde4e0b671f611/public/images/blockchain_icon.png
--------------------------------------------------------------------------------
/public/images/error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diego-blockchain/blockchain-go/93d8aad7e29c73e1cda4d7fed3cde4e0b671f611/public/images/error.png
--------------------------------------------------------------------------------
/public/images/gears.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diego-blockchain/blockchain-go/93d8aad7e29c73e1cda4d7fed3cde4e0b671f611/public/images/gears.gif
--------------------------------------------------------------------------------
/public/images/pallete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diego-blockchain/blockchain-go/93d8aad7e29c73e1cda4d7fed3cde4e0b671f611/public/images/pallete.png
--------------------------------------------------------------------------------
/public/images/player1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diego-blockchain/blockchain-go/93d8aad7e29c73e1cda4d7fed3cde4e0b671f611/public/images/player1.png
--------------------------------------------------------------------------------
/public/images/player2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diego-blockchain/blockchain-go/93d8aad7e29c73e1cda4d7fed3cde4e0b671f611/public/images/player2.png
--------------------------------------------------------------------------------
/public/images/player3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/diego-blockchain/blockchain-go/93d8aad7e29c73e1cda4d7fed3cde4e0b671f611/public/images/player3.png
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | blockchain-go
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
Smart Contract
26 | If the temperature exceeds 24ºC, the package must be inspected.
27 | The party responsible for the package at the time of the temperature
28 | increase is held accountable for all losses.
29 |
30 |
31 |
32 |
Play Tracking
33 |
34 |
35 |
36 |
Status Monitor
37 |
38 | Current owner:
39 | Time now:
40 | Last transaction:
41 | Contract status:
42 | Temperature:
43 | -
44 | +
45 |
46 | See contract
47 |
48 |
49 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 | Our interactive demo tracks the shipment of a package as it moves along the supply chain,
64 | passing through multiple carriers. It shows how an IoT-enabled package transmits required
65 | status information along the way and how each transaction is tracked and shared among all
66 | partners in a blockchain.
67 | Start Demo
68 |
69 |
70 |
71 |
72 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/public/js/animation.js:
--------------------------------------------------------------------------------
1 | /*creating animated blocks for monitor*/
2 | let block = 0;
3 | let space = 32, currentPayload;
4 | let blocksArray = [];
5 |
6 | function getStats() {
7 | $.get('/blockchain', function(data) {
8 | let found = false;
9 | blocksArray.forEach(function(seekAndDestroy) {
10 | if (seekAndDestroy.height === data.height) {
11 | console.log(`block allready exists ${data.height}`);
12 | found = true;
13 | return;
14 | }
15 | });
16 | if (!found) {
17 | blocksArray.push(data);
18 | let appendToHistory = payloadHistory[payloadHistory.length - 1];
19 | appendToHistory.height = data.height;
20 | //console.log("data.height: " + data.height + "last \n" + JSON.stringify(payloadHistory[payloadHistory.length - 1].height));
21 | block = block + 1;
22 | $(".animationDiv").append("" + data.height + "
");
23 | $('.block:last').animate({ opacity: 1, left: (block * space) }, 1000, function() {
24 | $('.lastblock').removeClass('lastblock');
25 | if (appendToHistory.temperature > 24) { //appendToHistory.status === true &&
26 | console.log(`getStats - status(return): ${appendToHistory.status} && ${appendToHistory.temperature}`);
27 | $('.block:last').addClass('alertBlock');
28 | } else {
29 | $('.block:last').addClass('lastblock');
30 | }
31 | });
32 | //console.log(JSON.stringify(data) + typeof (data));
33 | block++;
34 | }
35 | });
36 | }
37 |
38 | function sendBlocks(payload) {
39 | payload.user = currentPlayer.getTitle();
40 | payload.action = "transfer";
41 | doTransaction(payload);
42 | //console.log("sendBlocks: " + JSON.stringify(payload));
43 | }
44 |
45 | function getDeploymentBlock() {
46 | $.get('/genesis', function(deployed) {
47 | blocksArray.push(deployed);
48 | payloadHistory.push(deployed);
49 | block = block + 1;
50 | $(".animationDiv").append("" + deployed.height + "
");
51 | $('.block:last').animate({ opacity: 1, left: (block * space) }, 1000, function() {
52 | $('.lastblock').removeClass('lastblock');
53 | $('.block:last').addClass('lastblock');
54 | });
55 | block++;
56 | });
57 | }
58 |
59 |
60 | $(document).on('mouseover', '.block', function(event) {
61 | let height = Number($(this).html());
62 | //console.log(`let height = Number($(this).html() ${height}`);
63 | payloadHistory.forEach(function(dataHistory) {
64 | //console.log("dataHistory " + JSON.stringify(dataHistory));
65 | if (dataHistory.height === height) {
66 | currentPayload = dataHistory;
67 | }
68 | });
69 | show_details(event, height, currentPayload);
70 | });
71 |
72 | $(document).on('mouseleave', '.block', function() {
73 | $('#details').fadeOut();
74 | });
75 |
76 | //Missing payload info
77 | function show_details(event, id, message) {
78 | let currentBlock;
79 | var left, html, deploy = false;
80 | blocksArray.forEach(function(current) {
81 | if (current.height === id) {
82 | currentBlock = current;
83 | //console.log(currentBlock.height + " || " + id + " || " + message.height + " all " + JSON.stringify(currentBlock));
84 | }
85 | if (message.isDeploy) {
86 | message = { deployment: "first block!", created: message.lastTransaction }
87 | currentBlock.consensusMetadata = "genesis";
88 | deploy = true;
89 | } else if (message.isInit) {
90 | console.log(`isInit: ${message.isInit}`);
91 | message.action = "init";
92 | }
93 | });
94 |
95 | left = event.pageX - $('#details').parent().offset().left - 120;
96 |
97 | if (left < 0) left = 0;
98 | html = ' Ledger Block Height: ' + currentBlock.height + '
';
99 | html += 'Created: ' + formatDate(currentBlock.created * 1000, '%M-%d-%Y %I:%m%p') + '
';
100 | html += ' UUID:  ' + currentBlock.uuid.slice(0, 17);
101 | //html += ' Type: ' + message.type + '
';
102 | html += ' Consensus Metadata: ' + currentBlock.consensusMetadata + '
';
103 | if (!deploy) {
104 | if (message.action === undefined) {
105 | message.action = "update";
106 | }
107 | html += ' Action:  ' + message.action + ' ';
108 | html += ' Description:  ' + message.description + ' ';
109 | html += ' Owner:  ' + message.user + ' ';
110 | html += ' Temperature:  ' + message.temperature + ' C.° ';
111 | } else {
112 | html += ' Payload: ' + JSON.stringify(message) + ' ';
113 | }
114 | if (message.temperature > 24) {
115 | console.log("alert details");
116 | $('#details').addClass('alertDetails');
117 |
118 | }
119 | $('#details').html(html).css('left', left).fadeIn();
120 |
121 | }
122 |
123 | function formatDate(date, fmt) {
124 | date = new Date(date);
125 | function pad(value) {
126 | return (value.toString().length < 2) ? '0' + value : value;
127 | }
128 | return fmt.replace(/%([a-zA-Z])/g, function(_, fmtCode) {
129 | var tmp;
130 | switch (fmtCode) {
131 | case 'Y': //Year
132 | return date.getUTCFullYear();
133 | case 'M': //Month 0 padded
134 | return pad(date.getUTCMonth() + 1);
135 | case 'd': //Date 0 padded
136 | return pad(date.getUTCDate());
137 | case 'H': //24 Hour 0 padded
138 | return pad(date.getUTCHours());
139 | case 'I': //12 Hour 0 padded
140 | tmp = date.getUTCHours();
141 | if (tmp === 0) tmp = 12; //00:00 should be seen as 12:00am
142 | else if (tmp > 12) tmp -= 12;
143 | return pad(tmp);
144 | case 'p': //am / pm
145 | tmp = date.getUTCHours();
146 | if (tmp >= 12) return 'pm';
147 | return 'am';
148 | case 'P': //AM / PM
149 | tmp = date.getUTCHours();
150 | if (tmp >= 12) return 'PM';
151 | return 'AM';
152 | case 'm': //Minutes 0 padded
153 | return pad(date.getUTCMinutes());
154 | case 's': //Seconds 0 padded
155 | return pad(date.getUTCSeconds());
156 | case 'r': //Milliseconds 0 padded
157 | return pad(date.getUTCMilliseconds(), 3);
158 | case 'q': //UTC timestamp
159 | return date.getTime();
160 | default:
161 | throw new Error('Unsupported format code: ' + fmtCode);
162 | }
163 | });
164 | }
--------------------------------------------------------------------------------
/public/js/demo.js:
--------------------------------------------------------------------------------
1 | var map,
2 | uuid,
3 | marker,
4 | route,
5 | markers,
6 | trigger,
7 | trigger$,
8 | mqttClient,
9 | currentPlayer,
10 | dataInfo,
11 | infowindow,
12 | humidity,
13 | verifyValue,
14 | verifyOwner = "No",
15 | temperature = 21,
16 | payloadHistory = [],
17 | heldAccountable = false,
18 | count = 1, steps = 0,
19 | status = 'Satisfied',
20 | rand = Math.floor((Math.random() * 8000) + 1),
21 | pack = "Asset Package " + rand,
22 | now = new Date().toLocaleString(),
23 | data = { description: pack, user: "Industry", action: "create", temperature: temperature, lastTransaction: now };
24 |
25 |
26 | var defaultCoordinates = [{
27 | "lat": -23.56996189423875,
28 | "lng": -46.65141653365975
29 | }, {
30 | "lat": -23.57997497987705,
31 | "lng": -46.6491940773286
32 | }, {
33 | "lat": -23.581153,
34 | "lng": -46.663667
35 | }, {
36 | "lat": -23.581645286215887,
37 | "lng": -46.64944620296468
38 | }];
39 |
40 | var playerSet = [
41 | ['Industry', defaultCoordinates[0].lat, defaultCoordinates[0].lng, 2],
42 | ['Shipping Company', defaultCoordinates[1].lat, defaultCoordinates[1].lng, 3],
43 | ['Customer', defaultCoordinates[2].lat, defaultCoordinates[2].lng, 4]
44 | ];
45 |
46 | //---------------------//----------------------------//----------------//
47 |
48 | /*{@Object data}
49 | *On ready callback controls all the elements and order on tracking
50 | **/
51 | $(document).ready(function () {
52 |
53 | $('#myModal').modal('show');
54 |
55 | /*@{Object data} creates an asset triggering createAsset & doTransaction*/
56 | $('.btn-primary').click(function () {
57 | currentPlayer = markers[0];
58 | getDeploymentBlock();
59 | createAsset(data);
60 | });
61 |
62 | $('#startDemo').click(function () {
63 | $(".assetContainer").fadeOut("slow");
64 | setupTracking();
65 | seePackage();
66 | $(this).fadeOut();
67 | });
68 |
69 | $("#btnUpTemp").click(function () {
70 | temperature++;
71 | data.temperature = temperature;
72 | $("#lblTemperature").text(`${temperature} ºC`);
73 | console.log(data.temperature);
74 | });
75 |
76 | $("#btnDownTemp").click(function () {
77 | temperature--;
78 | data.temperature = temperature;
79 | $("#lblTemperature").text(`${temperature} ºC`);
80 | console.log(data.temperature);
81 | });
82 | });
83 |
84 | //------------------//-------------------------//--------------------//
85 |
86 | /*@{Object data} - Rest functions*/
87 | function doTransaction(action) {
88 | //console.log("[doTransaction]request: ${action} " + JSON.stringify(action));
89 | $.post('/request', action).done(function onSuccess(res) {
90 | data = res;
91 | console.log(`[doTransaction]success ${res.description}`);
92 | if (data.temperature > 24) {
93 | console.log(`doTransaction - status(return): ${data.status}`);
94 | data.status = true;
95 | }
96 | payloadHistory.push(data);
97 | getStats(payloadHistory);
98 | if (data.status === true && data.user === currentPlayer.getTitle()) {
99 | console.log(`${currentPlayer.getTitle()} = ${data.user}`);
100 | heldAccountable = true;
101 | checkStatus(data);
102 | } else {
103 | heldAccountable = false;
104 | data.status === false;
105 | }
106 | }).fail(function onError(error) {
107 | console.log(`error requesting ${error}`);
108 | });
109 | }
110 |
111 | function checkStatus(context) {
112 | //console.log(`checkStatus ${context.status}`);
113 | statsEventListenner(context);
114 | if (temperature > 24) { //heldAccountable ||
115 | status = "Verify Package! " + currentPlayer.getTitle() + "";
116 | let alertMsg = " " + context.user + " has violated the contract! ";
117 | infowindow.setContent(alertMsg);
118 | infowindow.open(map, currentPlayer);
119 | verifyValue = temperature;
120 | data.status === false;
121 | console.log(`verifyValue: (checkStatus) ${verifyValue}`);
122 | console.log(`status: (false?) ${data.status}`);
123 | for (var i = 1; i < playerSet.length - 1; i++) {
124 | if (playerSet[i][0] === currentPlayer.getTitle()) {
125 | verifyOwner = playerSet[i][0];
126 | }
127 | }
128 | } else {
129 | verifyValue = undefined;
130 | heldAccountable = false;
131 | data.status = false;
132 | }
133 | }
134 |
135 | /*@{Function data} - starting animation(executes once - calls playTracking() => interval)*/
136 | function setupTracking() {
137 | //info balloon notification
138 | dataInfo = currentPlayer.getTitle() + " is shipping assets";
139 | infowindow = new google.maps.InfoWindow({
140 | content: dataInfo,
141 | maxWidth: 250,
142 | maxHeight: 80
143 | });
144 |
145 | infowindow.open(map, currentPlayer);
146 | trigger = setInterval(function () {
147 | playTracking(data)
148 | }, 1000);
149 |
150 | trigger$ = setInterval(function () {
151 | sendBlocks(data);
152 | }, 9000)
153 | //ensuring it has valid objects
154 | markers.forEach(function (icon) {
155 | console.log(`marker ${icon.getTitle()}`);
156 | });
157 | }
158 |
159 | /*@{Function data} this function "animates" the icons through the route*/
160 | function playTracking(values) {
161 |
162 | let package = values; //fix error VM311
163 | //set of variables to hold current and next lat/long(comparision)
164 | let currentLat = currentPlayer.getPosition().lat();
165 | let nextLat = markers[count].getPosition().lat();
166 | let currentLng = currentPlayer.getPosition().lng();
167 | let nextLng = markers[count].getPosition().lng();
168 | if (verifyValue !== undefined) {
169 | package.temperature = verifyValue
170 | console.log(`Verifying value ${verifyValue} || infractors?: ${verifyOwner} heldAccountable ${heldAccountable}`);
171 | }
172 |
173 | /*console.log(`heldAccountable ${heldAccountable}`);
174 | console.log(`status now ${data.status}`);*/
175 |
176 | //update stats window
177 | checkStatus(package);
178 | currentPlayer.setPosition(route[steps + 15]);
179 | //console.log(`steps ${steps}`);
180 | if (currentLat - nextLat < 0.0000013522 && currentLng - nextLng < 0.0000013522) {
181 | console.log(`count ${count}`);
182 | currentPlayer = markers[count];
183 | package.user = currentPlayer.getTitle();
184 | package.action = "transfer";
185 |
186 | //current package's owner
187 | /*console.log(`interval ${package.user}`);*/
188 |
189 | //request to server
190 | doTransaction(package);
191 |
192 | //delay to update all UI elements with the new state
193 | setTimeout(function () {
194 | $('#currentPlayer').html(currentPlayer.getTitle());
195 | infowindow.setContent(package.user + " is shipping assets");
196 | infowindow.open(map, currentPlayer);
197 | count++;
198 | if (count === 3) {
199 | package.user = currentPlayer.getTitle();
200 | package.action = "transfer";
201 | doTransaction(package);
202 | stopTracking(trigger, trigger$);
203 | checkStatus(package);
204 | infowindow.setContent("Order finished");
205 | }
206 | }, 500);
207 | }
208 | steps++;
209 | }
210 |
211 | /*@{Object data} - stops playTracking()*/
212 | function stopTracking(interval, interval$) {
213 | clearInterval(interval$);
214 | clearInterval(interval);
215 | finalSummary();
216 | //console.log("payloadHistory " + JSON.stringify(payloadHistory));
217 | }
218 |
219 | //--------------------------------------------//------------------------------------------------
220 |
221 | /*Drawing Map*/
222 | function initMap() {
223 | directionsService = new google.maps.DirectionsService;
224 | directionsDisplay = new google.maps.DirectionsRenderer({
225 | draggable: true,
226 | suppressMarkers: true
227 | });
228 |
229 | var mapCenter = new google.maps.LatLng(
230 | defaultCoordinates[defaultCoordinates.length - 1].lat,
231 | defaultCoordinates[defaultCoordinates.length - 1].lng);
232 |
233 | var mapOptions = {
234 | center: mapCenter,
235 | zoom: 14,
236 | mapTypeId: google.maps.MapTypeId.HYBRID
237 | };
238 |
239 | map = new google.maps.Map(document.getElementById('map'), mapOptions);
240 |
241 | directionsDisplay.setMap(map);
242 | calculateAndDisplayRoute(directionsService, directionsDisplay);
243 | setMarkers(map);
244 | }
245 |
246 | function setMarkers(map) {
247 | let image, img;
248 | markers = [];
249 | for (var x = 0; x < playerSet.length; x++) {
250 | let actors = playerSet[x];
251 | img = x + 1;
252 | image = 'images/player' + img + '.png';
253 | marker = new google.maps.Marker({
254 | position: { lat: actors[1], lng: actors[2] },
255 | map: map,
256 | icon: image,
257 | animation: google.maps.Animation.DROP,
258 | title: actors[0],
259 | zIndex: actors[3],
260 | draggable: false
261 | });
262 | markers.push(marker);
263 | marker.addListener('dragend', function () {
264 | let player = this.getTitle();
265 | for (var y in playerSet) {
266 | if (playerSet[y][0] === player) {
267 | playerSet[y][1] = this.getPosition().lat();
268 | playerSet[y][2] = this.getPosition().lng();
269 | }
270 | }
271 | calculateAndDisplayRoute(directionsService, directionsDisplay);
272 | });
273 | }
274 | }
275 |
276 | function calculateAndDisplayRoute(directionsService, directionsDisplay) {
277 | var waypts = [];
278 |
279 | for (var i = 1; i < playerSet.length - 1; i++) {
280 | var position = { "lat": playerSet[i][1], "lng": playerSet[i][2] };
281 | waypts.push({
282 | location: position,
283 | stopover: true
284 | });
285 | }
286 |
287 | directionsService.route({
288 | origin: { lat: playerSet[0][1], lng: playerSet[0][2] },
289 | destination: { lat: playerSet[playerSet.length - 1][1], lng: playerSet[playerSet.length - 1][2] },
290 | waypoints: waypts,
291 | optimizeWaypoints: true,
292 | travelMode: google.maps.TravelMode.DRIVING
293 | }, function (data, status) {
294 | if (status === google.maps.DirectionsStatus.OK) {
295 | //preserveViewport: true => solved the zoom issue
296 | directionsDisplay.setOptions({ preserveViewport: true });
297 | directionsDisplay.setDirections(data);
298 | route = data.routes[0].overview_path;
299 |
300 | }
301 | });
302 | //map.setZoom(2);
303 | //console.log(`maps zoom: ${map.getZoom()}`);
304 | }
305 |
306 | /*--------------//-----------------------------------//---------------------*/
307 |
308 | /*UI events listenner*/
309 |
310 | function onLoadAsset() {
311 | $('.modal-content').empty();
312 | $('.modal-content').append('Creating Asset... ');
313 | $(".loading").fadeIn();
314 | }
315 |
316 | function createAsset(init) {
317 | onLoadAsset();
318 | doTransaction(init);
319 | let assetContainerBody = $('.assetContainerBody');
320 | let animationDiv = $('.animationDiv');
321 | let blockchainInfoDiv = $('.blockchainInfo');
322 | let assetContainer = $('.assetContainer');
323 | let btnStart = $('assetContainerBody button');
324 |
325 | setTimeout(function () {
326 | if (data !== null && data !== undefined) {
327 |
328 | $('.modal-backdrop').fadeOut();
329 | $('.modal-dialog').fadeOut("slow");
330 | $('#myModal').modal('hide');
331 |
332 | assetContainerBody.append(' ' +
333 | 'Asset created ' +
334 | 'Owner: ' + data.user.toUpperCase() +
335 | 'Description: ' + data.description +
336 | 'Registered: ' + data.lastTransaction);
337 |
338 | blockchainInfoDiv.fadeIn("slow");
339 | animationDiv.fadeIn("slow");
340 | assetContainer.fadeIn("slow");
341 | assetContainer.addClass("extendContainer");
342 | assetContainerBody.fadeIn("slow");
343 | btnStart.fadeIn("slow");
344 | checkStatus(init);
345 | }
346 | else {
347 | return alert("error creating asset.please try again");
348 | }
349 | }, 3000);
350 | }
351 |
352 | function seePackage() {
353 | $("#showPackage").mouseover(function () {
354 | $(".assetContainer").fadeIn("slow");
355 | });
356 |
357 | $("#showPackage").mouseout(function () {
358 | $(".assetContainer").fadeOut("slow");
359 | });
360 | }
361 |
362 | function finalSummary() {
363 |
364 | let content = $('.modal-content');
365 | let c = 1;
366 | content.empty();
367 | content.append('
Transaction History ' +
368 | '');
370 |
371 | payloadHistory.forEach(function (log) {
372 | //console.log("generating summary " + JSON.stringify(log));
373 | if (log.description !== undefined) {
374 | $('.modal-body').append('Description:\n '
375 | + log.description + ' User: ' + log.user + ' temperature: ' + log.temperature + ' C.°
');
376 |
377 | if (log.temperature > 24) {
378 | let thisElem = "#historyLog" + c;
379 | console.log(`temperature$ ${log.temperature}`);
380 | $(thisElem).addClass("infractorData");
381 | }
382 | c++;
383 | }
384 | });
385 |
386 | //showing final summary
387 | console.log(`modal-fade:`);
388 | $('.modal-dialog').modal();
389 | $('#myModal').modal("show");
390 |
391 | $('.hideModal').click(function () {
392 | $('.modal-dialog').modal("hide");
393 | $('#myModal').modal("hide");
394 | });
395 | }
396 |
397 | /*@{Object data} - listenner to blockchain events*/
398 | function statsEventListenner(context) {
399 | let currenTime = new Date().toLocaleString();
400 | console.log(`temp changing: ${context.temperature} || ${temperature}`);
401 | if (context.temperature !== temperature) {
402 | context.temperature = temperature;
403 | }
404 | $("#lblTemperature").text(`${temperature} ºC`);
405 | $("#lblTime").text(`${currenTime}`);
406 | $("#lastTransactionTime").text(`${context.lastTransaction}`);
407 | $("#lblDescription").text(`${context.description}`);
408 | $("#lblOwner").text(`${currentPlayer.getTitle()}`);
409 | $("#lblStatus").text(`${status}`);
410 | }
--------------------------------------------------------------------------------
/public/js/mqttClient.js:
--------------------------------------------------------------------------------
1 | //Mqtt Client functions
2 |
3 | // Create a client instance
4 | mqttClient = new Paho.MQTT.Client("b6kg16.messaging.internetofthings.ibmcloud.com", 1883, "a:b6kg16:mapui");
5 |
6 | // set callback handlers
7 | mqttClient.onConnectionLost = onConnectionLost;
8 | mqttClient.onMessageArrived = onMessageArrived;
9 |
10 | // connect the mqttClient
11 | mqttClient.connect({
12 | onSuccess: onConnect,
13 | userName: "a-b6kg16-makbfawlct",
14 | password: "xEQKOkZ+SL@TT5zXp&"
15 | });
16 |
17 |
18 | // called when the mqttClient connects
19 | function onConnect() {
20 | // Once a connection has been made, make a subscription and send a message.
21 |
22 | mqttClient.subscribe("iot-2/type/+/id/linkitone01/evt/telemetry/fmt/json");
23 | mqttClient.subscribe("iot-2/type/+/id/fake_device/evt/telemetry/fmt/json");
24 | message = new Paho.MQTT.Message("Hello");
25 | message.destinationName = "/World";
26 | mqttClient.send(message);
27 | }
28 |
29 | // called when the mqttClient loses its connection
30 | function onConnectionLost(responseObject) {
31 | if (responseObject.errorCode !== 0) {
32 | console.log(`error connecting to mqtt ${responseObject.errorCode}`);
33 | }
34 | }
35 |
36 | // called when a message arrives
37 | function onMessageArrived(message) {
38 | payload = JSON.parse(message.payloadString);
39 | payload.timestamp = new Date().getTime();
40 | temperature = Number((payload.t - 273).toFixed(2));
41 | console.log(`connected ${message.payloadString}`);
42 | //validating contract
43 |
44 | }
--------------------------------------------------------------------------------
/public/stylesheets/style.css:
--------------------------------------------------------------------------------
1 | html, body {
2 | height: 100%;
3 | margin: 0;
4 | padding: 0;
5 | }
6 |
7 | #map {
8 | height: 100%;
9 | }
10 |
11 | .hideModal {
12 | position: absolute;
13 | cursor: pointer;
14 | left: 5%;
15 | }
16 |
17 | #introBlockChain {
18 | text-align: center;
19 | }
20 |
21 | body .modal-dialog {
22 | width: 80%;
23 | align-content: center;
24 | }
25 |
26 | body .modal-dialog img {
27 | width: 80%;
28 | position: relative;
29 | left: 10%;
30 | }
31 |
32 | .assetContainerBody {
33 | display: none;
34 | }
35 |
36 | #packageImg {
37 | width: 30%;
38 | max-width: 45%;
39 | height: 30%;
40 | max-height: 45%;
41 | }
42 |
43 | .smartContract {
44 | border-radius: 8px;
45 | align-items: center;
46 | width: auto;
47 | min-width: 10%;
48 | height: auto;
49 | min-height: 10%;
50 | }
51 |
52 | .smartContract span {
53 | border-radius: 4px;
54 | color: #ffffff;
55 | font-size: 120%;
56 | }
57 |
58 | #gearsLoad {
59 | position: absolute;
60 | left: 45%;
61 | width: 20%;
62 | height: 15%;
63 | color: darkorange;
64 | border-right: 25px #222832 solid;
65 | border-left: 25px #222832 solid;
66 | border-top-right-radius: 10px;
67 | border-top-left-radius: 10px;
68 | border-bottom-right-radius: 10px;
69 | border-bottom-left-radius: 10px;
70 | }
71 |
72 | .assetContainer {
73 | width: auto;
74 | max-width: 40%;
75 | height: auto;
76 | max-height: 70%;
77 | position: absolute;
78 | right: 0;
79 | top: 45px;
80 | color: #7E90A0;
81 | background: #222832;
82 | align-items: center;
83 | padding: 30px 0;
84 | border-left: 25px #222832 solid;
85 | border-top-left-radius: 10px;
86 | border-bottom-left-radius: 10px;
87 | text-align: center;
88 | }
89 |
90 | .loadAsset {
91 | width: 25%;
92 | }
93 |
94 | .finalsummary {
95 | border-top-right-radius: 10px;
96 | border-top-left-radius: 10px;
97 | border-bottom-right-radius: 10px;
98 | border-bottom-left-radius: 10px;
99 | background: cornflowerblue;
100 | color: white;
101 | align-items: center;
102 | text-align: center;
103 | min-width: 30%;
104 | }
105 |
106 | .fullbody {
107 | background: #222832;
108 | color: #7E90A0;
109 | }
110 |
111 | .infractorData {
112 | color: orangered;
113 | }
114 |
115 | .btn-primary {
116 | right: 2%;
117 | bottom: 2%;
118 | position: absolute;
119 | }
120 |
121 | .btn-warning {
122 | width: 5px;
123 | height: 5px;
124 | align-content: center;
125 | }
126 |
127 | #myModal {
128 | width: 80%;
129 | top: 10%;
130 | position: absolute;
131 | left: 10%;
132 | }
133 |
134 | .blockchainInfo {
135 | width: auto;
136 | max-width: 55%;
137 | height: auto;
138 | max-height: 85%;
139 | position: absolute;
140 | left: 2%;
141 | top: 10%;
142 | color: #7E90A0;
143 | background: #222832;
144 | align-items: center;
145 | padding: 30px 0;
146 | border-right: 25px #222832 solid;
147 | border-left: 25px #222832 solid;
148 | border-top-right-radius: 10px;
149 | border-top-left-radius: 10px;
150 | border-bottom-right-radius: 10px;
151 | border-bottom-left-radius: 10px;
152 | text-align: center;
153 | }
154 |
155 | .blockchainInfo label {
156 | width: auto;
157 | height: auto;
158 | }
159 |
160 | .assetContainerBody button {
161 | top: 70%;
162 | width: auto;
163 | height: auto;
164 | }
165 |
166 | .assetContainerBody label {
167 | width: auto;
168 | height: auto;
169 | }
170 |
171 | .extendContainer {
172 | height: 67%;
173 | transition-duration: 1.5;
174 | }
175 |
176 | .stats {
177 | font: 30%;
178 | color: darkorange;
179 | align-self: center;
180 | }
181 |
182 | #showPackage:hover {
183 | cursor: pointer;
184 | }
185 |
186 | .alert {
187 | align-self: center;
188 | font-size: 130%;
189 | color: red;
190 | }
191 |
192 | .animationDiv {
193 | position: absolute;
194 | width: 70%;
195 | background: #222832;
196 | height: 7%;
197 | bottom: 2%;
198 | left: 15%;
199 | align-self: center;
200 | border-right: 25px #222832 solid;
201 | border-left: 25px #222832 solid;
202 | border-top-right-radius: 10px;
203 | border-top-left-radius: 10px;
204 | border-bottom-right-radius: 10px;
205 | border-bottom-left-radius: 10px;
206 | }
207 |
208 | .alertDetails {
209 | background: #222832;
210 | color: darkorange;
211 | display: none;
212 | position: absolute;
213 | top: -400%;
214 | width: 270px;
215 | min-width: 130px;
216 | min-height: 80px;
217 | max-height: 350px;
218 | border-radius: 10px;
219 | padding: 15px 30px;
220 | word-break: break-all;
221 | font-size: 12px;
222 | }
223 |
224 | #details {
225 | background: #222832;
226 | color: #2EB9D6;
227 | display: none;
228 | position: relative;
229 | top: -400%;
230 | width: 270px;
231 | min-width: 130px;
232 | min-height: 80px;
233 | max-height: 350px;
234 | border-radius: 10px;
235 | padding: 15px 30px;
236 | word-break: break-all;
237 | font-size: 12px;
238 | }
239 |
240 | .block:hover {
241 | cursor: pointer;
242 | }
243 |
244 | .block {
245 | line-height: 30px;
246 | color: #2EB9D6;
247 | text-align: center;
248 | position: absolute;
249 | top: 5%;
250 | left: 110%;
251 | height: 90%;
252 | width: 62px;
253 | border-radius: 4px;
254 | opacity: 5;
255 | border: #2EB9D6 solid 1px;
256 | font-size: 12px;
257 | transition: background-color 0.5s ease;
258 | font-weight: bold;
259 | }
260 |
261 | .alertBlock {
262 | transition: background-color 1s ease;
263 | background: #222832;
264 | color: darkorange;
265 | border-color: red;
266 | }
267 |
268 | .lastblock {
269 | transition: background-color 1s ease;
270 | background: #2EB9D6;
271 | color: #222832;
272 | border-color: #2EB9D6;
273 | }
274 |
275 | .block:hover {
276 | border: #22697A solid 1px;
277 | color: #22697A;
278 | }
--------------------------------------------------------------------------------
/rest/api.js:
--------------------------------------------------------------------------------
1 | /**************************************
2 | * Copyright 2016 IBM Corp. All Rights Reserved.
3 | * Rest module for interaction with a blockchain network.
4 | * First implementation by Vitor Diego
5 | * ************************************/
6 | 'use strict'
7 |
8 | const request = require('request-promise');
9 | const blockchain = require('../rest/listenner')();
10 |
11 | module.exports = function (host, port) {
12 |
13 | var chaincodeId, secureContextId;
14 |
15 | function registrar(user, secret) {
16 | console.log(`registrar() =>`);
17 | let url = "https://" + host + ":" + port
18 | var options = {
19 | //"method": 'POST',
20 | "url": url + '/registrar',
21 | "headers": {
22 | 'Accept': 'application/json',
23 | 'Content-Type': 'application/json'
24 | },
25 | "body": JSON.stringify({
26 | "enrollId": user,
27 | "enrollSecret": secret
28 | })
29 | };
30 |
31 | request.post(options).then(function (response) {
32 | console.log(`[registrar] success: ${response}`);
33 | secureContextId = user;
34 | blockchain.getListener(host, port);
35 | return init();
36 | }).catch(function (err) {
37 | if (err) {
38 | console.log(`[registrar] error: ${err}`);
39 | return err;
40 | }
41 | });
42 | }
43 |
44 | function init() {
45 | console.log(`init() =>`);
46 | let url = "https://" + host + ":" + port
47 | var options = {
48 | //"method": 'POST',
49 | "url": url + '/chaincode',
50 | "headers": {
51 | 'Accept': 'application/json',
52 | 'Content-Type': 'application/json'
53 | },
54 | "body": JSON.stringify({
55 | "jsonrpc": "2.0",
56 | "method": "deploy",
57 | "params": {
58 | "type": 1,
59 | "chaincodeID": {
60 | "path": "https://github.com/VitorSousaCode/chaincodes/experimental",
61 | "name": "chaincodeMain"
62 | },
63 | "ctorMsg": {
64 | "function": "init",
65 | "args": [
66 | "99"
67 | ]
68 | },
69 | "secureContext": secureContextId
70 | },
71 | "id": 1
72 | })
73 | };
74 |
75 | request.post(options).then(function (response) {
76 | //console.log("$%& " + typeof (response));
77 | console.log(`[init] success:${response}`);
78 | let id = JSON.parse(response);
79 | chaincodeId = id.result.message;
80 | return;
81 | }).catch(function (err) {
82 | if (err) {
83 | console.log(`[init] error: ${err}`);
84 | return err;
85 | }
86 | });
87 | }
88 |
89 | function init_asset(params, callback) {
90 | console.log(`init_asset() =>`);
91 | let url = "https://" + host + ":" + port
92 | var options = {
93 | "method": 'POST',
94 | "url": url + '/chaincode',
95 | "headers": {
96 | 'Accept': 'application/json',
97 | 'Content-Type': 'application/json'
98 | },
99 | "body": JSON.stringify({
100 | "jsonrpc": "2.0",
101 | "method": "invoke",
102 | "params": {
103 | "type": 1,
104 | "chaincodeID": {
105 | "name": chaincodeId
106 | },
107 | "ctorMsg": {
108 | "function": "init_asset",
109 | "args": params
110 |
111 | },
112 | "secureContext": secureContextId
113 | },
114 | "id": 1
115 | })
116 | };
117 |
118 | request(options).then(function (response) {
119 | console.log(`[init_asset] success: ${response}`);
120 | return callback(null, response);
121 | }).catch(function (err) {
122 | console.log(`[init_asset] error: ${err}`);
123 | return callback(err);
124 | });
125 | }
126 |
127 | function set_user(params, callback) {
128 | console.log(`set_user() =>`);
129 | let url = "https://" + host + ":" + port
130 | var options = {
131 | "method": 'POST',
132 | "url": url + '/chaincode',
133 | "headers": {
134 | 'Accept': 'application/json',
135 | 'Content-Type': 'application/json'
136 | },
137 | "body": JSON.stringify({
138 | "jsonrpc": "2.0",
139 | "method": "invoke",
140 | "params": {
141 | "type": 1,
142 | "chaincodeID": {
143 | //"path": chaincodeId,
144 | "name": chaincodeId
145 | },
146 | "ctorMsg": {
147 | "function": "set_user",
148 | "args": params
149 |
150 | },
151 | "secureContext": secureContextId
152 | },
153 | "id": 1
154 | })
155 | };
156 |
157 | request(options).then(function (response) {
158 | console.log(`[set_user] success: ${response}`);
159 | return callback(null, response);
160 | }).catch(function (err) {
161 | console.log(`[set_user] error: ${err}`);
162 | return callback(err);
163 | });
164 | }
165 |
166 | function read(params, callback) {
167 | console.log(`[api] read() => ${params}`);
168 | //params = ["Asset Package 18"];
169 | let url = "https://" + host + ":" + port
170 | var options = {
171 | "method": 'POST',
172 | "url": url + '/chaincode',
173 | "headers": {
174 | 'Accept': 'application/json',
175 | 'Content-Type': 'application/json'
176 | },
177 | "body": JSON.stringify({
178 | "jsonrpc": "2.0",
179 | "method": "query",
180 | "params": {
181 | "type": 1,
182 | "chaincodeID": {
183 | "name": chaincodeId
184 | },
185 | "ctorMsg": {
186 | "function": "read",
187 | "args": params
188 |
189 | },
190 | "secureContext": secureContextId
191 | },
192 | "id": 1
193 | })
194 | };
195 |
196 | request(options).then(function (response) {
197 | console.log(`[read] success: ${response}`);
198 | return callback(null, response);
199 | }).catch(function (err) {
200 | console.log(`[read] error: ${err}`);
201 | return callback(err);
202 | });
203 | }
204 |
205 | var restModule = {
206 |
207 | invoke: {
208 | init: init,
209 | init_asset: init_asset,
210 | set_user: set_user,
211 | registrar: registrar
212 | },
213 | query: {
214 | read: read
215 | }
216 | }
217 |
218 | return restModule;
219 |
220 | }
--------------------------------------------------------------------------------
/rest/blockchain.js:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | /* Copyright 2016 IBM Corp. All Rights Reserved.
3 | * rest implementation for Blockchain-Go demo
4 | * first implementation by Vitor Diego
5 | */
6 | //------------------------------------------------------------------------------
7 |
8 | 'use strict'
9 |
10 | //const Promise = require('bluebird');
11 | let chaincode;
12 | let response = '';
13 |
14 | module.exports.action = function (params, callback) {
15 | chaincode = require('../config/setup').chain();
16 | return chainInteraction(params, callback);
17 | }
18 |
19 | function chainInteraction(request, callback) {
20 |
21 | console.log(`[blockchain] request: ${request.action}`);
22 | console.log(typeof request);
23 | var timeout = 4000;
24 |
25 | //return new Promise(function)
26 | if (request.action === 'create') {
27 | request.id = makeid();
28 | //invoke.init_asset
29 | chaincode.invoke.init_asset(
30 | [request.description,
31 | request.lastTransaction,
32 | request.user,
33 | request.temperature,
34 | request.id], function (err, res) {
35 | if (!err) {
36 | setTimeout(function () {
37 | console.log(`[blockchain] init_asset() => ${request.description}`);
38 | return reading(request.description, callback);
39 | }, timeout);
40 | }
41 | });
42 | } else if (request.action === 'transfer') {
43 | //invoke.set_user
44 | chaincode.invoke.set_user(
45 | [request.description,
46 | request.user,
47 | request.temperature], function (err, res) {
48 | if (!err) {
49 | setTimeout(function () {
50 | console.log(`[set_user] set_user() => ${request.description}`);
51 | return reading(request.description, callback);
52 | }, timeout);
53 | }
54 | });
55 | } else if (request.action === 'read') {
56 | return reading(request.description, callback);
57 | } else {
58 | response = 'function not listed';
59 | return response;
60 | }
61 | }
62 |
63 | let reading = function query(description, callback) {
64 | chaincode.query.read([description], function (err, res) {
65 | if (!err) response = JSON.parse(res);
66 | //("merchant_id" in thisSession)==false
67 | if (response === undefined) {
68 | console.log(`invoking recursive resource`);
69 | query(description, callback);
70 | return;
71 | }
72 | //console.log(vars`Variables: ${{foo, bar, baz}}`);
73 | delete response.id;
74 | console.log(`[blockchain] read() => ${response.result.message}`);
75 | callback.send(JSON.parse(response.result.message));
76 | });
77 | }
78 |
79 | /*function makeid()
80 | *@returns {String} text - random numeric string -id's for assets(temporary way - replace for permanent id's into chaincode)
81 | */
82 | function makeid() {
83 | var text = "";
84 | var possible = "0123456789";
85 | for (var i = 0; i < 10; i++) {
86 | text += + possible.charAt(Math.floor(Math.random() * possible.length));
87 | }
88 | return text;
89 | }
--------------------------------------------------------------------------------
/rest/listener.js:
--------------------------------------------------------------------------------
1 | /**************************************
2 | * Copyright 2016 IBM Corp. All Rights Reserved.
3 | * This module listen to blockchain events.
4 | * First implementation by Vitor Diego
5 | *
6 | * ************************************/
7 |
8 | 'use strict'
9 |
10 | const request = require('request-promise');
11 | var blockdata = {}, chaincode = {};
12 |
13 | module.exports = function() {
14 |
15 | /**********************************************
16 | * returns:{
17 | "height": 0,
18 | "currentBlockHash": "string",
19 | "previousBlockHash": "string"
20 | }
21 | ***********************************************/
22 | function getChain(host, port, callback) {
23 | // console.log("[blackbird] /chain: ");
24 | let url = "https://" + host + ":" + port
25 | var options = {
26 | "method": 'GET',
27 | "url": url + '/chain',
28 | "headers": {
29 | 'Accept': 'application/json',
30 | 'Content-Type': 'application/json'
31 | }
32 | };
33 |
34 | request(options).then(function(response) {
35 | console.log(`[success] getChain() `);
36 | return callback(JSON.parse(response));
37 | }).catch(function(err) {
38 | if (err) {
39 | console.log("[err] error getChain()");
40 | return err;
41 | }
42 | });
43 | }
44 |
45 |
46 | /**********************************************
47 | * returns:{
48 | "proposerID": "string",
49 | "timestamp": {
50 | "seconds": 0,
51 | "nanos": 0
52 | },
53 | "transactions": [
54 | {
55 | "type": 0,
56 | "chaincodeID": "string",
57 | "payload": "string",
58 | "uuid": "string",
59 | "timestamp": {
60 | "seconds": 0,
61 | "nanos": 0
62 | },
63 | "confidentialityLevel": "PUBLIC",
64 | "nonce": "string",
65 | "cert": "string",
66 | "signature": "string"
67 | }
68 | ],
69 | "stateHash": "string",
70 | "previousBlockHash": "string",
71 | "consensusMetadata": "string",
72 | "nonHashData": "string"
73 | }
74 | ***********************************************/
75 | function getChainblocks(host, port, last, callback) {
76 | //console.log("[blackbird] /chain/blocks: " + last);
77 | let url = "https://" + host + ":" + port
78 | var options = {
79 | "method": 'GET',
80 | "url": url + '/chain/blocks/' + last,
81 | "headers": {
82 | 'Accept': 'application/json',
83 | 'Content-Type': 'application/json'
84 | }
85 | };
86 |
87 | request(options).then(function(response, err) {
88 | console.log(`[success] getChainblocks()`);
89 | return callback(null, JSON.parse(response));
90 | }).catch(function(err) {
91 | console.log("[err] error getChainblocks() " + err);
92 | return err;
93 |
94 | });
95 | }
96 |
97 |
98 | /**********************************************
99 | * returns:{
100 | "type": 0,
101 | "chaincodeID": "string",
102 | "payload": "string",
103 | "uuid": "string",
104 | "timestamp": {
105 | "seconds": 0,
106 | "nanos": 0
107 | },
108 | "confidentialityLevel": "PUBLIC",
109 | "nonce": "string",
110 | "cert": "string",
111 | "signature": "string"
112 | }
113 | ***********************************************/
114 | function getTransaction(host, port, uuid, callback) {
115 | //console.log("[blackbird] /transactions: ");
116 | let url = "https://" + host + ":" + port
117 | var options = {
118 | "method": 'GET',
119 | "url": url + '/transactions/' + uuid,
120 | "headers": {
121 | 'Accept': 'application/json',
122 | 'Content-Type': 'application/json'
123 | }
124 | };
125 |
126 | request(options).then(function(response) {
127 | console.log(`[success] getTransaction()`);
128 | return callback(null, JSON.parse(response));
129 | }).catch(function(err) {
130 | console.log("[err] error getTransaction() " + err);
131 | return err;
132 | });
133 | }
134 |
135 | /**************************
136 | * Calls each function sync
137 | * My version for monitor_blockheight -ibc
138 | **************************/
139 | function getListener(host, port) {
140 | let deployed = false
141 | /*Fetching blockchain data*/
142 | setInterval(function() {
143 | getChain(host, port, function(chain) {
144 | console.log("[listener] getChain() => height: " + chain.height);
145 | blockdata.currentBlockHash = chain.currentBlockHash;
146 | blockdata.height = chain.height;
147 | getChainblocks(host, port, blockdata.height - 1, function(err, stats) {
148 | if (stats.transactions) {
149 | blockdata.uuid = stats.transactions[0].txid;
150 | blockdata.consensusMetadata = stats.consensusMetadata;
151 | console.log("[listener] getChainblocks() => UUID: " + stats.transactions[0].txid);
152 | getTransaction(host, port, blockdata.uuid, function(err, data) {
153 | console.log("[listener] getTransaction() " + chain.height);
154 | if (!deployed) {
155 | data.uuid = blockdata.uuid;
156 | data.created = data.timestamp.seconds;
157 | console.log(` *___* deployment block: ${data}`);
158 | getDeploymentBlock(chain, stats, data);
159 | deployed = true;
160 | } else if (!err) {
161 | blockdata.type = data.type;
162 | blockdata.created = data.timestamp.seconds;
163 | } else {
164 | console.log(`[listener] error getTransaction() ${err}`);
165 | }
166 | });
167 | }
168 | });
169 | });
170 |
171 | }, 5000);
172 |
173 | /***************************************
174 | * @returns Object{} - deployment block
175 | * Holding deployment info
176 | **************************************/
177 | function getDeploymentBlock(chain, stats, data) {
178 | chaincode.currentBlockHash = chain.currentBlockHash;
179 | chaincode.height = chain.height;
180 | chaincode.uuid = data.uuid;
181 | chaincode.consensusMetadata = data.consensusMetadata;
182 | chaincode.type = data.type;
183 | chaincode.created = data.created;
184 | console.log("[getDeploymentBlock] " + JSON.stringify(chaincode));
185 | }
186 |
187 | }
188 |
189 | let rest = {
190 | getChain,
191 | getChainblocks,
192 | getTransaction,
193 | getListener
194 | }
195 | return rest;
196 | }
197 |
198 | module.exports.deployed = function() {
199 | return chaincode;
200 | }
201 |
202 | module.exports.blockdata = function() {
203 | return blockdata;
204 | }
205 |
--------------------------------------------------------------------------------
/routes/events.js:
--------------------------------------------------------------------------------
1 | /**
2 | *Routes to listenner events
3 | */
4 |
5 | const express = require('express');
6 | const events = require('../rest/listenner');
7 |
8 | module.exports = function () {
9 | console.log(`/events middleware running...`);
10 | var app = express.Router();
11 |
12 | app.get('/', function (req, res, next) {
13 | console.log(`/events middleware ${req.params.id}`);
14 | var response;
15 | if (req.params.id === 1) {
16 | response = events.chaincode;
17 | } else if (req.params.id === 2) {
18 | response = events.blockdata;
19 | } else {
20 | console.log(`invalid parameter!`);
21 | return;
22 | }
23 | res.send(response);
24 | next()
25 | });
26 |
27 | return app;
28 | }
29 |
--------------------------------------------------------------------------------