Add the javascript application for ledger queries

Add the asset-transfer-ledger-queries javascript application.
Update the CI script to run it against go and javascript chaincode.

Signed-off-by: Bret Harrison <beharrison@nc.rr.com>
This commit is contained in:
Bret Harrison 2020-08-07 16:58:53 -04:00 committed by denyeart
parent 8e2535ee65
commit f361386231
12 changed files with 422 additions and 68 deletions

View file

@ -9,7 +9,7 @@
const {Gateway, Wallets} = require('fabric-network');
const FabricCAServices = require('fabric-ca-client');
const path = require('path');
const {buildCAClient, registerUser, enrollAdmin} = require('../../test-application/javascript/CAUtil.js');
const {buildCAClient, registerAndEnrollUser, enrollAdmin} = require('../../test-application/javascript/CAUtil.js');
const {buildCCP, buildWallet} = require('../../test-application/javascript/AppUtil.js');
const channelName = 'mychannel';
@ -22,25 +22,46 @@ function prettyJSONString(inputString) {
}
// pre-requisites:
// - fabric-sample two organization test-network setup with two peers, ordering service, and 2 certificate authorities
// - fabric-sample two organization test-network setup with two peers, ordering service,
// and 2 certificate authorities
// ===> from directory /fabric-samples/test-network
// network.sh run createChannel -ca
// - any of the asset-transfer-basic chaincodes deployed on the channel "mychannel" with the chaincodeName of "basic"
// This deploy command will package, install, approve, and commit the javascript chaincode, all the actions it takes
// ./network.sh up createChannel -ca
// - Use any of the asset-transfer-basic chaincodes deployed on the channel "mychannel"
// with the chaincode name of "basic". The following deploy command will package,
// install, approve, and commit the javascript chaincode, all the actions it takes
// to deploy a chaincode to a channel.
// ===> from directory /fabric-samples/test-network
// network.sh deployCC -ccn basic -ccl javascript
// - node install
// ./network.sh deployCC -ccn basic -ccl javascript
// - Be sure that node.js is installed
// ===> from directory /fabric-samples/asset-transfer-basic/application-javascript
// node -v
// - npm installed code dependencies
// ===> from directory /fabric-samples/asset-transfer-basic/application-javascript
// npm install
// - to run this test application
// ===> from directory /fabric-samples/asset-transfer-basic/application-javascript
// node app.js
// # this may be run again again
// NOTE: If you see kind an error like these:
/*
2020-08-07T20:23:17.590Z - error: [DiscoveryService]: send[mychannel] - Channel:mychannel received discovery error:access denied
******** FAILED to run the application: Error: DiscoveryService: mychannel error: access denied
OR
Failed to register user : Error: fabric-ca request register failed with errors [[ { code: 20, message: 'Authentication failure' } ]]
******** FAILED to run the application: Error: Identity not found in wallet: appUser
*/
// Delete the /fabric-samples/asset-transfer-basic/application-javascript/wallet directory
// and retry this application.
//
// The certificate authority must have been restarted and the saved certificates for the
// admin and application user are not valid. Deleting the wallet store will force these to be reset
// with the new certificate authority.
//
/**
* A test application to show basic operations with any of the asset-transfer-basic chaincodes
* A test application to show basic queries operations with any of the asset-transfer-basic chaincodes
* -- How to submit a transaction
* -- How to query and check the results
*
@ -64,7 +85,7 @@ async function main() {
// in a real application this would be done only when a new user was required to be added
// and would be part of an administrative flow
await registerUser(caClient, wallet, userId, 'org1.department1');
await registerAndEnrollUser(caClient, wallet, userId, 'org1.department1');
// Create a new gateway instance for interacting with the fabric network.
// In a real application this would be done as the backend server session is setup for

View file

@ -10,7 +10,7 @@
"author": "Hyperledger",
"license": "Apache-2.0",
"dependencies": {
"fabric-ca-client": "2.2.0",
"fabric-network": "2.2.0"
"fabric-ca-client": "^2.2.0",
"fabric-network": "^2.2.0"
}
}

View file

@ -0,0 +1,5 @@
#
# SPDX-License-Identifier: Apache-2.0
#
coverage

View file

@ -0,0 +1,36 @@
/*
* SPDX-License-Identifier: Apache-2.0
*/
module.exports = {
env: {
node: true,
mocha: true
},
parserOptions: {
ecmaVersion: 8,
sourceType: 'script'
},
extends: "eslint:recommended",
rules: {
indent: ['error', 'tab'],
'linebreak-style': ['error', 'unix'],
quotes: ['error', 'single'],
semi: ['error', 'always'],
'no-unused-vars': ['error', { args: 'none' }],
'no-console': 'off',
curly: 'error',
eqeqeq: 'error',
'no-throw-literal': 'error',
strict: 'error',
'no-var': 'error',
'dot-notation': 'error',
'no-trailing-spaces': 'error',
'no-use-before-define': 'error',
'no-useless-call': 'error',
'no-with': 'error',
'operator-linebreak': 'error',
yoda: 'error',
'quote-props': ['error', 'as-needed']
}
};

View file

@ -0,0 +1,14 @@
#
# SPDX-License-Identifier: Apache-2.0
#
# Coverage directory used by tools like istanbul
coverage
# Dependency directories
node_modules/
jspm_packages/
package-lock.json
wallet
!wallet/.gitkeep

View file

@ -0,0 +1,242 @@
/*
* Copyright IBM Corp. All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
'use strict';
const {Gateway, Wallets} = require('fabric-network');
const FabricCAServices = require('fabric-ca-client');
const path = require('path');
const {buildCAClient, registerAndEnrollUser, enrollAdmin} = require('../../test-application/javascript/CAUtil.js');
const {buildCCP, buildWallet} = require('../../test-application/javascript/AppUtil.js');
const channelName = 'mychannel';
const chaincodeName = 'ledger';
const walletPath = path.join(__dirname, 'wallet');
const userId = 'appUser';
function prettyJSONString(inputString) {
return JSON.stringify(JSON.parse(inputString), null, 2);
}
// pre-requisites:
// - fabric-sample two organization test-network setup with two peers, ordering service,
// and 2 certificate authorities, with the state database using couchdb
// ===> from directory /fabric-samples/test-network
// ./network.sh up createChannel -ca -s couchdb
// - Use any of the asset-transfer-ledger-queries chaincodes deployed on the channel "mychannel"
// with the chaincode name of "ledger". The following deploy command will package,
// install, approve, and commit the javascript chaincode, all the actions it takes
// to deploy a chaincode to a channel.
// ===> from directory /fabric-samples/test-network
// ./network.sh deployCC -ccn ledger -ccl javascript
// - Be sure that node.js is installed
// ===> from directory /fabric-samples/asset-transfer-ledger-queries/application-javascript
// node -v
// - npm installed code dependencies
// ===> from directory /fabric-samples/asset-transfer-ledger-queries/application-javascript
// npm install
// - to run this test application
// ===> from directory /fabric-samples/asset-transfer-ledger-queries/application-javascript
// node app.js
// NOTE: If you see kind an error like these:
/*
2020-08-07T20:23:17.590Z - error: [DiscoveryService]: send[mychannel] - Channel:mychannel received discovery error:access denied
******** FAILED to run the application: Error: DiscoveryService: mychannel error: access denied
OR
Failed to register user : Error: fabric-ca request register failed with errors [[ { code: 20, message: 'Authentication failure' } ]]
******** FAILED to run the application: Error: Identity not found in wallet: appUser
*/
// Delete the /fabric-samples/asset-transfer-ledger-queries/application-javascript/wallet directory
// and retry this application.
//
// The certificate authority must have been restarted and the saved certificates for the
// admin and application user are not valid. Deleting the wallet store will force these to be reset
// with the new certificate authority.
//
/**
* A test application to show ledger queries operations with any of the asset-transfer-ledger-queries chaincodes
* -- How to submit a transaction
* -- How to query and check the results
*
* To see the SDK workings, try setting the logging to show on the console before running
* export HFC_LOGGING='{"debug":"console"}'
*/
async function main() {
let skipInit = false;
if (process.argv.length > 2) {
if (process.argv[2] === 'skipInit') {
skipInit = true;
}
}
try {
// build an in memory object with the network configuration (also known as a connection profile)
const ccp = buildCCP();
// build an instance of the fabric ca services client based on
// the information in the network configuration
const caClient = buildCAClient(FabricCAServices, ccp);
// setup the wallet to hold the credentials of the application user
const wallet = await buildWallet(Wallets, walletPath);
// in a real application this would be done on an administrative flow, and only once
await enrollAdmin(caClient, wallet);
// in a real application this would be done only when a new user was required to be added
// and would be part of an administrative flow
await registerAndEnrollUser(caClient, wallet, userId, 'org1.department1');
// Create a new gateway instance for interacting with the fabric network.
// In a real application this would be done as the backend server session is setup for
// a user that has been verified.
const gateway = new Gateway();
try {
// setup the gateway instance
// The user will now be able to create connections to the fabric network and be able to
// submit transactions and query. All transactions submitted by this gateway will be
// signed by this user using the credentials stored in the wallet.
await gateway.connect(ccp, {
wallet,
identity: userId,
discovery: {enabled: true, asLocalhost: true} // using asLocalhost as this gateway is using a fabric network deployed locally
});
// Build a network instance based on the channel where the smart contract is deployed
const network = await gateway.getNetwork(channelName);
// Get the contract from the network.
const contract = network.getContract(chaincodeName);
// Initialize a set of asset data on the channel using the chaincode 'InitLedger' function.
// This type of transaction would only be run once by an application the first time it was started after it
// deployed the first time. Any updates to the chaincode deployed later would likely not need to run
// an "init" type function.
if (!skipInit) {
try {
console.log('\n--> Submit Transaction: InitLedger, function creates the initial set of assets on the ledger');
await contract.submitTransaction('InitLedger');
console.log('*** Result: committed');
} catch(initError) {
// this is error is OK if we are rerunning this app without restarting
console.log(`******** initLedger failed :: ${initError}`)
}
} else {
console.log('*** not executing "InitLedger');
}
let result;
// Let's try a query operation (function).
// This will be sent to just one peer and the results will be shown.
console.log('\n--> Evaluate Transaction: GetAssetsByRange, function returns assets in a specific range from asset1 to before asset6');
result = await contract.evaluateTransaction('GetAssetsByRange', 'asset1', 'asset6');
console.log(`*** Result: ${prettyJSONString(result.toString())}`);
console.log('\n--> Evaluate Transaction: GetAssetsByRange, function use an open start and open end range to return assest1 to asset6');
result = await contract.evaluateTransaction('GetAssetsByRange', '', '');
console.log(`*** Result: ${prettyJSONString(result.toString())}`);
console.log('\n--> Evaluate Transaction: GetAssetsByRange, function use an fixed start (asset3) and open end range to return assest3 to asset6');
result = await contract.evaluateTransaction('GetAssetsByRange', 'asset3', '');
console.log(`*** Result: ${prettyJSONString(result.toString())}`);
console.log('\n--> Evaluate Transaction: GetAssetsByRange, function use an open start and fixed end (asset3) range to return assest1 to asset2');
result = await contract.evaluateTransaction('GetAssetsByRange', '', 'asset3');
console.log(`*** Result: ${prettyJSONString(result.toString())}`);
// Now let's try to submit a transaction.
// This will be sent to both peers and if both peers endorse the transaction, the endorsed proposal will be sent
// to the orderer to be committed by each of the peer's to the channel ledger.
console.log('\n--> Submit Transaction: CreateAsset, creates new asset with ID(asset7), color(yellow), size(5), owner(Tom), and appraisedValue(1300) arguments');
await contract.submitTransaction('CreateAsset', 'asset7', 'yellow', '5', 'Tom', '1300');
console.log('*** Result: committed');
console.log('\n--> Evaluate Transaction: ReadAsset, function returns information about an asset with ID(asset7)');
result = await contract.evaluateTransaction('ReadAsset', 'asset7');
console.log(`*** Result: ${prettyJSONString(result.toString())}`);
console.log('\n--> Evaluate Transaction: AssetExists, function returns "true" if an asset with ID(asset7) exist');
result = await contract.evaluateTransaction('AssetExists', 'asset7');
console.log(`*** Result: ${prettyJSONString(result.toString())}`);
// Now let's try to submit a transaction that deletes an asset
// This will be sent to both peers and if both peers endorse the transaction, the endorsed proposal will be sent
// to the orderer to be committed by each of the peer's to the channel ledger.
console.log('\n--> Submit Transaction: DeleteAsset with ID(asset7)');
await contract.submitTransaction('DeleteAsset', 'asset7');
console.log('*** Result: committed');
console.log('\n--> Evaluate Transaction: AssetExists, function returns "false" if an asset with ID(asset7) does not exist');
result = await contract.evaluateTransaction('AssetExists', 'asset7');
console.log(`*** Result: ${prettyJSONString(result.toString())}`)
console.log('\n--> Submit Transaction: TransferAsset, transfer asset(asset2) to new owner(Tom)');
await contract.submitTransaction('TransferAsset', 'asset2', 'Tom');
console.log('*** Result: committed');
console.log('\n--> Evaluate Transaction: ReadAsset, function returns information about an asset with ID(asset2)');
result = await contract.evaluateTransaction('ReadAsset', 'asset2');
console.log(`*** Result: ${prettyJSONString(result.toString())}`);
// Rich Query with Pagination (Only supported if CouchDB is used as state database)
console.log('\n--> Evaluate Transaction: QueryAssetsWithPagination, function returns "Tom" assets');
result = await contract.evaluateTransaction('QueryAssetsWithPagination', '{"selector":{"docType":"asset","owner":"Tom"}, "use_index":["_design/indexOwnerDoc", "indexOwner"]}','3','');
console.log(`*** Result: ${prettyJSONString(result.toString())}`);
console.log('\n--> Submit Transaction: TransferAssetByColor, transfer all yellow assets to new owner(Michel)');
await contract.submitTransaction('TransferAssetByColor', 'yellow', 'Michel');
console.log('*** Result: committed');
// Rich Query (Only supported if CouchDB is used as state database):
console.log('\n--> Evaluate Transaction: QueryAssetsByOwner, find all assets with owner(Michel)');
result = await contract.evaluateTransaction('QueryAssetsByOwner', 'Michel');
console.log(`*** Result: ${prettyJSONString(result.toString())}`);
console.log('\n--> Evaluate Transaction: GetAssetHistory, get the history of an asset(asset7)');
result = await contract.evaluateTransaction('GetAssetHistory', 'asset7');
console.log(`*** Result: ${prettyJSONString(result.toString())}`);
// Rich Query (Only supported if CouchDB is used as state database):
console.log('\n--> Evaluate Transaction: QueryAssets, assets of size 15');
result = await contract.evaluateTransaction('QueryAssets', '{"selector":{"size":15}}');
console.log(`*** Result: ${prettyJSONString(result.toString())}`);
// Rich Query with index design doc and index name specified (Only supported if CouchDB is used as state database):
console.log('\n--> Evaluate Transaction: QueryAssets, Jin Soo\'s assets');
result = await contract.evaluateTransaction('QueryAssets', '{"selector":{"docType":"asset","owner":"Jin Soo"}, "use_index":["_design/indexOwnerDoc", "indexOwner"]}');
console.log(`*** Result: ${prettyJSONString(result.toString())}`);
// Rich Query with Pagination (Only supported if CouchDB is used as state database)
console.log('\n--> Evaluate Transaction: GetAssetsByRangeWithPagination - get page 1 of assets from asset3 to asset6 (asset3, asset4)');
result = await contract.evaluateTransaction('GetAssetsByRangeWithPagination', 'asset3', 'asset6', '2', '');
console.log(`*** Result: ${prettyJSONString(result.toString())}`);
// Rich Query with Pagination (Only supported if CouchDB is used as state database)
console.log('\n--> Evaluate Transaction: GetAssetsByRangeWithPagination - get page 2 of assets from asset3 to asset6 (asset4, asset5)');
result = await contract.evaluateTransaction('GetAssetsByRangeWithPagination', 'asset3', 'asset6', '2', 'asset4');
console.log(`*** Result: ${prettyJSONString(result.toString())}`);
console.log('*** all tests completed');
} finally {
// Disconnect from the gateway when the application is closing
// This will close all connections to the network
gateway.disconnect();
}
} catch (error) {
console.error(`******** FAILED to run the application: ${error}`);
}
console.log('*** application ending');
}
main();

View file

@ -0,0 +1,16 @@
{
"name": "asset-transfer-basic",
"version": "1.0.0",
"description": "Asset-transfer-basic application implemented in JavaScript",
"engines": {
"node": ">=12",
"npm": ">=5"
},
"engineStrict": true,
"author": "Hyperledger",
"license": "Apache-2.0",
"dependencies": {
"fabric-ca-client": "^2.2.0",
"fabric-network": "^2.2.0"
}
}

View file

@ -99,7 +99,7 @@ type Asset struct {
// HistoryQueryResult structure used for returning result of history query
type HistoryQueryResult struct {
Record *Asset `json:"record"`
TxID string `json:"txID"`
TxId string `json:"txId"`
Timestamp time.Time `json:"timestamp"`
IsDelete bool `json:"isDelete"`
}
@ -379,6 +379,8 @@ func getQueryResultForQueryStringWithPagination(ctx contractapi.TransactionConte
// GetAssetHistory returns the chain of custody for an asset since issuance.
func (t *SimpleChaincode) GetAssetHistory(ctx contractapi.TransactionContextInterface, assetID string) ([]HistoryQueryResult, error) {
log.Printf("GetAssetHistory: ID %v", assetID)
resultsIterator, err := ctx.GetStub().GetHistoryForKey(assetID)
if err != nil {
return nil, err
@ -393,17 +395,24 @@ func (t *SimpleChaincode) GetAssetHistory(ctx contractapi.TransactionContextInte
}
var asset Asset
if len(response.Value) > 0 {
err = json.Unmarshal(response.Value, &asset)
if err != nil {
return nil, err
}
} else {
asset = Asset{
ID: assetID,
}
}
timestamp, err := ptypes.Timestamp(response.Timestamp)
if err != nil {
return nil, err
}
record := HistoryQueryResult{
TxID: response.TxId,
TxId: response.TxId,
Timestamp: timestamp,
Record: &asset,
IsDelete: response.IsDelete,

View file

@ -81,7 +81,7 @@ class Chaincode extends Contract{
// ==== Create asset object and marshal to JSON ====
let asset = {};
asset.docType = 'asset';
asset.assetID = assetID;
asset.ID = assetID;
asset.color = color;
asset.size = size;
asset.owner = owner;
@ -90,7 +90,7 @@ class Chaincode extends Contract{
// === Save asset to state ===
await ctx.stub.putState(assetID, Buffer.from(JSON.stringify(asset)));
let indexName = 'color~name'
let colorNameIndexKey = await ctx.stub.createCompositeKey(indexName, [asset.color, asset.assetID]);
let colorNameIndexKey = await ctx.stub.createCompositeKey(indexName, [asset.color, asset.ID]);
// Save index entry to state. Only the key name is needed, no need to store a duplicate copy of the marble.
// Note - passing a 'nil' value will effectively delete the key from state, therefore we pass null character as value
@ -137,7 +137,7 @@ class Chaincode extends Contract{
// delete the index
let indexName = 'color~name';
let colorNameIndexKey = ctx.stub.createCompositeKey(indexName, [assetJSON.color, assetJSON.assetID]);
let colorNameIndexKey = ctx.stub.createCompositeKey(indexName, [assetJSON.color, assetJSON.ID]);
if (!colorNameIndexKey) {
throw new Error(' Failed to create the createCompositeKey');
}
@ -145,7 +145,7 @@ class Chaincode extends Contract{
await ctx.stub.deleteState(colorNameIndexKey);
}
// TransferAsset transfers a asset by setting a new owner name on the asset
// TransferAsset transfers an asset by setting a new owner name on the asset
async TransferAsset(ctx, assetName, newOwner) {
let assetAsBytes = await ctx.stub.getState(assetName);
@ -293,8 +293,8 @@ class Chaincode extends Contract{
// GetAssetHistory returns the chain of custody for an asset since issuance.
async GetAssetHistory(ctx, assetName) {
let resultsIterator = await ctx.stub.getHistoryForKey(assetName);
let results = await this.GetAllResults(resultsIterator, true);
const resultsIterator = await ctx.stub.getHistoryForKey(assetName);
const results = await this.GetAllResults(resultsIterator, true);
return JSON.stringify(results);
}
@ -302,7 +302,7 @@ class Chaincode extends Contract{
// AssetExists returns true when asset with given ID exists in world state
async AssetExists(ctx, assetName) {
// ==== Check if asset already exists ====
let assetState = await ctx.stub.getState(assetName);
const assetState = await ctx.stub.getState(assetName);
if ( !assetState || assetState.length === 0 ) {
return false;
}
@ -310,80 +310,74 @@ class Chaincode extends Contract{
}
async GetAllResults(iterator, isHistory) {
let allResults = [];
while (true) {
const allResults = [];
let res = await iterator.next();
while (!res.done) {
const jsonRes = {};
if (res.value && res.value.value.toString()) {
let jsonRes = {};
console.log(res.value.value.toString('utf8'));
if (isHistory && isHistory === true) {
jsonRes.TxId = res.value.tx_id;
if (isHistory) {
jsonRes.TxId = res.value.txId;
jsonRes.Timestamp = res.value.timestamp;
try {
jsonRes.Value = JSON.parse(res.value.value.toString('utf8'));
} catch (err) {
console.log(err);
jsonRes.Value = res.value.value.toString('utf8');
jsonRes.IsDelete = res.value.isDelete;
}
} else {
jsonRes.Key = res.value.key;
try {
if (res.value.value.length > 0) {
jsonRes.Record = JSON.parse(res.value.value.toString('utf8'));
} catch (err) {
console.log(err);
jsonRes.Record = res.value.value.toString('utf8');
}
} else {
jsonRes.Record = {ID: res.value.key};
}
jsonRes.Key = res.value.key;
console.log('Result: ' + JSON.stringify(jsonRes));
allResults.push(jsonRes);
res = await iterator.next();
}
if (res.done) {
await iterator.close();
return allResults;
}
}
}
// InitLedger creates sample assets in the ledger
async InitLedger(ctx) {
const assets = [
{
assetID: 'asset1',
ID: 'asset1',
color: 'blue',
size: 5,
owner: 'Tom',
appraisedValue: 100
},
{
assetID: 'asset2',
ID: 'asset2',
color: 'red',
size: 5,
owner: 'Brad',
appraisedValue: 100
},
{
assetID: 'asset3',
ID: 'asset3',
color: 'green',
size: 10,
owner: 'Jin Soo',
appraisedValue: 200
},
{
assetID: 'asset4',
ID: 'asset4',
color: 'yellow',
size: 10,
owner: 'Max',
appraisedValue: 200
},
{
assetID: 'asset5',
ID: 'asset5',
color: 'black',
size: 15,
owner: 'Adriana',
appraisedValue: 250
},
{
assetID: 'asset6',
ID: 'asset6',
color: 'white',
size: 15,
owner: 'Michel',
@ -394,7 +388,7 @@ class Chaincode extends Contract{
for (let i = 0; i < assets.length; i++) {
await this.CreateAsset(
ctx,
assets[i].assetID,
assets[i].ID,
assets[i].color,
assets[i].size,
assets[i].owner,

View file

@ -27,3 +27,4 @@ popd
print "Stopping network"
./network.sh down
rm -R ../asset-transfer-basic/application-javascript/wallet

View file

@ -1,7 +1,6 @@
set -euo pipefail
FABRIC_VERSION=${FABRIC_VERSION:-2.2}
CHAINCODE_LANGUAGE=${CHAINCODE_LANGUAGE:-go}
CHAINCODE_NAME=${CHAINCODE_NAME:-ledger}
function print() {
@ -14,8 +13,28 @@ function print() {
print "Creating network"
./network.sh up createChannel -ca -s couchdb -i "${FABRIC_VERSION}"
print "Deploying ${CHAINCODE_NAME} chaincode"
./network.sh deployCC -ccn "${CHAINCODE_NAME}" -ccv 1 -ccs 1 -ccl "${CHAINCODE_LANGUAGE}"
print "Deploying ${CHAINCODE_NAME} go chaincode"
./network.sh deployCC -ccn "${CHAINCODE_NAME}" -ccv 1.0 -ccs 1 -ccl go
# Run Javascript application against the go chaincode
print "Initializing Javascript application"
pushd ../asset-transfer-ledger-queries/application-javascript
npm install
print "Executing app.js"
node app.js
popd
print "Deploying ${CHAINCODE_NAME} javascript chaincode"
./network.sh deployCC -ccn "${CHAINCODE_NAME}" -ccv 2.0 -ccs 2 -ccl javascript
# Run Javascript application against the javascript chaincode
print "Initializing Javascript application"
pushd ../asset-transfer-ledger-queries/application-javascript
npm install
print "Executing app.js"
node app.js skipInit
popd
print "Stopping network"
./network.sh down
rm -R ../asset-transfer-ledger-queries/application-javascript/wallet

View file

@ -6,9 +6,6 @@
'use strict';
const fs = require('fs');
const path = require('path');
const adminUserId = 'admin';
const adminUserPasswd = 'adminpw';
@ -53,7 +50,7 @@ exports.enrollAdmin = async (caClient, wallet) => {
}
};
exports.registerUser = async (caClient, wallet, userId, affiliation) => {
exports.registerAndEnrollUser = async (caClient, wallet, userId, affiliation) => {
try {
// Check to see if we've already enrolled the user
const userIdentity = await wallet.get(userId);