mirror of
https://github.com/hyperledger/fabric-samples.git
synced 2026-06-17 07:25:10 +00:00
These samples target Fabric v2.2 but contained references to the latest version of the Fabric documentation, many of which were broken links since the structure and content of the Fabric documentation has changed. This change updates links to the Fabric documentation so that they refer to release-2.2. Signed-off-by: Mark S. Lewis <Mark.S.Lewis@outlook.com>
545 lines
23 KiB
JavaScript
545 lines
23 KiB
JavaScript
/*
|
|
* Copyright IBM Corp. All Rights Reserved.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
/**
|
|
* Application that shows events when creating and updating an asset
|
|
* -- How to register a contract listener for chaincode events
|
|
* -- How to get the chaincode event name and value from the chaincode event
|
|
* -- How to retrieve the transaction and block information from the chaincode event
|
|
* -- How to register a block listener for full block events
|
|
* -- How to retrieve the transaction and block information from the full block event
|
|
* -- How to register to recieve private data associated with transactions when
|
|
* registering a block listener
|
|
* -- How to retreive the private data from the full block event
|
|
* -- The listener will be notified of an event at anytime. Notice that events will
|
|
* be posted by the listener after the application activity causing the ledger change
|
|
* and during other application activity unrelated to the event
|
|
* -- How to connect to a Gateway that will not use events when submitting transactions.
|
|
* This may be useful when the application does not want to wait for the peer to commit
|
|
* blocks and notify the application.
|
|
*
|
|
* To see the SDK workings, try setting the logging to be displayed on the console
|
|
* before executing this application.
|
|
* export HFC_LOGGING='{"debug":"console"}'
|
|
* See the following on how the SDK is working with the Peer's Event Services
|
|
* https://hyperledger-fabric.readthedocs.io/en/release-2.2/peer_event_services.html
|
|
*
|
|
* See the following for more details on using the Node SDK
|
|
* https://hyperledger.github.io/fabric-sdk-node/release-2.2/module-fabric-network.html
|
|
*/
|
|
|
|
// pre-requisites:
|
|
// - fabric-sample two organization test-network setup with two peers, ordering service,
|
|
// and 2 certificate authorities
|
|
// ===> from directory test-network
|
|
// ./network.sh up createChannel -ca
|
|
//
|
|
// - Use the asset-transfer-events/chaincode-javascript chaincode deployed on
|
|
// the channel "mychannel". 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 test-network
|
|
// ./network.sh deployCC -ccn events -ccp ../asset-transfer-events/chaincode-javacript/ -ccl javascript -ccep "OR('Org1MSP.peer','Org2MSP.peer')"
|
|
//
|
|
// - Be sure that node.js is installed
|
|
// ===> from directory asset-transfer-sbe/application-javascript
|
|
// node -v
|
|
// - npm installed code dependencies
|
|
// ===> from directory asset-transfer-sbe/application-javascript
|
|
// npm install
|
|
// - to run this test application
|
|
// ===> from directory asset-transfer-sbe/application-javascript
|
|
// node app.js
|
|
|
|
// NOTE: If you see an error like these:
|
|
/*
|
|
|
|
Error in setup: Error: DiscoveryService: mychannel error: access denied
|
|
|
|
OR
|
|
|
|
Failed to register user : Error: fabric-ca request register failed with errors [[ { code: 20, message: 'Authentication failure' } ]]
|
|
|
|
*/
|
|
// Delete the /fabric-samples/asset-transfer-sbe/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.
|
|
//
|
|
|
|
// use this to set logging, must be set before the require('fabric-network');
|
|
process.env.HFC_LOGGING = '{"debug": "./debug.log"}';
|
|
|
|
const { Gateway, Wallets } = require('fabric-network');
|
|
const EventStrategies = require('fabric-network/lib/impl/event/defaulteventhandlerstrategies');
|
|
const FabricCAServices = require('fabric-ca-client');
|
|
const path = require('path');
|
|
const { buildCAClient, registerAndEnrollUser, enrollAdmin } = require('../../test-application/javascript/CAUtil.js');
|
|
const { buildCCPOrg1, buildWallet } = require('../../test-application/javascript/AppUtil.js');
|
|
|
|
const channelName = 'mychannel';
|
|
const chaincodeName = 'events';
|
|
|
|
const org1 = 'Org1MSP';
|
|
const Org1UserId = 'appUser1';
|
|
|
|
const RED = '\x1b[31m\n';
|
|
const GREEN = '\x1b[32m\n';
|
|
const BLUE = '\x1b[34m';
|
|
const RESET = '\x1b[0m';
|
|
|
|
/**
|
|
* Perform a sleep -- asynchronous wait
|
|
* @param ms the time in milliseconds to sleep for
|
|
*/
|
|
function sleep(ms) {
|
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
}
|
|
|
|
async function initGatewayForOrg1(useCommitEvents) {
|
|
console.log(`${GREEN}--> Fabric client user & Gateway init: Using Org1 identity to Org1 Peer${RESET}`);
|
|
// build an in memory object with the network configuration (also known as a connection profile)
|
|
const ccpOrg1 = buildCCPOrg1();
|
|
|
|
// build an instance of the fabric ca services client based on
|
|
// the information in the network configuration
|
|
const caOrg1Client = buildCAClient(FabricCAServices, ccpOrg1, 'ca.org1.example.com');
|
|
|
|
// setup the wallet to cache the credentials of the application user, on the app server locally
|
|
const walletPathOrg1 = path.join(__dirname, 'wallet', 'org1');
|
|
const walletOrg1 = await buildWallet(Wallets, walletPathOrg1);
|
|
|
|
// in a real application this would be done on an administrative flow, and only once
|
|
// stores admin identity in local wallet, if needed
|
|
await enrollAdmin(caOrg1Client, walletOrg1, org1);
|
|
// register & enroll application user with CA, which is used as client identify to make chaincode calls
|
|
// and stores app user identity in local 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(caOrg1Client, walletOrg1, org1, Org1UserId, 'org1.department1');
|
|
|
|
try {
|
|
// Create a new gateway for connecting to Org's peer node.
|
|
const gatewayOrg1 = new Gateway();
|
|
|
|
if (useCommitEvents) {
|
|
await gatewayOrg1.connect(ccpOrg1, {
|
|
wallet: walletOrg1,
|
|
identity: Org1UserId,
|
|
discovery: { enabled: true, asLocalhost: true }
|
|
});
|
|
} else {
|
|
await gatewayOrg1.connect(ccpOrg1, {
|
|
wallet: walletOrg1,
|
|
identity: Org1UserId,
|
|
discovery: { enabled: true, asLocalhost: true },
|
|
eventHandlerOptions: EventStrategies.NONE
|
|
});
|
|
}
|
|
|
|
|
|
return gatewayOrg1;
|
|
} catch (error) {
|
|
console.error(`Error in connecting to gateway for Org1: ${error}`);
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
function checkAsset(org, resultBuffer, color, size, owner, appraisedValue, price) {
|
|
console.log(`${GREEN}<-- Query results from ${org}${RESET}`);
|
|
|
|
let asset;
|
|
if (resultBuffer) {
|
|
asset = JSON.parse(resultBuffer.toString('utf8'));
|
|
} else {
|
|
console.log(`${RED}*** Failed to read asset${RESET}`);
|
|
}
|
|
console.log(`*** verify asset ${asset.ID}`);
|
|
|
|
if (asset) {
|
|
if (asset.Color === color) {
|
|
console.log(`*** asset ${asset.ID} has color ${asset.Color}`);
|
|
} else {
|
|
console.log(`${RED}*** asset ${asset.ID} has color of ${asset.Color}${RESET}`);
|
|
}
|
|
if (asset.Size === size) {
|
|
console.log(`*** asset ${asset.ID} has size ${asset.Size}`);
|
|
} else {
|
|
console.log(`${RED}*** Failed size check from ${org} - asset ${asset.ID} has size of ${asset.Size}${RESET}`);
|
|
}
|
|
if (asset.Owner === owner) {
|
|
console.log(`*** asset ${asset.ID} owned by ${asset.Owner}`);
|
|
} else {
|
|
console.log(`${RED}*** Failed owner check from ${org} - asset ${asset.ID} owned by ${asset.Owner}${RESET}`);
|
|
}
|
|
if (asset.AppraisedValue === appraisedValue) {
|
|
console.log(`*** asset ${asset.ID} has appraised value ${asset.AppraisedValue}`);
|
|
} else {
|
|
console.log(`${RED}*** Failed appraised value check from ${org} - asset ${asset.ID} has appraised value of ${asset.AppraisedValue}${RESET}`);
|
|
}
|
|
if (price) {
|
|
if (asset.asset_properties && asset.asset_properties.Price === price) {
|
|
console.log(`*** asset ${asset.ID} has price ${asset.asset_properties.Price}`);
|
|
} else {
|
|
console.log(`${RED}*** Failed price check from ${org} - asset ${asset.ID} has price of ${asset.asset_properties.Price}${RESET}`);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function showTransactionData(transactionData) {
|
|
const creator = transactionData.actions[0].header.creator;
|
|
console.log(` - submitted by: ${creator.mspid}-${creator.id_bytes.toString('hex')}`);
|
|
for (const endorsement of transactionData.actions[0].payload.action.endorsements) {
|
|
console.log(` - endorsed by: ${endorsement.endorser.mspid}-${endorsement.endorser.id_bytes.toString('hex')}`);
|
|
}
|
|
const chaincode = transactionData.actions[0].payload.chaincode_proposal_payload.input.chaincode_spec;
|
|
console.log(` - chaincode:${chaincode.chaincode_id.name}`);
|
|
console.log(` - function:${chaincode.input.args[0].toString()}`);
|
|
for (let x = 1; x < chaincode.input.args.length; x++) {
|
|
console.log(` - arg:${chaincode.input.args[x].toString()}`);
|
|
}
|
|
}
|
|
|
|
async function main() {
|
|
console.log(`${BLUE} **** START ****${RESET}`);
|
|
try {
|
|
let randomNumber = Math.floor(Math.random() * 1000) + 1;
|
|
// use a random key so that we can run multiple times
|
|
let assetKey = `item-${randomNumber}`;
|
|
|
|
/** ******* Fabric client init: Using Org1 identity to Org1 Peer ******* */
|
|
const gateway1Org1 = await initGatewayForOrg1(true); // transaction handling uses commit events
|
|
const gateway2Org1 = await initGatewayForOrg1();
|
|
|
|
try {
|
|
//
|
|
// - - - - - - C H A I N C O D E E V E N T S
|
|
//
|
|
console.log(`${BLUE} **** CHAINCODE EVENTS ****${RESET}`);
|
|
let transaction;
|
|
let listener;
|
|
const network1Org1 = await gateway1Org1.getNetwork(channelName);
|
|
const contract1Org1 = network1Org1.getContract(chaincodeName);
|
|
|
|
try {
|
|
// first create a listener to be notified of chaincode code events
|
|
// coming from the chaincode ID "events"
|
|
listener = async (event) => {
|
|
// The payload of the chaincode event is the value place there by the
|
|
// chaincode. Notice it is a byte data and the application will have
|
|
// to know how to deserialize.
|
|
// In this case we know that the chaincode will always place the asset
|
|
// being worked with as the payload for all events produced.
|
|
const asset = JSON.parse(event.payload.toString());
|
|
console.log(`${GREEN}<-- Contract Event Received: ${event.eventName} - ${JSON.stringify(asset)}${RESET}`);
|
|
// show the information available with the event
|
|
console.log(`*** Event: ${event.eventName}:${asset.ID}`);
|
|
// notice how we have access to the transaction information that produced this chaincode event
|
|
const eventTransaction = event.getTransactionEvent();
|
|
console.log(`*** transaction: ${eventTransaction.transactionId} status:${eventTransaction.status}`);
|
|
showTransactionData(eventTransaction.transactionData);
|
|
// notice how we have access to the full block that contains this transaction
|
|
const eventBlock = eventTransaction.getBlockEvent();
|
|
console.log(`*** block: ${eventBlock.blockNumber.toString()}`);
|
|
};
|
|
// now start the client side event service and register the listener
|
|
console.log(`${GREEN}--> Start contract event stream to peer in Org1${RESET}`);
|
|
await contract1Org1.addContractListener(listener);
|
|
} catch (eventError) {
|
|
console.log(`${RED}<-- Failed: Setup contract events - ${eventError}${RESET}`);
|
|
}
|
|
|
|
try {
|
|
// C R E A T E
|
|
console.log(`${GREEN}--> Submit Transaction: CreateAsset, ${assetKey} owned by Sam${RESET}`);
|
|
transaction = contract1Org1.createTransaction('CreateAsset');
|
|
await transaction.submit(assetKey, 'blue', '10', 'Sam', '100');
|
|
console.log(`${GREEN}<-- Submit CreateAsset Result: committed, asset ${assetKey}${RESET}`);
|
|
} catch (createError) {
|
|
console.log(`${RED}<-- Submit Failed: CreateAsset - ${createError}${RESET}`);
|
|
}
|
|
try {
|
|
// R E A D
|
|
console.log(`${GREEN}--> Evaluate: ReadAsset, - ${assetKey} should be owned by Sam${RESET}`);
|
|
const resultBuffer = await contract1Org1.evaluateTransaction('ReadAsset', assetKey);
|
|
checkAsset(org1, resultBuffer, 'blue', '10', 'Sam', '100');
|
|
} catch (readError) {
|
|
console.log(`${RED}<-- Failed: ReadAsset - ${readError}${RESET}`);
|
|
}
|
|
|
|
try {
|
|
// U P D A T E
|
|
console.log(`${GREEN}--> Submit Transaction: UpdateAsset ${assetKey} update appraised value to 200`);
|
|
transaction = contract1Org1.createTransaction('UpdateAsset');
|
|
await transaction.submit(assetKey, 'blue', '10', 'Sam', '200');
|
|
console.log(`${GREEN}<-- Submit UpdateAsset Result: committed, asset ${assetKey}${RESET}`);
|
|
} catch (updateError) {
|
|
console.log(`${RED}<-- Failed: UpdateAsset - ${updateError}${RESET}`);
|
|
}
|
|
try {
|
|
// R E A D
|
|
console.log(`${GREEN}--> Evaluate: ReadAsset, - ${assetKey} should now have appraised value of 200${RESET}`);
|
|
const resultBuffer = await contract1Org1.evaluateTransaction('ReadAsset', assetKey);
|
|
checkAsset(org1, resultBuffer, 'blue', '10', 'Sam', '200');
|
|
} catch (readError) {
|
|
console.log(`${RED}<-- Failed: ReadAsset - ${readError}${RESET}`);
|
|
}
|
|
|
|
try {
|
|
// T R A N S F E R
|
|
console.log(`${GREEN}--> Submit Transaction: TransferAsset ${assetKey} to Mary`);
|
|
transaction = contract1Org1.createTransaction('TransferAsset');
|
|
await transaction.submit(assetKey, 'Mary');
|
|
console.log(`${GREEN}<-- Submit TransferAsset Result: committed, asset ${assetKey}${RESET}`);
|
|
} catch (transferError) {
|
|
console.log(`${RED}<-- Failed: TransferAsset - ${transferError}${RESET}`);
|
|
}
|
|
try {
|
|
// R E A D
|
|
console.log(`${GREEN}--> Evaluate: ReadAsset, - ${assetKey} should now be owned by Mary${RESET}`);
|
|
const resultBuffer = await contract1Org1.evaluateTransaction('ReadAsset', assetKey);
|
|
checkAsset(org1, resultBuffer, 'blue', '10', 'Mary', '200');
|
|
} catch (readError) {
|
|
console.log(`${RED}<-- Failed: ReadAsset - ${readError}${RESET}`);
|
|
}
|
|
|
|
try {
|
|
// D E L E T E
|
|
console.log(`${GREEN}--> Submit Transaction: DeleteAsset ${assetKey}`);
|
|
transaction = contract1Org1.createTransaction('DeleteAsset');
|
|
await transaction.submit(assetKey);
|
|
console.log(`${GREEN}<-- Submit DeleteAsset Result: committed, asset ${assetKey}${RESET}`);
|
|
} catch (deleteError) {
|
|
console.log(`${RED}<-- Failed: DeleteAsset - ${deleteError}${RESET}`);
|
|
if (deleteError.toString().includes('ENDORSEMENT_POLICY_FAILURE')) {
|
|
console.log(`${RED}Be sure that chaincode was deployed with the endorsement policy "OR('Org1MSP.peer','Org2MSP.peer')"${RESET}`)
|
|
}
|
|
}
|
|
try {
|
|
// R E A D
|
|
console.log(`${GREEN}--> Evaluate: ReadAsset, - ${assetKey} should now be deleted${RESET}`);
|
|
const resultBuffer = await contract1Org1.evaluateTransaction('ReadAsset', assetKey);
|
|
checkAsset(org1, resultBuffer, 'blue', '10', 'Mary', '200');
|
|
console.log(`${RED}<-- Failed: ReadAsset - should not have read this asset${RESET}`);
|
|
} catch (readError) {
|
|
console.log(`${GREEN}<-- Success: ReadAsset - ${readError}${RESET}`);
|
|
}
|
|
|
|
// all done with this listener
|
|
contract1Org1.removeContractListener(listener);
|
|
|
|
//
|
|
// - - - - - - B L O C K E V E N T S with P R I V A T E D A T A
|
|
//
|
|
console.log(`${BLUE} **** BLOCK EVENTS with PRIVATE DATA ****${RESET}`);
|
|
const network2Org1 = await gateway2Org1.getNetwork(channelName);
|
|
const contract2Org1 = network2Org1.getContract(chaincodeName);
|
|
|
|
randomNumber = Math.floor(Math.random() * 1000) + 1;
|
|
assetKey = `item-${randomNumber}`;
|
|
|
|
let firstBlock = true; // simple indicator to track blocks
|
|
|
|
try {
|
|
let listener;
|
|
|
|
// create a block listener
|
|
listener = async (event) => {
|
|
if (firstBlock) {
|
|
console.log(`${GREEN}<-- Block Event Received - block number: ${event.blockNumber.toString()}` +
|
|
'\n### Note:' +
|
|
'\n This block event represents the current top block of the ledger.' +
|
|
`\n All block events after this one are events that represent new blocks added to the ledger${RESET}`);
|
|
firstBlock = false;
|
|
} else {
|
|
console.log(`${GREEN}<-- Block Event Received - block number: ${event.blockNumber.toString()}${RESET}`);
|
|
}
|
|
const transEvents = event.getTransactionEvents();
|
|
for (const transEvent of transEvents) {
|
|
console.log(`*** transaction event: ${transEvent.transactionId}`);
|
|
if (transEvent.privateData) {
|
|
for (const namespace of transEvent.privateData.ns_pvt_rwset) {
|
|
console.log(` - private data: ${namespace.namespace}`);
|
|
for (const collection of namespace.collection_pvt_rwset) {
|
|
console.log(` - collection: ${collection.collection_name}`);
|
|
if (collection.rwset.reads) {
|
|
for (const read of collection.rwset.reads) {
|
|
console.log(` - read set - ${BLUE}key:${RESET} ${read.key} ${BLUE}value:${read.value.toString()}`);
|
|
}
|
|
}
|
|
if (collection.rwset.writes) {
|
|
for (const write of collection.rwset.writes) {
|
|
console.log(` - write set - ${BLUE}key:${RESET}${write.key} ${BLUE}is_delete:${RESET}${write.is_delete} ${BLUE}value:${RESET}${write.value.toString()}`);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (transEvent.transactionData) {
|
|
showTransactionData(transEvent.transactionData);
|
|
}
|
|
}
|
|
};
|
|
// now start the client side event service and register the listener
|
|
console.log(`${GREEN}--> Start private data block event stream to peer in Org1${RESET}`);
|
|
await network2Org1.addBlockListener(listener, {type: 'private'});
|
|
} catch (eventError) {
|
|
console.log(`${RED}<-- Failed: Setup block events - ${eventError}${RESET}`);
|
|
}
|
|
|
|
try {
|
|
// C R E A T E
|
|
console.log(`${GREEN}--> Submit Transaction: CreateAsset, ${assetKey} owned by Sam${RESET}`);
|
|
transaction = contract2Org1.createTransaction('CreateAsset');
|
|
|
|
// create the private data with salt and assign to the transaction
|
|
const randomNumber = Math.floor(Math.random() * 100) + 1;
|
|
const asset_properties = {
|
|
object_type: 'asset_properties',
|
|
asset_id: assetKey,
|
|
Price: '90',
|
|
salt: Buffer.from(randomNumber.toString()).toString('hex')
|
|
};
|
|
const asset_properties_string = JSON.stringify(asset_properties);
|
|
transaction.setTransient({
|
|
asset_properties: Buffer.from(asset_properties_string)
|
|
});
|
|
// With the addition of private data to the transaction
|
|
// We must only send this to the organization that will be
|
|
// saving the private data or we will get an endorsement policy failure
|
|
transaction.setEndorsingOrganizations(org1);
|
|
// endorse and commit - private data (transient data) will be
|
|
// saved to the implicit collection on the peer
|
|
await transaction.submit(assetKey, 'blue', '10', 'Sam', '100');
|
|
console.log(`${GREEN}<-- Submit CreateAsset Result: committed, asset ${assetKey}${RESET}`);
|
|
} catch (createError) {
|
|
console.log(`${RED}<-- Failed: CreateAsset - ${createError}${RESET}`);
|
|
}
|
|
await sleep(5000); // need to wait for event to be committed
|
|
try {
|
|
// R E A D
|
|
console.log(`${GREEN}--> Evaluate: ReadAsset, - ${assetKey} should be owned by Sam${RESET}`);
|
|
const resultBuffer = await contract2Org1.evaluateTransaction('ReadAsset', assetKey);
|
|
checkAsset(org1, resultBuffer, 'blue', '10', 'Sam', '100', '90');
|
|
} catch (readError) {
|
|
console.log(`${RED}<-- Failed: ReadAsset - ${readError}${RESET}`);
|
|
}
|
|
|
|
try {
|
|
// U P D A T E
|
|
console.log(`${GREEN}--> Submit Transaction: UpdateAsset ${assetKey} update appraised value to 200`);
|
|
transaction = contract2Org1.createTransaction('UpdateAsset');
|
|
|
|
// update the private data with new salt and assign to the transaction
|
|
const randomNumber = Math.floor(Math.random() * 100) + 1;
|
|
const asset_properties = {
|
|
object_type: 'asset_properties',
|
|
asset_id: assetKey,
|
|
Price: '90',
|
|
salt: Buffer.from(randomNumber.toString()).toString('hex')
|
|
};
|
|
const asset_properties_string = JSON.stringify(asset_properties);
|
|
transaction.setTransient({
|
|
asset_properties: Buffer.from(asset_properties_string)
|
|
});
|
|
transaction.setEndorsingOrganizations(org1);
|
|
|
|
await transaction.submit(assetKey, 'blue', '10', 'Sam', '200');
|
|
console.log(`${GREEN}<-- Submit UpdateAsset Result: committed, asset ${assetKey}${RESET}`);
|
|
} catch (updateError) {
|
|
console.log(`${RED}<-- Failed: UpdateAsset - ${updateError}${RESET}`);
|
|
}
|
|
await sleep(5000); // need to wait for event to be committed
|
|
try {
|
|
// R E A D
|
|
console.log(`${GREEN}--> Evaluate: ReadAsset, - ${assetKey} should now have appraised value of 200${RESET}`);
|
|
const resultBuffer = await contract2Org1.evaluateTransaction('ReadAsset', assetKey);
|
|
checkAsset(org1, resultBuffer, 'blue', '10', 'Sam', '200', '90');
|
|
} catch (readError) {
|
|
console.log(`${RED}<-- Failed: ReadAsset - ${readError}${RESET}`);
|
|
}
|
|
|
|
try {
|
|
// T R A N S F E R
|
|
console.log(`${GREEN}--> Submit Transaction: TransferAsset ${assetKey} to Mary`);
|
|
transaction = contract2Org1.createTransaction('TransferAsset');
|
|
|
|
// update the private data with new salt and assign to the transaction
|
|
const randomNumber = Math.floor(Math.random() * 100) + 1;
|
|
const asset_properties = {
|
|
object_type: 'asset_properties',
|
|
asset_id: assetKey,
|
|
Price: '180',
|
|
salt: Buffer.from(randomNumber.toString()).toString('hex')
|
|
};
|
|
const asset_properties_string = JSON.stringify(asset_properties);
|
|
transaction.setTransient({
|
|
asset_properties: Buffer.from(asset_properties_string)
|
|
});
|
|
transaction.setEndorsingOrganizations(org1);
|
|
|
|
await transaction.submit(assetKey, 'Mary');
|
|
console.log(`${GREEN}<-- Submit TransferAsset Result: committed, asset ${assetKey}${RESET}`);
|
|
} catch (transferError) {
|
|
console.log(`${RED}<-- Failed: TransferAsset - ${transferError}${RESET}`);
|
|
}
|
|
await sleep(5000); // need to wait for event to be committed
|
|
try {
|
|
// R E A D
|
|
console.log(`${GREEN}--> Evaluate: ReadAsset, - ${assetKey} should now be owned by Mary${RESET}`);
|
|
const resultBuffer = await contract2Org1.evaluateTransaction('ReadAsset', assetKey);
|
|
checkAsset(org1, resultBuffer, 'blue', '10', 'Mary', '200', '180');
|
|
} catch (readError) {
|
|
console.log(`${RED}<-- Failed: ReadAsset - ${readError}${RESET}`);
|
|
}
|
|
|
|
try {
|
|
// D E L E T E
|
|
console.log(`${GREEN}--> Submit Transaction: DeleteAsset ${assetKey}`);
|
|
transaction = contract2Org1.createTransaction('DeleteAsset');
|
|
await transaction.submit(assetKey);
|
|
console.log(`${GREEN}<-- Submit DeleteAsset Result: committed, asset ${assetKey}${RESET}`);
|
|
} catch (deleteError) {
|
|
console.log(`${RED}<-- Failed: DeleteAsset - ${deleteError}${RESET}`);
|
|
}
|
|
await sleep(5000); // need to wait for event to be committed
|
|
try {
|
|
// R E A D
|
|
console.log(`${GREEN}--> Evaluate: ReadAsset, - ${assetKey} should now be deleted${RESET}`);
|
|
const resultBuffer = await contract2Org1.evaluateTransaction('ReadAsset', assetKey);
|
|
checkAsset(org1, resultBuffer, 'blue', '10', 'Mary', '200');
|
|
console.log(`${RED}<-- Failed: ReadAsset - should not have read this asset${RESET}`);
|
|
} catch (readError) {
|
|
console.log(`${GREEN}<-- Success: ReadAsset - ${readError}${RESET}`);
|
|
}
|
|
|
|
// all done with this listener
|
|
network2Org1.removeBlockListener(listener);
|
|
|
|
} catch (runError) {
|
|
console.error(`Error in transaction: ${runError}`);
|
|
if (runError.stack) {
|
|
console.error(runError.stack);
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error(`Error in setup: ${error}`);
|
|
if (error.stack) {
|
|
console.error(error.stack);
|
|
}
|
|
process.exit(1);
|
|
}
|
|
|
|
await sleep(5000);
|
|
console.log(`${BLUE} **** END ****${RESET}`);
|
|
process.exit(0);
|
|
}
|
|
main();
|