-
Notifications
You must be signed in to change notification settings - Fork 30
/
crowd_fund_demo.js
315 lines (273 loc) · 10 KB
/
crowd_fund_demo.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
// Hyperledger Fabric Client to connect to the Fabric network
var hfc = require('hfc');
// For printing formatted things
var util = require('util');
// Express to listen to browser requests
var express = require('express');
var app = express();
// Body parser for parsing the request body
var bodyParser = require('body-parser')
// Debug modules to aid with debugging
var debugModule = require('debug');
var debug = debugModule('crowd_fund');
////////////////////////////////////////////////////////////////////////////////
// The fist part of this application configures all the required settings the //
// app will need to connect to the Fabric network, such as the membership //
// service address, the peer address(es), the eventHub address for listening //
// to incoming events, etc. //
////////////////////////////////////////////////////////////////////////////////
//
// Get the Docker Host IP from command line
//
var DOCKER_HOST_IP = process.argv[2];
if (DOCKER_HOST_IP == null || DOCKER_HOST_IP == "") {
console.log("ERROR: No Docker Host IP specified! Exiting.");
process.exit(1);
} else {
console.log("Docker Host IP: " + DOCKER_HOST_IP + "\n");
}
//
// Required configuration settings
//
var SDK_KEYSTORE = "/tmp/keyValStore";
var SDK_MEMBERSRVC_ADDRESS = "grpc://" + DOCKER_HOST_IP + ":7054";
var SDK_PEER_ADDRESSES = [
"grpc://" + DOCKER_HOST_IP + ":7051",
"grpc://" + DOCKER_HOST_IP + ":8051",
"grpc://" + DOCKER_HOST_IP + ":9051",
"grpc://" + DOCKER_HOST_IP + ":10051"
];
var SDK_EVENTHUB_ADDRESS = "grpc://" + DOCKER_HOST_IP + ":7053";
//
// Create a chain object
//
var chain = hfc.newChain("testChain");
//
// Configure the chain settings
//
// Set the location of the KeyValueStore
console.log("Setting keyValStore location to: " + SDK_KEYSTORE);
chain.setKeyValStore(hfc.newFileKeyValStore(SDK_KEYSTORE));
// Set the membership services address
console.log("Setting membersrvc address to: " + SDK_MEMBERSRVC_ADDRESS);
chain.setMemberServicesUrl(SDK_MEMBERSRVC_ADDRESS);
// Set the peer address(es) depending on the network type
if (process.argv[3] == "single-peer") {
console.log("Setting peer address to: " + SDK_PEER_ADDRESSES[0]);
chain.addPeer(SDK_PEER_ADDRESSES[0]);
} else if (process.argv[3] == "four-peer") {
SDK_PEER_ADDRESSES.forEach(function(peer_address) {
console.log("Adding peer address: " + peer_address);
chain.addPeer(peer_address);
});
} else {
console.log("ERROR: Please select either a `single-peer` " +
" or a `four-peer` network!");
process.exit(1);
}
// Set the eventHub address
console.log("Setting eventHubAddr address to: " + SDK_EVENTHUB_ADDRESS + "\n");
chain.eventHubConnect(SDK_EVENTHUB_ADDRESS);
process.on('exit', function () {
console.log("Exiting and disconnecting eventHub channel.");
chain.eventHubDisconnect();
});
// Set the chaincode deployment mode to "network", i.e. chaincode runs inside
// a Docker container
chain.setDevMode(false);
//
// Declare variables that will be used across multiple operations
//
// User object returned after registration and enrollment
var app_user;
// chaincodeID will store the chaincode ID value after deployment which is
// later used to execute invocations and queries
var chaincodeID;
////////////////////////////////////////////////////////////////////////////////
// The second part of this app does the required setup to register itself //
// with the Fabric network. Specifically, it enrolls and registers the //
// required users and then deploys the chaincode to the network. The //
// chaincode will then be ready to take invoke and query requests. //
////////////////////////////////////////////////////////////////////////////////
//
// Enroll the WebAppAdmin member. WebAppAdmin member is already registered
// manually by being included inside the membersrvc.yaml file, i.e. the
// configuration file for the membership services Docker container.
//
chain.getMember("WebAppAdmin", function (err, WebAppAdmin) {
if (err) {
console.log("ERROR: Failed to get WebAppAdmin member -- " + err);
process.exit(1);
} else {
console.log("Successfully got WebAppAdmin member.");
// Enroll the WebAppAdmin member with the certificate authority using
// the one time password hard coded inside the membersrvc.yaml.
pw = "DJY27pEnl16d";
WebAppAdmin.enroll(pw, function (err, enrollment) {
if (err) {
console.log("ERROR: Failed to enroll WebAppAdmin member -- " +
err);
process.exit(1);
} else {
// Set the WebAppAdmin as the designated chain registrar
console.log("Successfully enrolled WebAppAdmin member.");
console.log("Setting WebAppAdmin as chain registrar.");
chain.setRegistrar(WebAppAdmin);
// Register a new user with WebAppAdmin as the chain registrar
console.log("Registering user `WebAppUser_1`.");
registerUser("WebApp_user1");
}
});
}
});
//
// Register and enroll a new user with the certificate authority.
// This will be performed by the member with registrar authority, WebAppAdmin.
//
function registerUser(user_name) {
// Register and enroll the user
chain.getMember(user_name, function (err, user) {
if (err) {
console.log("ERROR: Failed to get " + user.getName() + " -- ", err);
process.exit(1);
} else {
app_user = user;
// User may not be enrolled yet. Perform both registration
// and enrollment.
var registrationRequest = {
enrollmentID: app_user.getName(),
affiliation: "bank_a"
};
app_user.registerAndEnroll(registrationRequest, function (err, member) {
if (err) {
console.log("ERROR: Failed to enroll " +
app_user.getName() + " -- " + err);
process.exit(1);
} else{
console.log("Successfully registered and enrolled " +
app_user.getName() + ".\n");
// Deploy a chaincode with the new user
console.log("Deploying chaincode now...");
deployChaincode()
}
});
}
});
}
//
// Construct and issue a chaincode deployment request. Deploy the chaincode from
// a local directory in the user's $GOPATH.
//
function deployChaincode() {
// Construct the deploy request
var deployRequest = {
// Path (under $GOPATH/src) required for deploy in network mode
chaincodePath: "crowd_fund_chaincode",
// Function to trigger
fcn: "init",
// Arguments to the initializing function
args: ["account", "0"],
};
// Trigger the deploy transaction
var deployTx = app_user.deploy(deployRequest);
// Print the successfull deploy results
deployTx.on('complete', function (results) {
// Set the chaincodeID for subsequent tests
chaincodeID = results.chaincodeID;
console.log(util.format("Successfully deployed chaincode: request=%j, " +
"response=%j" + "\n", deployRequest, results));
// The chaincode is successfully deployed, start the listener port
startListener();
});
deployTx.on('error', function (err) {
// Deploy request failed
console.log(util.format("ERROR: Failed to deploy chaincode: request=%j, " +
"error=%j", deployRequest, err));
process.exit(1);
});
}
////////////////////////////////////////////////////////////////////////////////
// The third part of this app configures an HTTP server in order to listen //
// for incoming HTTP requests. These requests will then invoke or query the //
// chancode and return a response to the client. //
////////////////////////////////////////////////////////////////////////////////
// Assign any listening port for your webApp
var app_port = 3000;
// Enable CORS for ease of development and testing
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
// Use body-parer to parse the JSON formatted request payload
app.use(bodyParser.json());
//
// Add route for a chaincode query request for a specific state variable
//
app.get("/state/:var", function(req, res) {
// State variable to retrieve
var stateVar = req.params.var;
// Construct the query request
var queryRequest = {
// Name (hash) required for query
chaincodeID: chaincodeID,
// Function to trigger
fcn: "query",
// State variable to retrieve
args: [stateVar]
};
// Trigger the query transaction
var queryTx = app_user.query(queryRequest);
// Query completed successfully
queryTx.on('complete', function (results) {
console.log(util.format("Successfully queried existing chaincode state: " +
"request=%j, response=%j, value=%s", queryRequest, results, results.result.toString()));
res.status(200).json({ "value": results.result.toString() });
});
// Query failed
queryTx.on('error', function (err) {
var errorMsg = util.format("ERROR: Failed to query existing chaincode " +
"state: request=%j, error=%j", queryRequest, err);
console.log(errorMsg);
res.status(500).json({ error: errorMsg });
});
});
//
// Add route for a chaincode invoke request
//
app.post('/transactions', function(req, res) {
// Amount to transfer
var amount = req.body.amount;
// Construct the invoke request
var invokeRequest = {
// Name (hash) required for invoke
chaincodeID: chaincodeID,
// Function to trigger
fcn: "invoke",
// Parameters for the invoke function
args: ["account", amount]
};
// Trigger the invoke transaction
var invokeTx = app_user.invoke(invokeRequest);
// Invoke transaction submitted successfully
invokeTx.on('submitted', function (results) {
console.log(util.format("Successfully submitted chaincode invoke " +
"transaction: request=%j, response=%j", invokeRequest, results));
res.status(200).json({ status: "submitted" });
});
// Invoke transaction submission failed
invokeTx.on('error', function (err) {
var errorMsg = util.format("ERROR: Failed to submit chaincode invoke " +
"transaction: request=%j, error=%j", invokeRequest, err);
console.log(errorMsg);
res.status(500).json({ error: errorMsg });
});
});
//
// Start the HTTP server to listen for incoming requests
//
function startListener() {
console.log("Starting WebApp on port " + app_port);
app.listen(app_port);
console.log("WebApp is now listening on port " + app_port + "\n");
}