├── .gitignore ├── README.md ├── javascript ├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── app.js ├── enrollAdmin.js ├── files │ └── index.html ├── invoke.js ├── package-lock.json ├── package.json ├── query.js ├── registerUser.js └── run.sh ├── kill.sh └── startFabric.sh /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules/ 2 | /package-lock.json 3 | /hfc-key-store/ 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Z-Voting-API 2 | 3 | This is the NodeJS powered REST API that acts as the intermediarry between the HyperLedger Fabric network and the client. 4 | 5 | --- 6 | ## Requirements 7 | 8 | For development, you will only need Node.js and a node global package, Yarn, installed in your environement. 9 | 10 | ### Node 11 | - #### Node installation on Windows 12 | 13 | Just go on [official Node.js website](https://nodejs.org/) and download the installer. 14 | Also, be sure to have `git` available in your PATH, `npm` might need it (You can find git [here](https://git-scm.com/)). 15 | 16 | - #### Node installation on Ubuntu 17 | 18 | You can install nodejs and npm easily with apt install, just run the following commands. 19 | 20 | $ sudo apt install nodejs 21 | $ sudo apt install npm 22 | 23 | - #### Other Operating Systems 24 | You can find more information about the installation on the [official Node.js website](https://nodejs.org/) and the [official NPM website](https://npmjs.org/). 25 | 26 | If the installation was successful, you should be able to run the following command. 27 | 28 | $ node --version 29 | v8.11.3 30 | 31 | $ npm --version 32 | 6.1.0 33 | 34 | If you need to update `npm`, you can make it using `npm`! Cool right? After running the following command, just open again the command line and be happy. 35 | 36 | $ npm install npm -g 37 | 38 | --- 39 | 40 | ## Install 41 | 42 | $ git clone https://github.com/Z-Voting/Z-Voting-API 43 | $ cd Z-Voting-API/javascript 44 | $ npm install 45 | 46 | ## Running the project 47 | 48 | $ bash ./run.sh 49 | -------------------------------------------------------------------------------- /javascript/.editorconfig: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-License-Identifier: Apache-2.0 3 | # 4 | 5 | root = true 6 | 7 | [*] 8 | indent_style = space 9 | indent_size = 4 10 | end_of_line = lf 11 | charset = utf-8 12 | trim_trailing_whitespace = true 13 | insert_final_newline = true 14 | 15 | [*.md] 16 | trim_trailing_whitespace = false 17 | -------------------------------------------------------------------------------- /javascript/.eslintignore: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-License-Identifier: Apache-2.0 3 | # 4 | 5 | coverage 6 | -------------------------------------------------------------------------------- /javascript/.eslintrc.js: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | */ 4 | 5 | module.exports = { 6 | env: { 7 | node: true, 8 | mocha: true 9 | }, 10 | parserOptions: { 11 | ecmaVersion: 8, 12 | sourceType: 'script' 13 | }, 14 | extends: "eslint:recommended", 15 | rules: { 16 | indent: ['error', 4], 17 | 'linebreak-style': ['error', 'unix'], 18 | quotes: ['error', 'single'], 19 | semi: ['error', 'always'], 20 | 'no-unused-vars': ['error', { args: 'none' }], 21 | 'no-console': 'off', 22 | curly: 'error', 23 | eqeqeq: 'error', 24 | 'no-throw-literal': 'error', 25 | strict: 'error', 26 | 'no-var': 'error', 27 | 'dot-notation': 'error', 28 | 'no-tabs': 'error', 29 | 'no-trailing-spaces': 'error', 30 | 'no-use-before-define': 'error', 31 | 'no-useless-call': 'error', 32 | 'no-with': 'error', 33 | 'operator-linebreak': 'error', 34 | yoda: 'error', 35 | 'quote-props': ['error', 'as-needed'] 36 | } 37 | }; 38 | -------------------------------------------------------------------------------- /javascript/.gitignore: -------------------------------------------------------------------------------- 1 | # 2 | # SPDX-License-Identifier: Apache-2.0 3 | # 4 | 5 | # Logs 6 | logs 7 | *.log 8 | npm-debug.log* 9 | yarn-debug.log* 10 | yarn-error.log* 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | 24 | # nyc test coverage 25 | .nyc_output 26 | 27 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 28 | .grunt 29 | 30 | # Bower dependency directory (https://bower.io/) 31 | bower_components 32 | 33 | # node-waf configuration 34 | .lock-wscript 35 | 36 | # Compiled binary addons (https://nodejs.org/api/addons.html) 37 | build/Release 38 | 39 | # Dependency directories 40 | node_modules/ 41 | jspm_packages/ 42 | 43 | # TypeScript v1 declaration files 44 | typings/ 45 | 46 | # Optional npm cache directory 47 | .npm 48 | 49 | # Optional eslint cache 50 | .eslintcache 51 | 52 | # Optional REPL history 53 | .node_repl_history 54 | 55 | # Output of 'npm pack' 56 | *.tgz 57 | 58 | # Yarn Integrity file 59 | .yarn-integrity 60 | 61 | # dotenv environment variables file 62 | .env 63 | 64 | # parcel-bundler cache (https://parceljs.org/) 65 | .cache 66 | 67 | # next.js build output 68 | .next 69 | 70 | # nuxt.js build output 71 | .nuxt 72 | 73 | # vuepress build output 74 | .vuepress/dist 75 | 76 | # Serverless directories 77 | .serverless 78 | 79 | wallet 80 | !wallet/.gitkeep 81 | -------------------------------------------------------------------------------- /javascript/app.js: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | */ 4 | 5 | 'use strict'; 6 | 'use esversion: 6'; 7 | 8 | const { FileSystemWallet, Gateway } = require('fabric-network'); 9 | const path = require('path'); 10 | 11 | const ccpPath = path.resolve(__dirname, '..', '..', 'first-network', 'connection-org1.json'); 12 | 13 | function makeid(length) { 14 | let result = ''; 15 | let characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; 16 | let charactersLength = characters.length; 17 | for (let i = 0; i < length; i++) { 18 | result += characters.charAt(Math.floor(Math.random() * charactersLength)); 19 | } 20 | return result; 21 | } 22 | 23 | function concat() { 24 | let ret = ''; 25 | for (let i = 0; i < arguments.length; i++) { 26 | ret += ' ' + arguments[i]; 27 | } 28 | return ret; 29 | } 30 | 31 | async function main() { 32 | try { 33 | 34 | // Create a new file system based wallet for managing identities. 35 | const walletPath = path.join(process.cwd(), 'wallet'); 36 | const wallet = new FileSystemWallet(walletPath); 37 | console.log(`Wallet path: ${walletPath}`); 38 | 39 | // Check to see if we've already enrolled the user. 40 | const userExists = await wallet.exists('user1'); 41 | if (!userExists) { 42 | console.log('An identity for the user "user1" does not exist in the wallet'); 43 | console.log('Run the registerUserHandler.js application before retrying'); 44 | return; 45 | } 46 | 47 | // Create a new gateway for connecting to our peer node. 48 | const gateway = new Gateway(); 49 | await gateway.connect(ccpPath, { wallet, identity: 'user1', discovery: { enabled: true, asLocalhost: true } }); 50 | 51 | // Get the network (channel) our contract is deployed to. 52 | const network = await gateway.getNetwork('mychannel'); 53 | 54 | // Get the contract from the network. 55 | const contract = network.getContract('fabcar'); 56 | 57 | ////////////////////////////////////////////////// 58 | //////////////////////////////////// putting a boundary to keep new code seperate from old code 59 | let express = require('express'); 60 | let app = express(); 61 | let bodyParser = require('body-parser'); 62 | const PORT = process.env.PORT || 3000; 63 | 64 | // Create application/x-www-form-urlencoded parser 65 | 66 | // parse application/x-www-form-urlencoded 67 | app.use(bodyParser.urlencoded({ extended: false })); 68 | 69 | // parse application/json 70 | app.use(bodyParser.json()); 71 | 72 | 73 | app.use(express.static('files')); //we'll put the files in the "files" folder 74 | 75 | app.get('/getRandom', async (req, res) => { 76 | let randomData = {}; 77 | let seed = Date.now().toString(); 78 | let result = await contract.evaluateTransaction('getRandom', seed); 79 | result = JSON.parse(result); 80 | randomData.data = result; 81 | res.setHeader('content-type', 'text/json'); 82 | res.send(randomData); 83 | }); 84 | 85 | app.post('/getRandom', async (req, res) => { 86 | let seed = req.body.seed.toString(); 87 | let result = await contract.evaluateTransaction('getRandom', seed); 88 | // result = JSON.parse(result); 89 | res.setHeader('content-type', 'text/json'); 90 | res.send(result); 91 | }); 92 | 93 | app.get('/generateUID', async (req, res) => { 94 | let result = await contract.evaluateTransaction('generateUID'); 95 | // result = JSON.parse(result); 96 | res.setHeader('content-type', 'text/json'); 97 | res.send(result); 98 | }); 99 | 100 | app.post('/generateUID', async (req, res) => { 101 | let result = await contract.evaluateTransaction('generateUID'); 102 | // result = JSON.parse(result); 103 | res.setHeader('content-type', 'text/json'); 104 | res.send(result); 105 | }); 106 | 107 | app.post('/createElection', async (req, res) => { 108 | let electionName = req.body.electionName.toString(); 109 | let electionDuration = req.body.electionDuration.toString(); 110 | 111 | // console.log(electionName, electionDuration); 112 | // res.setHeader('content-type', 'text/json'); 113 | 114 | let promise = contract.submitTransaction('createElection', electionName, electionDuration); 115 | promise.then((data) => { 116 | console.log(data); 117 | 118 | let msg = { 119 | status: 'success', 120 | message: 'Election Created' 121 | }; 122 | 123 | res.setHeader('content-type', 'text/json'); 124 | res.send(msg); 125 | }).catch((err) => { 126 | console.log(err); 127 | 128 | let msg = { 129 | status: 'failure', 130 | message: err.toString() 131 | }; 132 | 133 | res.setHeader('content-type', 'text/json'); 134 | res.send(msg); 135 | }); 136 | 137 | 138 | }); 139 | 140 | let getElectionsHandler = async (req, res) => { 141 | try { 142 | let result = await contract.evaluateTransaction('getElections'); 143 | // result = JSON.parse(result); 144 | res.setHeader('content-type', 'text/json'); 145 | res.send(result.toString()); 146 | } catch (e) { 147 | res.send(e); 148 | } 149 | }; 150 | app.get('/getElections', getElectionsHandler); 151 | app.post('/getElections', getElectionsHandler); 152 | 153 | let addCandidateHandler = async (req, res) => { 154 | let name = req.body.name.toString(), 155 | sign = req.body.sign.toString(), 156 | imgAddress = req.body.imgAddress.toString(), 157 | electionId = req.body.electionId.toString(); 158 | 159 | let debug = false; 160 | if (debug) { 161 | res.setHeader('content-type', 'text/json'); 162 | res.send(JSON.stringify({ name, sign, imgAddress, electionId })); 163 | return; 164 | } else { 165 | contract.submitTransaction('addCandidate', name, sign, imgAddress, electionId).then((data) => { 166 | console.log(data); 167 | let msg = { 168 | status: 'success', 169 | message: 'Candidate Added' 170 | }; 171 | res.setHeader('content-type', 'text/json'); 172 | res.send(msg); 173 | }).catch((err) => { 174 | console.log(err); 175 | let msg = { 176 | status: 'failure', 177 | message: err.toString() 178 | }; 179 | res.setHeader('content-type', 'text/json'); 180 | res.send(msg); 181 | }); 182 | } 183 | }; 184 | app.post('/addCandidate', addCandidateHandler); 185 | 186 | let getCandidatesHandler = async (req, res) => { 187 | let electionId = req.body.electionId.toString(); 188 | 189 | let debug = false; 190 | if (debug) { 191 | res.setHeader('content-type', 'text/json'); 192 | res.send(electionId); 193 | return; 194 | } else { 195 | contract.evaluateTransaction('getCandidates', electionId).then((data) => { 196 | console.log(data.toString()); 197 | res.setHeader('content-type', 'text/json'); 198 | res.send(data.toString()); 199 | }).catch((err) => { 200 | console.log(err); 201 | let msg = { 202 | status: 'failure', 203 | message: err.toString() 204 | }; 205 | res.setHeader('content-type', 'text/json'); 206 | res.send(msg); 207 | }); 208 | } 209 | }; 210 | app.post('/getCandidates', getCandidatesHandler); 211 | 212 | 213 | let registerUserHandler = async (req, res) => { 214 | let name = req.body.name.toString(), 215 | email = req.body.email.toString(), 216 | v1 = req.body.v1.toString(), 217 | v2 = req.body.v2.toString(), 218 | v3 = req.body.v3.toString(), 219 | electionId = req.body.electionId.toString(); 220 | 221 | 222 | let debug = false; 223 | if (debug) { 224 | res.setHeader('content-type', 'text/json'); 225 | res.send(JSON.stringify({ name, email, v1, v2, v3, electionId })); 226 | return; 227 | } else { 228 | contract.submitTransaction('registerVoter', name, email, v1, v2, v3, electionId).then((data) => { 229 | console.log(data); 230 | let msg = { 231 | status: 'success', 232 | data: data.toString(), 233 | message: 'Voter Added' 234 | }; 235 | res.setHeader('content-type', 'text/json'); 236 | res.send(msg); 237 | }).catch((err) => { 238 | console.log(err); 239 | let msg = { 240 | status: 'failure', 241 | message: err.toString() 242 | }; 243 | res.setHeader('content-type', 'text/json'); 244 | res.send(msg); 245 | }); 246 | } 247 | }; 248 | app.post('/registerVoter', registerUserHandler); 249 | 250 | let getLoginChallengeHandler = async (req, res) => { 251 | let result = await contract.evaluateTransaction('getLoginChallenge'); 252 | // result = JSON.parse(result); 253 | res.setHeader('content-type', 'text/json'); 254 | res.send(result); 255 | }; 256 | app.get('/getLoginChallenge', getLoginChallengeHandler); 257 | app.post('/getLoginChallenge', getLoginChallengeHandler); 258 | 259 | 260 | let voterLoginHandler = async (req, res) => { 261 | let email = req.body.email.toString(), 262 | x = req.body.x.toString(), 263 | a1 = req.body.a1.toString(), 264 | a2 = req.body.a2.toString(), 265 | a3 = req.body.a3.toString(), 266 | v1 = req.body.v1.toString(), 267 | v2 = req.body.v2.toString(), 268 | v3 = req.body.v3.toString(), 269 | y1 = req.body.y1.toString(), 270 | electionID = req.body.electionID.toString(); 271 | 272 | let debug = false; 273 | if (debug) { 274 | res.setHeader('content-type', 'text/json'); 275 | res.send(JSON.stringify({ email, x, a1, a2, a3, v1, v2, v3, y1, electionID })); 276 | return; 277 | } else { 278 | try { 279 | contract.evaluateTransaction('voterLogin', email, x, a1, a2, a3, v1, v2, v3, y1, electionID).then((data) => { 280 | console.log(data); 281 | let msg = { 282 | status: 'success', 283 | data: JSON.parse(data), 284 | message: '' 285 | }; 286 | res.setHeader('content-type', 'text/json'); 287 | res.send(msg); 288 | }).catch((err) => { 289 | console.log(err); 290 | let msg = { 291 | status: 'failure', 292 | message: err.toString() 293 | }; 294 | res.setHeader('content-type', 'text/json'); 295 | res.send(msg); 296 | }); 297 | } catch (e) { 298 | res.send(e); 299 | } 300 | contract.evaluateTransaction('voterLogin', email, x, a1, a2, a3, v1, v2, v3, y1, electionID).then((data) => { 301 | console.log(data); 302 | let msg = { 303 | status: 'success', 304 | data: JSON.parse(data), 305 | message: '' 306 | }; 307 | res.setHeader('content-type', 'text/json'); 308 | res.send(msg); 309 | }).catch((err) => { 310 | console.log(err); 311 | let msg = { 312 | status: 'failure', 313 | message: err.toString() 314 | }; 315 | res.setHeader('content-type', 'text/json'); 316 | res.send(msg); 317 | }); 318 | } 319 | }; 320 | app.post('/voterLogin', voterLoginHandler); 321 | 322 | let castVoteHandler = async (req, res) => { 323 | let id = req.body.id.toString(), 324 | voteContent = req.body.voteContent.toString(); 325 | 326 | let debug = false; 327 | if (debug) { 328 | res.setHeader('content-type', 'text/json'); 329 | res.send(JSON.stringify({ id, voteContent })); 330 | } else { 331 | try { 332 | let data = await contract.evaluateTransaction('castVote', id, voteContent); 333 | if (data === null) { 334 | throw new Error(400); 335 | } 336 | 337 | contract.submitTransaction('castVote', id, voteContent).then((data) => { 338 | console.log(data); 339 | let msg = { 340 | status: 'success', 341 | data: JSON.parse(data), 342 | message: 'Vote Cast Successful' 343 | }; 344 | res.setHeader('content-type', 'text/json'); 345 | res.send(msg); 346 | }).catch((err) => { 347 | console.log(err); 348 | let msg = { 349 | status: 'failure', 350 | message: err.toString() 351 | }; 352 | res.setHeader('content-type', 'text/json'); 353 | res.send(msg); 354 | }); 355 | 356 | } catch (e) { 357 | console.log(e); 358 | } 359 | } 360 | }; 361 | app.post('/castVote', castVoteHandler); 362 | 363 | 364 | let calculateResultHandler = async (req, res) => { 365 | let electionId = req.body.electionId.toString(); 366 | 367 | let debug = false; 368 | if (debug) { 369 | res.setHeader('content-type', 'text/json'); 370 | res.send(concat(electionId)); 371 | return; 372 | } else { 373 | res.setHeader('content-type', 'text/json'); 374 | 375 | contract.evaluateTransaction('calculateResult', electionId).then((data) => { 376 | let ret = JSON.parse(data.toString()); 377 | 378 | contract.evaluateTransaction('getCandidates', electionId).then((data) => { 379 | ret.candidates = JSON.parse(data.toString()); 380 | 381 | res.send(JSON.stringify(ret)); 382 | }); 383 | }).catch((err) => { 384 | console.log(err.toString()); 385 | res.setHeader('content-type', 'text/json'); 386 | 387 | let ret = { 388 | id: 'LnfgDsc2WD8F2qNfHK5aResult', 389 | publisherID: err.toString(), 390 | values: [ 391 | 0, 392 | 0, 393 | 0, 394 | 0 395 | ], 396 | electionID: 'LnfgDsc2WD8F2qNfHK5a', 397 | doctype: 'ElectionResult' 398 | }; 399 | 400 | contract.evaluateTransaction('getCandidates', electionId).then((data) => { 401 | ret.candidates = JSON.parse(data.toString()); 402 | 403 | res.send(JSON.stringify(ret)); 404 | }); 405 | }); 406 | } 407 | }; 408 | app.post('/calculateResult', calculateResultHandler); 409 | 410 | 411 | let startElectionHandler = async (req, res) => { 412 | let electionId = req.body.electionId.toString(); 413 | 414 | let debug = false; 415 | if (debug) { 416 | res.setHeader('content-type', 'text/json'); 417 | res.send(concat(electionId)); 418 | return; 419 | } else { 420 | contract.submitTransaction('startElection', electionId).then((data) => { 421 | console.log(data); 422 | let msg = { 423 | status: 'success', 424 | data: data.toString(), 425 | message: '' 426 | }; 427 | res.setHeader('content-type', 'text/json'); 428 | res.send(msg); 429 | }).catch((err) => { 430 | console.log(err); 431 | let msg = { 432 | status: 'failure', 433 | message: err.toString() 434 | }; 435 | res.setHeader('content-type', 'text/json'); 436 | res.send(msg); 437 | }); 438 | } 439 | }; 440 | app.post('/startElection', startElectionHandler); 441 | 442 | 443 | app.get('/', function (req, res) { 444 | res.sendFile(__dirname + '/files/' + 'index.html'); 445 | }); 446 | 447 | 448 | //let's create a post request endpoint at /insertMovie 449 | app.post('/insertMovie', async function (req, res) { 450 | let name = req.body.name; 451 | let director = req.body.director; 452 | let genre = req.body.genre; 453 | let year = req.body.year; 454 | 455 | //now I have to call the chaincode 456 | //we are going to get that code from the invoke.js file 457 | 458 | let key = makeid(20); 459 | 460 | await contract.submitTransaction('createMovie', key, name, director, year, genre); 461 | res.setHeader('content-type', 'text/json'); 462 | res.send(JSON.stringify({ key, name, director, genre, year })); 463 | 464 | console.log('record added'); 465 | }); 466 | 467 | app.get('/viewAllMovies', async function (req, res) { 468 | const result = await contract.evaluateTransaction('queryAllMovies'); 469 | 470 | let resultData = result.toString(); 471 | // let movies = JSON.parse(resultData); 472 | 473 | let html = `
${resultData}`; 474 | 475 | 476 | res.setHeader('content-type', 'text/json'); 477 | res.send(html); 478 | }); 479 | 480 | app.post('/queryMoviesByYear', async function (req, res) { 481 | let year = req.body.year; 482 | 483 | //now I have to call the chaincode 484 | //we are going to get that code from the invoke.js file 485 | 486 | const result = await contract.evaluateTransaction('queryMoviesByYear', year); 487 | res.setHeader('content-type', 'text/json'); 488 | res.send(result.toString()); 489 | 490 | console.log('query complete'); 491 | }); 492 | 493 | app.post('/queryMoviesByGenre', async function (req, res) { 494 | let genre = req.body.genre; 495 | 496 | //now I have to call the chaincode 497 | //we are going to get that code from the invoke.js file 498 | 499 | const result = await contract.evaluateTransaction('queryMoviesByGenre', genre); 500 | res.setHeader('content-type', 'text/json'); 501 | res.send(result.toString()); 502 | 503 | console.log('query complete'); 504 | }); 505 | 506 | app.post('/deleteAll', async function (req, res) { 507 | await contract.submitTransaction('deleteAll'); 508 | 509 | res.setHeader('content-type', 'text/json'); 510 | res.send(JSON.stringify({ 511 | status: 'Deletion Completed' 512 | })); 513 | }); 514 | 515 | const server = app.listen(PORT, function () { 516 | let host = server.address().address; 517 | let port = server.address().port; 518 | 519 | console.log('Example app listening at http://%s:%s', host, port); 520 | }); 521 | //////////////////////////////////// 522 | ////////////////////////////////////////////////// 523 | 524 | 525 | } catch (error) { 526 | console.error(`Failed to evaluate transaction: ${error}`); 527 | process.exit(1); 528 | } 529 | } 530 | 531 | main(); 532 | -------------------------------------------------------------------------------- /javascript/enrollAdmin.js: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | */ 4 | 5 | 'use strict'; 6 | 7 | const FabricCAServices = require('fabric-ca-client'); 8 | const { FileSystemWallet, X509WalletMixin } = require('fabric-network'); 9 | const fs = require('fs'); 10 | const path = require('path'); 11 | 12 | const ccpPath = path.resolve(__dirname, '..', '..', 'first-network', 'connection-org1.json'); 13 | console.log(ccpPath); 14 | const ccpJSON = fs.readFileSync(ccpPath, 'utf8'); 15 | console.log(ccpJSON); 16 | const ccp = JSON.parse(ccpJSON); 17 | 18 | 19 | async function main() { 20 | try { 21 | 22 | // Create a new CA client for interacting with the CA. 23 | const caInfo = ccp.certificateAuthorities['ca.org1.example.com']; 24 | const caTLSCACerts = caInfo.tlsCACerts.pem; 25 | const ca = new FabricCAServices(caInfo.url, { trustedRoots: caTLSCACerts, verify: false }, caInfo.caName); 26 | 27 | // Create a new file system based wallet for managing identities. 28 | const walletPath = path.join(process.cwd(), 'wallet'); 29 | const wallet = new FileSystemWallet(walletPath); 30 | console.log(`Wallet path: ${walletPath}`); 31 | 32 | // Check to see if we've already enrolled the admin user. 33 | const adminExists = await wallet.exists('admin'); 34 | if (adminExists) { 35 | console.log('An identity for the admin user "admin" already exists in the wallet'); 36 | return; 37 | } 38 | 39 | // Enroll the admin user, and import the new identity into the wallet. 40 | const enrollment = await ca.enroll({ enrollmentID: 'admin', enrollmentSecret: 'adminpw' }); 41 | const identity = X509WalletMixin.createIdentity('Org1MSP', enrollment.certificate, enrollment.key.toBytes()); 42 | await wallet.import('admin', identity); 43 | console.log('Successfully enrolled admin user "admin" and imported it into the wallet'); 44 | 45 | } catch (error) { 46 | console.error(`Failed to enroll admin user "admin": ${error}`); 47 | process.exit(1); 48 | } 49 | } 50 | 51 | main(); 52 | -------------------------------------------------------------------------------- /javascript/files/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |