mirror of
https://github.com/hyperledger/fabric-samples.git
synced 2026-06-17 15:35:09 +00:00
new file: LandContract/application-typescript/package.json
new file: LandContract/application-typescript/src/Admin.js new file: LandContract/application-typescript/src/app.ts new file: LandContract/application-typescript/src/registerEnrollUser.js new file: LandContract/application-typescript/src/utils/AppUtil.ts new file: LandContract/application-typescript/src/utils/CAUtil.ts new file: LandContract/application-typescript/tsconfig.json new file: LandContract/application-typescript/tslint.json new file: chaincode-typescript/Dockerfile new file: chaincode-typescript/dist/Contract/landAsset.d.ts new file: chaincode-typescript/dist/Contract/landAsset.js new file: chaincode-typescript/dist/Contract/landAsset.js.map new file: chaincode-typescript/dist/Contract/landTransaction.d.ts new file: chaincode-typescript/dist/Contract/landTransaction.js new file: chaincode-typescript/dist/Contract/landTransaction.js.map new file: chaincode-typescript/dist/asset.d.ts new file: chaincode-typescript/dist/asset.js new file: chaincode-typescript/dist/asset.js.map new file: chaincode-typescript/dist/assetTransfer.d.ts new file: chaincode-typescript/dist/assetTransfer.js new file: chaincode-typescript/dist/assetTransfer.js.map new file: chaincode-typescript/dist/index.d.ts new file: chaincode-typescript/dist/index.js new file: chaincode-typescript/dist/index.js.map new file: chaincode-typescript/docker/docker-entrypoint.sh new file: chaincode-typescript/npm-shrinkwrap.json new file: chaincode-typescript/package.json new file: chaincode-typescript/src/Contract/Admin.js new file: chaincode-typescript/src/Contract/landAsset.ts new file: chaincode-typescript/src/Contract/landTransaction.ts new file: chaincode-typescript/src/Contract/registerEnrollUser.js new file: chaincode-typescript/src/Contract/userRequest.ts new file: chaincode-typescript/src/Contract/wallet/admin.id new file: chaincode-typescript/src/Contract/wallet/user123.id new file: chaincode-typescript/src/asset.ts new file: chaincode-typescript/src/assetTransfer.ts new file: chaincode-typescript/src/index.ts new file: chaincode-typescript/tsconfig.json new file: chaincode-typescript/tslint.json modified: test-network/compose/compose-ca.yaml modified: test-network/compose/compose-test-net.yaml modified: test-network/compose/docker/docker-compose-bft-test-net.yaml modified: test-network/compose/docker/docker-compose-test-net.yaml modified: test-network/configtx/configtx.yaml modified: test-network/network.sh modified: test-network/organizations/ccp-generate.sh modified: test-network/organizations/cryptogen/crypto-config-org2.yaml new file: test-network/organizations/cryptogen/crypto-config-org3.yaml new file: test-network/organizations/cryptogen/crypto-config-org4.yaml modified: test-network/organizations/fabric-ca/registerEnroll.sh new file: test-network_org4.zip
This commit is contained in:
parent
62f304a98f
commit
3768c0add8
52 changed files with 6412 additions and 83 deletions
15
LandContract/application-typescript/.gitignore
vendored
Normal file
15
LandContract/application-typescript/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Compiled TypeScript files
|
||||
dist
|
||||
|
||||
51
LandContract/application-typescript/package.json
Normal file
51
LandContract/application-typescript/package.json
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
{
|
||||
"name": "asset-transfer-basic",
|
||||
"version": "1.0.0",
|
||||
"description": "Asset Transfer Basic contract implemented in TypeScript",
|
||||
"main": "dist/index.js",
|
||||
"typings": "dist/index.d.ts",
|
||||
"engines": {
|
||||
"node": ">=14.14"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "tslint -c tslint.json 'src/**/*.ts'",
|
||||
"pretest": "npm run lint",
|
||||
"start": "npm run build && node dist/app.js",
|
||||
"build": "tsc",
|
||||
"build:watch": "tsc -w",
|
||||
"prepublishOnly": "npm run build"
|
||||
},
|
||||
"engineStrict": true,
|
||||
"author": "Hyperledger",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"fabric-ca-client": "^2.2.19",
|
||||
"fabric-network": "^2.2.19"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tsconfig/node14": "^14.1.0",
|
||||
"@types/node": "^14.17.32",
|
||||
"tslint": "^5.11.0",
|
||||
"typescript": "~4.9.4"
|
||||
},
|
||||
"nyc": {
|
||||
"extension": [
|
||||
".ts",
|
||||
".tsx"
|
||||
],
|
||||
"exclude": [
|
||||
"coverage/**",
|
||||
"dist/**"
|
||||
],
|
||||
"reporter": [
|
||||
"text-summary",
|
||||
"html"
|
||||
],
|
||||
"all": true,
|
||||
"check-coverage": true,
|
||||
"statements": 100,
|
||||
"branches": 100,
|
||||
"functions": 100,
|
||||
"lines": 100
|
||||
}
|
||||
}
|
||||
47
LandContract/application-typescript/src/Admin.js
Normal file
47
LandContract/application-typescript/src/Admin.js
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
const { Wallets } = require('fabric-network');
|
||||
const FabricCAServices = require('fabric-ca-client');
|
||||
const path = require('path');
|
||||
const { buildCAClient, enrollAdmin, ClearWallet } = require('./utils/CAUtil.ts');
|
||||
const { buildCCPOrg1, buildWallet } = require('./utils/AppUtil.ts');
|
||||
|
||||
const mspOrg1 = 'Org1MSP';
|
||||
|
||||
async function enrollAdmmin() {
|
||||
console.log('\n--> Enrolling the Org1 CA admin');
|
||||
const ccpOrg1 = buildCCPOrg1();
|
||||
const caOrg1Client = buildCAClient(FabricCAServices, ccpOrg1, 'ca.org1.example.com');
|
||||
|
||||
const walletPathOrg1 = path.join(__dirname, 'wallet');
|
||||
const walletOrg1 = await buildWallet(Wallets, walletPathOrg1);
|
||||
|
||||
await enrollAdmin(caOrg1Client, walletOrg1, mspOrg1);
|
||||
}
|
||||
|
||||
async function clearWallet(){
|
||||
const walletPath = path.join(__dirname, 'wallet');
|
||||
const wallet = await buildWallet(Wallets, walletPath);
|
||||
|
||||
await ClearWallet(wallet);
|
||||
}
|
||||
|
||||
async function main() {
|
||||
cmd = "create";
|
||||
if (!(process.argv[2] === undefined)) {
|
||||
cmd = process.argv[2];
|
||||
}
|
||||
|
||||
try {
|
||||
if(cmd=="clear"){
|
||||
await clearWallet();
|
||||
}else if(cmd=="create"){
|
||||
await enrollAdmmin();
|
||||
}else{
|
||||
throw Error(cmd + " is not defined. (create / clean)")
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Error in admin: ${error}`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
172
LandContract/application-typescript/src/app.ts
Normal file
172
LandContract/application-typescript/src/app.ts
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
/*
|
||||
* Copyright IBM Corp. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
import { Gateway, GatewayOptions } from 'fabric-network';
|
||||
import * as path from 'path';
|
||||
import { buildCCPOrg1, buildWallet, prettyJSONString } from './utils//AppUtil';
|
||||
import { buildCAClient, enrollAdmin, registerAndEnrollUser } from './utils/CAUtil';
|
||||
|
||||
const channelName = process.env.CHANNEL_NAME || 'mychannel';
|
||||
const chaincodeName = process.env.CHAINCODE_NAME || 'basic';
|
||||
|
||||
const mspOrg1 = 'Org1MSP';
|
||||
const walletPath = path.join(__dirname, 'wallet');
|
||||
const org1UserId = 'typescriptAppUser';
|
||||
|
||||
// pre-requisites:
|
||||
// - fabric-sample two organization test-network setup with two peers, ordering service,
|
||||
// and 2 certificate authorities
|
||||
// ===> from directory /fabric-samples/test-network
|
||||
// ./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 -ccp ../asset-transfer-basic/chaincode-typescript/ -ccl javascript
|
||||
// - Be sure that node.js is installed
|
||||
// ===> from directory /fabric-samples/asset-transfer-basic/application-typescript
|
||||
// node -v
|
||||
// - npm installed code dependencies
|
||||
// ===> from directory /fabric-samples/asset-transfer-basic/application-typescript
|
||||
// npm install
|
||||
// - to run this test application
|
||||
// ===> from directory /fabric-samples/asset-transfer-basic/application-typescript
|
||||
// npm start
|
||||
|
||||
// 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-typescript/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 queries operations with any of the asset-transfer-basic 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() {
|
||||
try {
|
||||
// build an in memory object with the network configuration (also known as a connection profile)
|
||||
const ccp = buildCCPOrg1();
|
||||
|
||||
// build an instance of the fabric ca services client based on
|
||||
// the information in the network configuration
|
||||
const caClient = buildCAClient(ccp, 'ca.org1.example.com');
|
||||
|
||||
// setup the wallet to hold the credentials of the application user
|
||||
const wallet = await buildWallet(walletPath);
|
||||
|
||||
// in a real application this would be done on an administrative flow, and only once
|
||||
await enrollAdmin(caClient, wallet, mspOrg1);
|
||||
|
||||
// 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, mspOrg1, org1UserId, '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();
|
||||
|
||||
const gatewayOpts: GatewayOptions = {
|
||||
wallet,
|
||||
identity: org1UserId,
|
||||
discovery: { enabled: true, asLocalhost: true }, // using asLocalhost as this gateway is using a fabric network deployed locally
|
||||
};
|
||||
|
||||
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, gatewayOpts);
|
||||
|
||||
// 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.
|
||||
console.log('\n--> Submit Transaction: InitLedger, function creates the initial set of assets on the ledger');
|
||||
await contract.submitTransaction('InitLedger');
|
||||
console.log('*** Result: committed');
|
||||
|
||||
// Let's try a query type operation (function).
|
||||
// This will be sent to just one peer and the results will be shown.
|
||||
console.log('\n--> Evaluate Transaction: GetAllAssets, function returns all the current assets on the ledger');
|
||||
let result = await contract.evaluateTransaction('GetAllAssets');
|
||||
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, color, owner, size, and appraisedValue arguments');
|
||||
await contract.submitTransaction('CreateAsset', 'asset413', 'yellow', '5', 'Tom', '1300');
|
||||
console.log('*** Result: committed');
|
||||
|
||||
console.log('\n--> Evaluate Transaction: ReadAsset, function returns an asset with a given assetID');
|
||||
result = await contract.evaluateTransaction('ReadAsset', 'asset413');
|
||||
console.log(`*** Result: ${prettyJSONString(result.toString())}`);
|
||||
|
||||
console.log('\n--> Evaluate Transaction: AssetExists, function returns "true" if an asset with given assetID exist');
|
||||
result = await contract.evaluateTransaction('AssetExists', 'asset1');
|
||||
console.log(`*** Result: ${prettyJSONString(result.toString())}`);
|
||||
|
||||
console.log('\n--> Submit Transaction: UpdateAsset asset1, change the appraisedValue to 350');
|
||||
await contract.submitTransaction('UpdateAsset', 'asset1', 'blue', '5', 'Tomoko', '350');
|
||||
console.log('*** Result: committed');
|
||||
|
||||
console.log('\n--> Evaluate Transaction: ReadAsset, function returns "asset1" attributes');
|
||||
result = await contract.evaluateTransaction('ReadAsset', 'asset1');
|
||||
console.log(`*** Result: ${prettyJSONString(result.toString())}`);
|
||||
|
||||
try {
|
||||
// How about we try a transactions where the executing chaincode throws an error
|
||||
// Notice how the submitTransaction will throw an error containing the error thrown by the chaincode
|
||||
console.log('\n--> Submit Transaction: UpdateAsset asset70, asset70 does not exist and should return an error');
|
||||
await contract.submitTransaction('UpdateAsset', 'asset70', 'blue', '5', 'Tomoko', '300');
|
||||
console.log('******** FAILED to return an error');
|
||||
} catch (error) {
|
||||
console.log(`*** Successfully caught the error: \n ${error}`);
|
||||
}
|
||||
|
||||
console.log('\n--> Submit Transaction: TransferAsset asset1, transfer to new owner of Tom');
|
||||
await contract.submitTransaction('TransferAsset', 'asset1', 'Tom');
|
||||
console.log('*** Result: committed');
|
||||
|
||||
console.log('\n--> Evaluate Transaction: ReadAsset, function returns "asset1" attributes');
|
||||
result = await contract.evaluateTransaction('ReadAsset', 'asset1');
|
||||
console.log(`*** Result: ${prettyJSONString(result.toString())}`);
|
||||
} 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}`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
const { Wallets } = require('fabric-network');
|
||||
const FabricCAServices = require('fabric-ca-client');
|
||||
const path = require('path');
|
||||
const { buildCAClient, registerAndEnrollUser} = require('../../../test-application/javascript/CAUtil.js');
|
||||
const { buildCCPOrg1, buildWallet } = require('../../../test-application/javascript/AppUtil.js');
|
||||
|
||||
const mspOrg1 = 'Org1MSP';
|
||||
|
||||
|
||||
async function connectToOrg1CA(UserID) {
|
||||
console.log('\n--> Register and enrolling new user');
|
||||
const ccpOrg1 = buildCCPOrg1();
|
||||
const caOrg1Client = buildCAClient(FabricCAServices, ccpOrg1, 'ca.org1.example.com');
|
||||
|
||||
const walletPathOrg1 = path.join(__dirname, 'wallet');
|
||||
const walletOrg1 = await buildWallet(Wallets, walletPathOrg1);
|
||||
|
||||
await registerAndEnrollUser(caOrg1Client, walletOrg1, mspOrg1, UserID, 'org1.department1');
|
||||
|
||||
}
|
||||
|
||||
async function main() {
|
||||
|
||||
if (process.argv[2] === undefined ) {
|
||||
console.log('Usage: node registerEnrollUser.js userID');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const userId = process.argv[2];
|
||||
|
||||
try {
|
||||
|
||||
await connectToOrg1CA(userId);
|
||||
|
||||
} catch (error) {
|
||||
console.error(`Error in enrolling admin: ${error}`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
76
LandContract/application-typescript/src/utils/AppUtil.ts
Normal file
76
LandContract/application-typescript/src/utils/AppUtil.ts
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Copyright IBM Corp. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { Wallet, Wallets } from 'fabric-network';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
|
||||
const buildCCPOrg1 = (): Record<string, any> => {
|
||||
// load the common connection configuration file
|
||||
const ccpPath = path.resolve(__dirname, '..', '..', '..', '..', 'test-network',
|
||||
'organizations', 'peerOrganizations', 'org1.example.com', 'connection-org1.json');
|
||||
const fileExists = fs.existsSync(ccpPath);
|
||||
if (!fileExists) {
|
||||
throw new Error(`no such file or directory: ${ccpPath}`);
|
||||
}
|
||||
const contents = fs.readFileSync(ccpPath, 'utf8');
|
||||
|
||||
// build a JSON object from the file contents
|
||||
const ccp = JSON.parse(contents);
|
||||
|
||||
console.log(`Loaded the network configuration located at ${ccpPath}`);
|
||||
return ccp;
|
||||
};
|
||||
|
||||
const buildCCPOrg2 = (): Record<string, any> => {
|
||||
// load the common connection configuration file
|
||||
const ccpPath = path.resolve(__dirname, '..', '..', '..', '..', 'test-network',
|
||||
'organizations', 'peerOrganizations', 'org2.example.com', 'connection-org2.json');
|
||||
const fileExists = fs.existsSync(ccpPath);
|
||||
if (!fileExists) {
|
||||
throw new Error(`no such file or directory: ${ccpPath}`);
|
||||
}
|
||||
const contents = fs.readFileSync(ccpPath, 'utf8');
|
||||
|
||||
// build a JSON object from the file contents
|
||||
const ccp = JSON.parse(contents);
|
||||
|
||||
console.log(`Loaded the network configuration located at ${ccpPath}`);
|
||||
return ccp;
|
||||
};
|
||||
|
||||
const buildWallet = async (walletPath: string): Promise<Wallet> => {
|
||||
// Create a new wallet : Note that wallet is for managing identities.
|
||||
let wallet: Wallet;
|
||||
if (walletPath) {
|
||||
|
||||
// remove any pre-existing wallet from prior runs
|
||||
fs.rmSync(walletPath, { recursive: true, force: true });
|
||||
|
||||
wallet = await Wallets.newFileSystemWallet(walletPath);
|
||||
console.log(`Built a file system wallet at ${walletPath}`);
|
||||
} else {
|
||||
wallet = await Wallets.newInMemoryWallet();
|
||||
console.log('Built an in memory wallet');
|
||||
}
|
||||
|
||||
return wallet;
|
||||
};
|
||||
|
||||
const prettyJSONString = (inputString: string): string => {
|
||||
if (inputString) {
|
||||
return JSON.stringify(JSON.parse(inputString), null, 2);
|
||||
} else {
|
||||
return inputString;
|
||||
}
|
||||
};
|
||||
|
||||
export {
|
||||
buildCCPOrg1,
|
||||
buildCCPOrg2,
|
||||
buildWallet,
|
||||
prettyJSONString,
|
||||
};
|
||||
119
LandContract/application-typescript/src/utils/CAUtil.ts
Normal file
119
LandContract/application-typescript/src/utils/CAUtil.ts
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* Copyright IBM Corp. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import FabricCAServices from 'fabric-ca-client';
|
||||
import { Wallet } from 'fabric-network';
|
||||
|
||||
const adminUserId = 'admin';
|
||||
const adminUserPasswd = 'adminpw';
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {*} ccp
|
||||
*/
|
||||
const buildCAClient = (ccp: Record<string, any>, caHostName: string): FabricCAServices => {
|
||||
// Create a new CA client for interacting with the CA.
|
||||
const caInfo = ccp.certificateAuthorities[caHostName]; // lookup CA details from config
|
||||
const caTLSCACerts = caInfo.tlsCACerts.pem;
|
||||
const caClient = new FabricCAServices(caInfo.url, { trustedRoots: caTLSCACerts, verify: false }, caInfo.caName);
|
||||
|
||||
console.log(`Built a CA Client named ${caInfo.caName}`);
|
||||
return caClient;
|
||||
};
|
||||
|
||||
const enrollAdmin = async (caClient: FabricCAServices, wallet: Wallet, orgMspId: string): Promise<void> => {
|
||||
try {
|
||||
// Check to see if we've already enrolled the admin user.
|
||||
const identity = await wallet.get(adminUserId);
|
||||
if (identity) {
|
||||
console.log('An identity for the admin user already exists in the wallet');
|
||||
return;
|
||||
}
|
||||
|
||||
// Enroll the admin user, and import the new identity into the wallet.
|
||||
const enrollment = await caClient.enroll({ enrollmentID: adminUserId, enrollmentSecret: adminUserPasswd });
|
||||
const x509Identity = {
|
||||
credentials: {
|
||||
certificate: enrollment.certificate,
|
||||
privateKey: enrollment.key.toBytes(),
|
||||
},
|
||||
mspId: orgMspId,
|
||||
type: 'X.509',
|
||||
};
|
||||
await wallet.put(adminUserId, x509Identity);
|
||||
console.log('Successfully enrolled admin user and imported it into the wallet');
|
||||
} catch (error) {
|
||||
console.error(`Failed to enroll admin user : ${error}`);
|
||||
}
|
||||
};
|
||||
|
||||
const registerAndEnrollUser = async (caClient: FabricCAServices, wallet: Wallet, orgMspId: string, userId: string, affiliation: string): Promise<void> => {
|
||||
try {
|
||||
// Check to see if we've already enrolled the user
|
||||
const userIdentity = await wallet.get(userId);
|
||||
if (userIdentity) {
|
||||
console.log(`An identity for the user ${userId} already exists in the wallet`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Must use an admin to register a new user
|
||||
const adminIdentity = await wallet.get(adminUserId);
|
||||
if (!adminIdentity) {
|
||||
console.log('An identity for the admin user does not exist in the wallet');
|
||||
console.log('Enroll the admin user before retrying');
|
||||
return;
|
||||
}
|
||||
|
||||
// build a user object for authenticating with the CA
|
||||
const provider = wallet.getProviderRegistry().getProvider(adminIdentity.type);
|
||||
const adminUser = await provider.getUserContext(adminIdentity, adminUserId);
|
||||
|
||||
// Register the user, enroll the user, and import the new identity into the wallet.
|
||||
// if affiliation is specified by client, the affiliation value must be configured in CA
|
||||
const secret = await caClient.register({
|
||||
affiliation,
|
||||
enrollmentID: userId,
|
||||
role: 'client',
|
||||
}, adminUser);
|
||||
const enrollment = await caClient.enroll({
|
||||
enrollmentID: userId,
|
||||
enrollmentSecret: secret,
|
||||
});
|
||||
const x509Identity = {
|
||||
credentials: {
|
||||
certificate: enrollment.certificate,
|
||||
privateKey: enrollment.key.toBytes(),
|
||||
},
|
||||
mspId: orgMspId,
|
||||
type: 'X.509',
|
||||
};
|
||||
await wallet.put(userId, x509Identity);
|
||||
console.log(`Successfully registered and enrolled user ${userId} and imported it into the wallet`);
|
||||
} catch (error) {
|
||||
console.error(`Failed to register user : ${error}`);
|
||||
}
|
||||
};
|
||||
|
||||
const ClearWallet = async (wallet:Wallet) => {
|
||||
try{
|
||||
const list = await wallet.list();
|
||||
console.log(list)
|
||||
for(const item in list){
|
||||
await wallet.remove(list[item]);
|
||||
}
|
||||
|
||||
console.log(`cleared the wallet`);
|
||||
} catch (error) {
|
||||
console.error(`Failed to clear : ${error}`);
|
||||
}
|
||||
};
|
||||
|
||||
export {
|
||||
buildCAClient,
|
||||
enrollAdmin,
|
||||
registerAndEnrollUser,
|
||||
ClearWallet,
|
||||
};
|
||||
15
LandContract/application-typescript/tsconfig.json
Normal file
15
LandContract/application-typescript/tsconfig.json
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"extends": "@tsconfig/node14/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"declaration": true,
|
||||
"sourceMap": true,
|
||||
},
|
||||
"include": [
|
||||
"./src/**/*"
|
||||
],
|
||||
"exclude": [
|
||||
"./src/**/*.spec.ts"
|
||||
]
|
||||
}
|
||||
23
LandContract/application-typescript/tslint.json
Normal file
23
LandContract/application-typescript/tslint.json
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"defaultSeverity": "error",
|
||||
"extends": [
|
||||
"tslint:recommended"
|
||||
],
|
||||
"jsRules": {},
|
||||
"rules": {
|
||||
"indent": [true, "spaces", 4],
|
||||
"linebreak-style": [true, "LF"],
|
||||
"quotemark": [true, "single"],
|
||||
"semicolon": [true, "always"],
|
||||
"no-console": false,
|
||||
"curly": true,
|
||||
"triple-equals": true,
|
||||
"no-string-throw": true,
|
||||
"no-var-keyword": true,
|
||||
"no-trailing-whitespace": true,
|
||||
"object-literal-key-quotes": [true, "as-needed"],
|
||||
"object-literal-sort-keys": false,
|
||||
"max-line-length": false
|
||||
},
|
||||
"rulesDirectory": []
|
||||
}
|
||||
36
chaincode-typescript/Dockerfile
Normal file
36
chaincode-typescript/Dockerfile
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
FROM node:16 AS builder
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
# Copy node.js source and build, changing owner as well
|
||||
COPY --chown=node:node . /usr/src/app
|
||||
ENV npm_config_cache=/usr/src/app
|
||||
RUN npm ci && npm run package
|
||||
|
||||
|
||||
FROM node:16 AS production
|
||||
ARG CC_SERVER_PORT
|
||||
|
||||
# Setup tini to work better handle signals
|
||||
ENV TINI_VERSION v0.19.0
|
||||
ENV PLATFORM=amd64
|
||||
ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini-${PLATFORM} /tini
|
||||
RUN chmod +x /tini
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
COPY --chown=node:node --from=builder /usr/src/app/dist ./dist
|
||||
COPY --chown=node:node --from=builder /usr/src/app/package.json ./
|
||||
COPY --chown=node:node --from=builder /usr/src/app/npm-shrinkwrap.json ./
|
||||
COPY --chown=node:node docker/docker-entrypoint.sh /usr/src/app/docker-entrypoint.sh
|
||||
|
||||
RUN npm ci --omit=dev && npm cache clean --force
|
||||
|
||||
ENV PORT $CC_SERVER_PORT
|
||||
EXPOSE $CC_SERVER_PORT
|
||||
ENV NODE_ENV=production
|
||||
|
||||
USER node
|
||||
ENTRYPOINT [ "/tini", "--", "/usr/src/app/docker-entrypoint.sh" ]
|
||||
6
chaincode-typescript/dist/Contract/landAsset.d.ts
vendored
Normal file
6
chaincode-typescript/dist/Contract/landAsset.d.ts
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
export declare class Asset {
|
||||
ID: string;
|
||||
Size: number;
|
||||
Owner: string;
|
||||
TimeStamp: number;
|
||||
}
|
||||
36
chaincode-typescript/dist/Contract/landAsset.js
vendored
Normal file
36
chaincode-typescript/dist/Contract/landAsset.js
vendored
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
"use strict";
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Asset = void 0;
|
||||
const fabric_contract_api_1 = require("fabric-contract-api");
|
||||
let Asset = class Asset {
|
||||
};
|
||||
__decorate([
|
||||
(0, fabric_contract_api_1.Property)(),
|
||||
__metadata("design:type", String)
|
||||
], Asset.prototype, "ID", void 0);
|
||||
__decorate([
|
||||
(0, fabric_contract_api_1.Property)(),
|
||||
__metadata("design:type", Number)
|
||||
], Asset.prototype, "Size", void 0);
|
||||
__decorate([
|
||||
(0, fabric_contract_api_1.Property)(),
|
||||
__metadata("design:type", String)
|
||||
], Asset.prototype, "Owner", void 0);
|
||||
__decorate([
|
||||
(0, fabric_contract_api_1.Property)(),
|
||||
__metadata("design:type", Number)
|
||||
], Asset.prototype, "TimeStamp", void 0);
|
||||
Asset = __decorate([
|
||||
(0, fabric_contract_api_1.Object)()
|
||||
], Asset);
|
||||
exports.Asset = Asset;
|
||||
//# sourceMappingURL=landAsset.js.map
|
||||
1
chaincode-typescript/dist/Contract/landAsset.js.map
vendored
Normal file
1
chaincode-typescript/dist/Contract/landAsset.js.map
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"landAsset.js","sourceRoot":"","sources":["../../src/Contract/landAsset.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,6DAAqD;AAG9C,IAAM,KAAK,GAAX,MAAM,KAAK;CAYjB,CAAA;AAXG;IAAC,IAAA,8BAAQ,GAAE;;iCACO;AAElB;IAAC,IAAA,8BAAQ,GAAE;;mCACS;AAEpB;IAAC,IAAA,8BAAQ,GAAE;;oCACU;AAErB;IAAC,IAAA,8BAAQ,GAAE;;wCACc;AAXhB,KAAK;IADjB,IAAA,4BAAM,GAAE;GACI,KAAK,CAYjB;AAZY,sBAAK"}
|
||||
11
chaincode-typescript/dist/Contract/landTransaction.d.ts
vendored
Normal file
11
chaincode-typescript/dist/Contract/landTransaction.d.ts
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
import { Context, Contract } from 'fabric-contract-api';
|
||||
export declare class LandTransferContract extends Contract {
|
||||
InitLedger(ctx: Context): Promise<void>;
|
||||
private CreateAsset;
|
||||
private DeleteAsset;
|
||||
TransferAsset(ctx: Context, id: string, newOwner: string): Promise<string>;
|
||||
SplitAsset(ctx: Context, id: string, newOwner: string, transfer: string): Promise<string>;
|
||||
ReadAsset(ctx: Context, id: string): Promise<string>;
|
||||
AssetExists(ctx: Context, id: string): Promise<boolean>;
|
||||
GetAllAssets(ctx: Context): Promise<string>;
|
||||
}
|
||||
171
chaincode-typescript/dist/Contract/landTransaction.js
vendored
Normal file
171
chaincode-typescript/dist/Contract/landTransaction.js
vendored
Normal file
|
|
@ -0,0 +1,171 @@
|
|||
"use strict";
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.LandTransferContract = void 0;
|
||||
const fabric_contract_api_1 = require("fabric-contract-api");
|
||||
const json_stringify_deterministic_1 = __importDefault(require("json-stringify-deterministic"));
|
||||
const sort_keys_recursive_1 = __importDefault(require("sort-keys-recursive"));
|
||||
22224;
|
||||
let LandTransferContract = class LandTransferContract extends fabric_contract_api_1.Contract {
|
||||
async InitLedger(ctx) {
|
||||
const assets = [
|
||||
{
|
||||
ID: "0",
|
||||
Size: 10000,
|
||||
Owner: "Government",
|
||||
TimeStamp: Date.now()
|
||||
}
|
||||
];
|
||||
for (const asset of assets) {
|
||||
await ctx.stub.putState(asset.ID, Buffer.from((0, json_stringify_deterministic_1.default)((0, sort_keys_recursive_1.default)(asset))));
|
||||
console.info(`Asset ${asset.ID} initialized`);
|
||||
}
|
||||
}
|
||||
async CreateAsset(ctx, id, size, owner) {
|
||||
const exists = await this.AssetExists(ctx, id);
|
||||
if (exists) {
|
||||
throw new Error(`The asset ${id} already exists`);
|
||||
}
|
||||
const asset = {
|
||||
ID: id,
|
||||
Size: size,
|
||||
Owner: owner,
|
||||
TimeStamp: Date.now()
|
||||
};
|
||||
await ctx.stub.putState(id, Buffer.from((0, json_stringify_deterministic_1.default)((0, sort_keys_recursive_1.default)(asset))));
|
||||
}
|
||||
async DeleteAsset(ctx, id) {
|
||||
const exists = await this.AssetExists(ctx, id);
|
||||
if (!exists) {
|
||||
throw new Error(`The asset ${id} does not exist`);
|
||||
}
|
||||
return ctx.stub.deleteState(id);
|
||||
}
|
||||
async TransferAsset(ctx, id, newOwner) {
|
||||
const assetString = await this.ReadAsset(ctx, id);
|
||||
const asset = JSON.parse(assetString);
|
||||
const oldOwner = asset.Owner;
|
||||
asset.Owner = newOwner;
|
||||
// we insert data in alphabetic order using 'json-stringify-deterministic' and 'sort-keys-recursive'
|
||||
await ctx.stub.putState(id, Buffer.from((0, json_stringify_deterministic_1.default)((0, sort_keys_recursive_1.default)(asset))));
|
||||
return oldOwner;
|
||||
}
|
||||
async SplitAsset(ctx, id, newOwner, transfer) {
|
||||
const transferSize = parseInt(transfer);
|
||||
const assetString = await this.ReadAsset(ctx, id);
|
||||
const asset = JSON.parse(assetString);
|
||||
if (asset.Size < transferSize) {
|
||||
throw new Error(`Cannot transfer more than the user owns`);
|
||||
}
|
||||
const oldOwner = asset.Owner;
|
||||
try {
|
||||
await this.DeleteAsset(ctx, id);
|
||||
}
|
||||
catch (error) {
|
||||
throw error;
|
||||
}
|
||||
if (asset.Size > transferSize)
|
||||
await this.CreateAsset(ctx, id + "0", asset.Size - transferSize, oldOwner);
|
||||
await this.CreateAsset(ctx, id + "1", transferSize, newOwner);
|
||||
// we insert data in alphabetic order using 'json-stringify-deterministic' and 'sort-keys-recursive'
|
||||
// await ctx.stub.putState(id, Buffer.from(stringify(sortKeysRecursive(asset))));
|
||||
return oldOwner;
|
||||
}
|
||||
async ReadAsset(ctx, id) {
|
||||
const assetJSON = await ctx.stub.getState(id); // get the asset from chaincode state
|
||||
if (!assetJSON || assetJSON.length === 0) {
|
||||
throw new Error(`The asset ${id} does not exist`);
|
||||
}
|
||||
return assetJSON.toString();
|
||||
}
|
||||
async AssetExists(ctx, id) {
|
||||
const assetJSON = await ctx.stub.getState(id);
|
||||
return assetJSON && assetJSON.length > 0;
|
||||
}
|
||||
async GetAllAssets(ctx) {
|
||||
const allResults = [];
|
||||
// range query with empty string for startKey and endKey does an open-ended query of all assets in the chaincode namespace.
|
||||
const iterator = await ctx.stub.getStateByRange('', '');
|
||||
let result = await iterator.next();
|
||||
while (!result.done) {
|
||||
const strValue = Buffer.from(result.value.value.toString()).toString('utf8');
|
||||
let record;
|
||||
try {
|
||||
record = JSON.parse(strValue);
|
||||
}
|
||||
catch (err) {
|
||||
console.log(err);
|
||||
record = strValue;
|
||||
}
|
||||
allResults.push(record);
|
||||
result = await iterator.next();
|
||||
}
|
||||
return JSON.stringify(allResults);
|
||||
}
|
||||
};
|
||||
__decorate([
|
||||
(0, fabric_contract_api_1.Transaction)(),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [fabric_contract_api_1.Context]),
|
||||
__metadata("design:returntype", Promise)
|
||||
], LandTransferContract.prototype, "InitLedger", null);
|
||||
__decorate([
|
||||
(0, fabric_contract_api_1.Transaction)(),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [fabric_contract_api_1.Context, String, Number, String]),
|
||||
__metadata("design:returntype", Promise)
|
||||
], LandTransferContract.prototype, "CreateAsset", null);
|
||||
__decorate([
|
||||
(0, fabric_contract_api_1.Transaction)(),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [fabric_contract_api_1.Context, String]),
|
||||
__metadata("design:returntype", Promise)
|
||||
], LandTransferContract.prototype, "DeleteAsset", null);
|
||||
__decorate([
|
||||
(0, fabric_contract_api_1.Transaction)(),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [fabric_contract_api_1.Context, String, String]),
|
||||
__metadata("design:returntype", Promise)
|
||||
], LandTransferContract.prototype, "TransferAsset", null);
|
||||
__decorate([
|
||||
(0, fabric_contract_api_1.Transaction)(),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [fabric_contract_api_1.Context, String, String, String]),
|
||||
__metadata("design:returntype", Promise)
|
||||
], LandTransferContract.prototype, "SplitAsset", null);
|
||||
__decorate([
|
||||
(0, fabric_contract_api_1.Transaction)(false),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [fabric_contract_api_1.Context, String]),
|
||||
__metadata("design:returntype", Promise)
|
||||
], LandTransferContract.prototype, "ReadAsset", null);
|
||||
__decorate([
|
||||
(0, fabric_contract_api_1.Transaction)(false),
|
||||
(0, fabric_contract_api_1.Returns)('boolean'),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [fabric_contract_api_1.Context, String]),
|
||||
__metadata("design:returntype", Promise)
|
||||
], LandTransferContract.prototype, "AssetExists", null);
|
||||
__decorate([
|
||||
(0, fabric_contract_api_1.Transaction)(false),
|
||||
(0, fabric_contract_api_1.Returns)('string'),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [fabric_contract_api_1.Context]),
|
||||
__metadata("design:returntype", Promise)
|
||||
], LandTransferContract.prototype, "GetAllAssets", null);
|
||||
LandTransferContract = __decorate([
|
||||
(0, fabric_contract_api_1.Info)({ title: 'LandTransfer', description: 'Smart contract for trading land assets' })
|
||||
], LandTransferContract);
|
||||
exports.LandTransferContract = LandTransferContract;
|
||||
//# sourceMappingURL=landTransaction.js.map
|
||||
1
chaincode-typescript/dist/Contract/landTransaction.js.map
vendored
Normal file
1
chaincode-typescript/dist/Contract/landTransaction.js.map
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"landTransaction.js","sourceRoot":"","sources":["../../src/Contract/landTransaction.ts"],"names":[],"mappings":"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"}
|
||||
8
chaincode-typescript/dist/asset.d.ts
vendored
Normal file
8
chaincode-typescript/dist/asset.d.ts
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
export declare class Asset {
|
||||
docType?: string;
|
||||
ID: string;
|
||||
Color: string;
|
||||
Size: number;
|
||||
Owner: string;
|
||||
AppraisedValue: number;
|
||||
}
|
||||
47
chaincode-typescript/dist/asset.js
vendored
Normal file
47
chaincode-typescript/dist/asset.js
vendored
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
"use strict";
|
||||
/*
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Asset = void 0;
|
||||
const fabric_contract_api_1 = require("fabric-contract-api");
|
||||
let Asset = class Asset {
|
||||
};
|
||||
__decorate([
|
||||
(0, fabric_contract_api_1.Property)(),
|
||||
__metadata("design:type", String)
|
||||
], Asset.prototype, "docType", void 0);
|
||||
__decorate([
|
||||
(0, fabric_contract_api_1.Property)(),
|
||||
__metadata("design:type", String)
|
||||
], Asset.prototype, "ID", void 0);
|
||||
__decorate([
|
||||
(0, fabric_contract_api_1.Property)(),
|
||||
__metadata("design:type", String)
|
||||
], Asset.prototype, "Color", void 0);
|
||||
__decorate([
|
||||
(0, fabric_contract_api_1.Property)(),
|
||||
__metadata("design:type", Number)
|
||||
], Asset.prototype, "Size", void 0);
|
||||
__decorate([
|
||||
(0, fabric_contract_api_1.Property)(),
|
||||
__metadata("design:type", String)
|
||||
], Asset.prototype, "Owner", void 0);
|
||||
__decorate([
|
||||
(0, fabric_contract_api_1.Property)(),
|
||||
__metadata("design:type", Number)
|
||||
], Asset.prototype, "AppraisedValue", void 0);
|
||||
Asset = __decorate([
|
||||
(0, fabric_contract_api_1.Object)()
|
||||
], Asset);
|
||||
exports.Asset = Asset;
|
||||
//# sourceMappingURL=asset.js.map
|
||||
1
chaincode-typescript/dist/asset.js.map
vendored
Normal file
1
chaincode-typescript/dist/asset.js.map
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"asset.js","sourceRoot":"","sources":["../src/asset.ts"],"names":[],"mappings":";AAAA;;EAEE;;;;;;;;;;;;AAEF,6DAAqD;AAG9C,IAAM,KAAK,GAAX,MAAM,KAAK;CAkBjB,CAAA;AAjBG;IAAC,IAAA,8BAAQ,GAAE;;sCACa;AAExB;IAAC,IAAA,8BAAQ,GAAE;;iCACO;AAElB;IAAC,IAAA,8BAAQ,GAAE;;oCACU;AAErB;IAAC,IAAA,8BAAQ,GAAE;;mCACS;AAEpB;IAAC,IAAA,8BAAQ,GAAE;;oCACU;AAErB;IAAC,IAAA,8BAAQ,GAAE;;6CACmB;AAjBrB,KAAK;IADjB,IAAA,4BAAM,GAAE;GACI,KAAK,CAkBjB;AAlBY,sBAAK"}
|
||||
11
chaincode-typescript/dist/assetTransfer.d.ts
vendored
Normal file
11
chaincode-typescript/dist/assetTransfer.d.ts
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
import { Context, Contract } from 'fabric-contract-api';
|
||||
export declare class AssetTransferContract extends Contract {
|
||||
InitLedger(ctx: Context): Promise<void>;
|
||||
CreateAsset(ctx: Context, id: string, color: string, size: number, owner: string, appraisedValue: number): Promise<void>;
|
||||
ReadAsset(ctx: Context, id: string): Promise<string>;
|
||||
UpdateAsset(ctx: Context, id: string, color: string, size: number, owner: string, appraisedValue: number): Promise<void>;
|
||||
DeleteAsset(ctx: Context, id: string): Promise<void>;
|
||||
AssetExists(ctx: Context, id: string): Promise<boolean>;
|
||||
TransferAsset(ctx: Context, id: string, newOwner: string): Promise<string>;
|
||||
GetAllAssets(ctx: Context): Promise<string>;
|
||||
}
|
||||
219
chaincode-typescript/dist/assetTransfer.js
vendored
Normal file
219
chaincode-typescript/dist/assetTransfer.js
vendored
Normal file
|
|
@ -0,0 +1,219 @@
|
|||
"use strict";
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.AssetTransferContract = void 0;
|
||||
/*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
// Deterministic JSON.stringify()
|
||||
const fabric_contract_api_1 = require("fabric-contract-api");
|
||||
const json_stringify_deterministic_1 = __importDefault(require("json-stringify-deterministic"));
|
||||
const sort_keys_recursive_1 = __importDefault(require("sort-keys-recursive"));
|
||||
let AssetTransferContract = class AssetTransferContract extends fabric_contract_api_1.Contract {
|
||||
async InitLedger(ctx) {
|
||||
const assets = [
|
||||
{
|
||||
ID: 'asset1',
|
||||
Color: 'blue',
|
||||
Size: 5,
|
||||
Owner: 'Tomoko',
|
||||
AppraisedValue: 300,
|
||||
},
|
||||
{
|
||||
ID: 'asset2',
|
||||
Color: 'red',
|
||||
Size: 5,
|
||||
Owner: 'Brad',
|
||||
AppraisedValue: 400,
|
||||
},
|
||||
{
|
||||
ID: 'asset3',
|
||||
Color: 'green',
|
||||
Size: 10,
|
||||
Owner: 'Jin Soo',
|
||||
AppraisedValue: 500,
|
||||
},
|
||||
{
|
||||
ID: 'asset4',
|
||||
Color: 'yellow',
|
||||
Size: 10,
|
||||
Owner: 'Max',
|
||||
AppraisedValue: 600,
|
||||
},
|
||||
{
|
||||
ID: 'asset5',
|
||||
Color: 'black',
|
||||
Size: 15,
|
||||
Owner: 'Adriana',
|
||||
AppraisedValue: 700,
|
||||
},
|
||||
{
|
||||
ID: 'asset6',
|
||||
Color: 'white',
|
||||
Size: 15,
|
||||
Owner: 'Michel',
|
||||
AppraisedValue: 800,
|
||||
},
|
||||
];
|
||||
for (const asset of assets) {
|
||||
asset.docType = 'asset';
|
||||
// example of how to write to world state deterministically
|
||||
// use convetion of alphabetic order
|
||||
// we insert data in alphabetic order using 'json-stringify-deterministic' and 'sort-keys-recursive'
|
||||
// when retrieving data, in any lang, the order of data will be the same and consequently also the corresonding hash
|
||||
await ctx.stub.putState(asset.ID, Buffer.from((0, json_stringify_deterministic_1.default)((0, sort_keys_recursive_1.default)(asset))));
|
||||
console.info(`Asset ${asset.ID} initialized`);
|
||||
}
|
||||
}
|
||||
// CreateAsset issues a new asset to the world state with given details.
|
||||
async CreateAsset(ctx, id, color, size, owner, appraisedValue) {
|
||||
const exists = await this.AssetExists(ctx, id);
|
||||
if (exists) {
|
||||
throw new Error(`The asset ${id} already exists`);
|
||||
}
|
||||
const asset = {
|
||||
ID: id,
|
||||
Color: color,
|
||||
Size: size,
|
||||
Owner: owner,
|
||||
AppraisedValue: appraisedValue,
|
||||
};
|
||||
// we insert data in alphabetic order using 'json-stringify-deterministic' and 'sort-keys-recursive'
|
||||
await ctx.stub.putState(id, Buffer.from((0, json_stringify_deterministic_1.default)((0, sort_keys_recursive_1.default)(asset))));
|
||||
}
|
||||
// ReadAsset returns the asset stored in the world state with given id.
|
||||
async ReadAsset(ctx, id) {
|
||||
const assetJSON = await ctx.stub.getState(id); // get the asset from chaincode state
|
||||
if (!assetJSON || assetJSON.length === 0) {
|
||||
throw new Error(`The asset ${id} does not exist`);
|
||||
}
|
||||
return assetJSON.toString();
|
||||
}
|
||||
// UpdateAsset updates an existing asset in the world state with provided parameters.
|
||||
async UpdateAsset(ctx, id, color, size, owner, appraisedValue) {
|
||||
const exists = await this.AssetExists(ctx, id);
|
||||
if (!exists) {
|
||||
throw new Error(`The asset ${id} does not exist`);
|
||||
}
|
||||
// overwriting original asset with new asset
|
||||
const updatedAsset = {
|
||||
ID: id,
|
||||
Color: color,
|
||||
Size: size,
|
||||
Owner: owner,
|
||||
AppraisedValue: appraisedValue,
|
||||
};
|
||||
// we insert data in alphabetic order using 'json-stringify-deterministic' and 'sort-keys-recursive'
|
||||
return ctx.stub.putState(id, Buffer.from((0, json_stringify_deterministic_1.default)((0, sort_keys_recursive_1.default)(updatedAsset))));
|
||||
}
|
||||
// DeleteAsset deletes an given asset from the world state.
|
||||
async DeleteAsset(ctx, id) {
|
||||
const exists = await this.AssetExists(ctx, id);
|
||||
if (!exists) {
|
||||
throw new Error(`The asset ${id} does not exist`);
|
||||
}
|
||||
return ctx.stub.deleteState(id);
|
||||
}
|
||||
// AssetExists returns true when asset with given ID exists in world state.
|
||||
async AssetExists(ctx, id) {
|
||||
const assetJSON = await ctx.stub.getState(id);
|
||||
return assetJSON && assetJSON.length > 0;
|
||||
}
|
||||
// TransferAsset updates the owner field of asset with given id in the world state, and returns the old owner.
|
||||
async TransferAsset(ctx, id, newOwner) {
|
||||
const assetString = await this.ReadAsset(ctx, id);
|
||||
const asset = JSON.parse(assetString);
|
||||
const oldOwner = asset.Owner;
|
||||
asset.Owner = newOwner;
|
||||
// we insert data in alphabetic order using 'json-stringify-deterministic' and 'sort-keys-recursive'
|
||||
await ctx.stub.putState(id, Buffer.from((0, json_stringify_deterministic_1.default)((0, sort_keys_recursive_1.default)(asset))));
|
||||
return oldOwner;
|
||||
}
|
||||
// GetAllAssets returns all assets found in the world state.
|
||||
async GetAllAssets(ctx) {
|
||||
const allResults = [];
|
||||
// range query with empty string for startKey and endKey does an open-ended query of all assets in the chaincode namespace.
|
||||
const iterator = await ctx.stub.getStateByRange('', '');
|
||||
let result = await iterator.next();
|
||||
while (!result.done) {
|
||||
const strValue = Buffer.from(result.value.value.toString()).toString('utf8');
|
||||
let record;
|
||||
try {
|
||||
record = JSON.parse(strValue);
|
||||
}
|
||||
catch (err) {
|
||||
console.log(err);
|
||||
record = strValue;
|
||||
}
|
||||
allResults.push(record);
|
||||
result = await iterator.next();
|
||||
}
|
||||
return JSON.stringify(allResults);
|
||||
}
|
||||
};
|
||||
__decorate([
|
||||
(0, fabric_contract_api_1.Transaction)(),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [fabric_contract_api_1.Context]),
|
||||
__metadata("design:returntype", Promise)
|
||||
], AssetTransferContract.prototype, "InitLedger", null);
|
||||
__decorate([
|
||||
(0, fabric_contract_api_1.Transaction)(),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [fabric_contract_api_1.Context, String, String, Number, String, Number]),
|
||||
__metadata("design:returntype", Promise)
|
||||
], AssetTransferContract.prototype, "CreateAsset", null);
|
||||
__decorate([
|
||||
(0, fabric_contract_api_1.Transaction)(false),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [fabric_contract_api_1.Context, String]),
|
||||
__metadata("design:returntype", Promise)
|
||||
], AssetTransferContract.prototype, "ReadAsset", null);
|
||||
__decorate([
|
||||
(0, fabric_contract_api_1.Transaction)(),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [fabric_contract_api_1.Context, String, String, Number, String, Number]),
|
||||
__metadata("design:returntype", Promise)
|
||||
], AssetTransferContract.prototype, "UpdateAsset", null);
|
||||
__decorate([
|
||||
(0, fabric_contract_api_1.Transaction)(),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [fabric_contract_api_1.Context, String]),
|
||||
__metadata("design:returntype", Promise)
|
||||
], AssetTransferContract.prototype, "DeleteAsset", null);
|
||||
__decorate([
|
||||
(0, fabric_contract_api_1.Transaction)(false),
|
||||
(0, fabric_contract_api_1.Returns)('boolean'),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [fabric_contract_api_1.Context, String]),
|
||||
__metadata("design:returntype", Promise)
|
||||
], AssetTransferContract.prototype, "AssetExists", null);
|
||||
__decorate([
|
||||
(0, fabric_contract_api_1.Transaction)(),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [fabric_contract_api_1.Context, String, String]),
|
||||
__metadata("design:returntype", Promise)
|
||||
], AssetTransferContract.prototype, "TransferAsset", null);
|
||||
__decorate([
|
||||
(0, fabric_contract_api_1.Transaction)(false),
|
||||
(0, fabric_contract_api_1.Returns)('string'),
|
||||
__metadata("design:type", Function),
|
||||
__metadata("design:paramtypes", [fabric_contract_api_1.Context]),
|
||||
__metadata("design:returntype", Promise)
|
||||
], AssetTransferContract.prototype, "GetAllAssets", null);
|
||||
AssetTransferContract = __decorate([
|
||||
(0, fabric_contract_api_1.Info)({ title: 'AssetTransfer', description: 'Smart contract for trading assets' })
|
||||
], AssetTransferContract);
|
||||
exports.AssetTransferContract = AssetTransferContract;
|
||||
//# sourceMappingURL=assetTransfer.js.map
|
||||
1
chaincode-typescript/dist/assetTransfer.js.map
vendored
Normal file
1
chaincode-typescript/dist/assetTransfer.js.map
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"assetTransfer.js","sourceRoot":"","sources":["../src/assetTransfer.ts"],"names":[],"mappings":"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"}
|
||||
2
chaincode-typescript/dist/index.d.ts
vendored
Normal file
2
chaincode-typescript/dist/index.d.ts
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
export { LandTransferContract } from './Contract/landTransaction';
|
||||
export declare const contracts: any[];
|
||||
14
chaincode-typescript/dist/index.js
vendored
Normal file
14
chaincode-typescript/dist/index.js
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
"use strict";
|
||||
// /*
|
||||
// * SPDX-License-Identifier: Apache-2.0
|
||||
// */
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.contracts = exports.LandTransferContract = void 0;
|
||||
// import {AssetTransferContract} from './assetTransfer';
|
||||
// export {AssetTransferContract} from './assetTransfer';
|
||||
// export const contracts: any[] = [AssetTransferContract];
|
||||
const landTransaction_1 = require("./Contract/landTransaction");
|
||||
var landTransaction_2 = require("./Contract/landTransaction");
|
||||
Object.defineProperty(exports, "LandTransferContract", { enumerable: true, get: function () { return landTransaction_2.LandTransferContract; } });
|
||||
exports.contracts = [landTransaction_1.LandTransferContract];
|
||||
//# sourceMappingURL=index.js.map
|
||||
1
chaincode-typescript/dist/index.js.map
vendored
Normal file
1
chaincode-typescript/dist/index.js.map
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,KAAK;AACL,yCAAyC;AACzC,MAAM;;;AAEN,yDAAyD;AAEzD,yDAAyD;AAEzD,2DAA2D;AAE3D,gEAAgE;AAEhE,8DAAgE;AAAxD,uHAAA,oBAAoB,OAAA;AAEf,QAAA,SAAS,GAAU,CAAC,sCAAoB,CAAC,CAAC"}
|
||||
16
chaincode-typescript/docker/docker-entrypoint.sh
Executable file
16
chaincode-typescript/docker/docker-entrypoint.sh
Executable file
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env bash
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
set -euo pipefail
|
||||
: ${CORE_PEER_TLS_ENABLED:="false"}
|
||||
: ${DEBUG:="false"}
|
||||
|
||||
if [ "${DEBUG,,}" = "true" ]; then
|
||||
npm run start:server-debug
|
||||
elif [ "${CORE_PEER_TLS_ENABLED,,}" = "true" ]; then
|
||||
npm run start:server
|
||||
else
|
||||
npm run start:server-nontls
|
||||
fi
|
||||
|
||||
4410
chaincode-typescript/npm-shrinkwrap.json
generated
Normal file
4410
chaincode-typescript/npm-shrinkwrap.json
generated
Normal file
File diff suppressed because it is too large
Load diff
71
chaincode-typescript/package.json
Normal file
71
chaincode-typescript/package.json
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
{
|
||||
"name": "asset-transfer-basic",
|
||||
"version": "1.0.0",
|
||||
"description": "Asset Transfer Basic contract implemented in TypeScript",
|
||||
"main": "dist/index.js",
|
||||
"typings": "dist/index.d.ts",
|
||||
"engines": {
|
||||
"node": ">=12",
|
||||
"npm": ">=5"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "tslint -c tslint.json 'src/**/*.ts'",
|
||||
"pretest": "npm run lint",
|
||||
"test": "nyc mocha -r ts-node/register src/**/*.spec.ts",
|
||||
"start": "set -x && fabric-chaincode-node start",
|
||||
"build": "tsc",
|
||||
"build:watch": "tsc -w",
|
||||
"prepublishOnly": "npm run build",
|
||||
"docker": "docker build -f ./Dockerfile -t asset-transfer-basic .",
|
||||
"package": "npm run build && npm shrinkwrap",
|
||||
"start:server-nontls": "set -x && fabric-chaincode-node server --chaincode-address=$CHAINCODE_SERVER_ADDRESS --chaincode-id=$CHAINCODE_ID",
|
||||
"start:server-debug": "set -x && NODE_OPTIONS='--inspect=0.0.0.0:9229' fabric-chaincode-node server --chaincode-address=$CHAINCODE_SERVER_ADDRESS --chaincode-id=$CHAINCODE_ID",
|
||||
"start:server": "set -x && fabric-chaincode-node server --chaincode-address=$CHAINCODE_SERVER_ADDRESS --chaincode-id=$CHAINCODE_ID --chaincode-tls-key-file=/hyperledger/privatekey.pem --chaincode-tls-client-cacert-file=/hyperledger/rootcert.pem --chaincode-tls-cert-file=/hyperledger/cert.pem"
|
||||
},
|
||||
"engineStrict": true,
|
||||
"author": "Hyperledger",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"fabric-ca-client": "^2.2.19",
|
||||
"fabric-contract-api": "^2.4.0",
|
||||
"fabric-network": "^2.2.19",
|
||||
"fabric-shim": "^2.4.0",
|
||||
"json-stringify-deterministic": "^1.0.1",
|
||||
"sort-keys-recursive": "^2.1.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/chai": "^4.1.7",
|
||||
"@types/mocha": "^5.2.5",
|
||||
"@types/node": "^12.20.55",
|
||||
"@types/sinon": "^5.0.7",
|
||||
"@types/sinon-chai": "^3.2.1",
|
||||
"chai": "^4.2.0",
|
||||
"mocha": "^10.0.0",
|
||||
"nyc": "^14.1.1",
|
||||
"sinon": "^7.1.1",
|
||||
"sinon-chai": "^3.3.0",
|
||||
"ts-node": "^7.0.1",
|
||||
"tslint": "^5.11.0",
|
||||
"typescript": "^4.4"
|
||||
},
|
||||
"nyc": {
|
||||
"extension": [
|
||||
".ts",
|
||||
".tsx"
|
||||
],
|
||||
"exclude": [
|
||||
"coverage/**",
|
||||
"dist/**"
|
||||
],
|
||||
"reporter": [
|
||||
"text-summary",
|
||||
"html"
|
||||
],
|
||||
"all": true,
|
||||
"check-coverage": true,
|
||||
"statements": 100,
|
||||
"branches": 100,
|
||||
"functions": 100,
|
||||
"lines": 100
|
||||
}
|
||||
}
|
||||
47
chaincode-typescript/src/Contract/Admin.js
Normal file
47
chaincode-typescript/src/Contract/Admin.js
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
const { Wallets } = require('fabric-network');
|
||||
const FabricCAServices = require('fabric-ca-client');
|
||||
const path = require('path');
|
||||
const { buildCAClient, enrollAdmin, ClearWallet } = require('../../../test-application/javascript/CAUtil.js');
|
||||
const { buildCCPOrg1, buildWallet } = require('../../../test-application/javascript/AppUtil.js');
|
||||
|
||||
const mspOrg1 = 'Org1MSP';
|
||||
|
||||
async function enrollAdmmin() {
|
||||
console.log('\n--> Enrolling the Org1 CA admin');
|
||||
const ccpOrg1 = buildCCPOrg1();
|
||||
const caOrg1Client = buildCAClient(FabricCAServices, ccpOrg1, 'ca.org1.example.com');
|
||||
|
||||
const walletPathOrg1 = path.join(__dirname, 'wallet');
|
||||
const walletOrg1 = await buildWallet(Wallets, walletPathOrg1);
|
||||
|
||||
await enrollAdmin(caOrg1Client, walletOrg1, mspOrg1);
|
||||
}
|
||||
|
||||
async function clearWallet(){
|
||||
const walletPath = path.join(__dirname, 'wallet');
|
||||
const wallet = await buildWallet(Wallets, walletPath);
|
||||
|
||||
await ClearWallet(wallet);
|
||||
}
|
||||
|
||||
async function main() {
|
||||
cmd = "create";
|
||||
if (!(process.argv[2] === undefined)) {
|
||||
cmd = process.argv[2];
|
||||
}
|
||||
|
||||
try {
|
||||
if(cmd=="clear"){
|
||||
await clearWallet();
|
||||
}else if(cmd=="create"){
|
||||
await enrollAdmmin();
|
||||
}else{
|
||||
throw Error(cmd + " is not defined. (create / clean)")
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Error in admin: ${error}`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
16
chaincode-typescript/src/Contract/landAsset.ts
Normal file
16
chaincode-typescript/src/Contract/landAsset.ts
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
import {Object, Property} from 'fabric-contract-api';
|
||||
|
||||
@Object()
|
||||
export class Asset {
|
||||
@Property()
|
||||
public ID: string;
|
||||
|
||||
@Property()
|
||||
public Size: number;
|
||||
|
||||
@Property()
|
||||
public Owner: string;
|
||||
|
||||
@Property()
|
||||
public TimeStamp: number;
|
||||
}
|
||||
121
chaincode-typescript/src/Contract/landTransaction.ts
Normal file
121
chaincode-typescript/src/Contract/landTransaction.ts
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
import {Context, Contract, Returns, Transaction, Info} from 'fabric-contract-api';
|
||||
import stringify from 'json-stringify-deterministic';
|
||||
import sortKeysRecursive from 'sort-keys-recursive';
|
||||
import { Asset } from './landAsset';
|
||||
|
||||
@Info({title: 'LandTransfer', description: 'Smart contract for trading land assets'})
|
||||
export class LandTransferContract extends Contract {
|
||||
|
||||
@Transaction()
|
||||
public async InitLedger(ctx: Context): Promise<void> {
|
||||
const assets: Asset[] = [
|
||||
{
|
||||
ID: "0",
|
||||
Size: 10000,
|
||||
Owner: "Government",
|
||||
TimeStamp: Date.now()
|
||||
}
|
||||
];
|
||||
|
||||
for (const asset of assets) {
|
||||
await ctx.stub.putState(asset.ID, Buffer.from(stringify(sortKeysRecursive(asset))));
|
||||
console.info(`Asset ${asset.ID} initialized`);
|
||||
}
|
||||
}
|
||||
|
||||
@Transaction()
|
||||
private async CreateAsset(ctx: Context, id:string, size: number, owner: string): Promise<void> {
|
||||
const exists = await this.AssetExists(ctx, id);
|
||||
if (exists) {
|
||||
throw new Error(`The asset ${id} already exists`);
|
||||
}
|
||||
|
||||
const asset:Asset = {
|
||||
ID: id,
|
||||
Size: size,
|
||||
Owner: owner,
|
||||
TimeStamp: Date.now()
|
||||
};
|
||||
await ctx.stub.putState(id, Buffer.from(stringify(sortKeysRecursive(asset))));
|
||||
}
|
||||
|
||||
@Transaction()
|
||||
private async DeleteAsset(ctx: Context, id: string): Promise<void> {
|
||||
const exists = await this.AssetExists(ctx, id);
|
||||
if (!exists) {
|
||||
throw new Error(`The asset ${id} does not exist`);
|
||||
}
|
||||
return ctx.stub.deleteState(id);
|
||||
}
|
||||
|
||||
@Transaction()
|
||||
public async TransferAsset(ctx: Context, id: string, newOwner: string): Promise<string> {
|
||||
const assetString = await this.ReadAsset(ctx, id);
|
||||
const asset = JSON.parse(assetString);
|
||||
const oldOwner = asset.Owner;
|
||||
asset.Owner = newOwner;
|
||||
// we insert data in alphabetic order using 'json-stringify-deterministic' and 'sort-keys-recursive'
|
||||
await ctx.stub.putState(id, Buffer.from(stringify(sortKeysRecursive(asset))));
|
||||
return oldOwner;
|
||||
}
|
||||
|
||||
@Transaction()
|
||||
public async SplitAsset(ctx: Context, id: string, newOwner: string, transfer:string): Promise<string> {
|
||||
const transferSize = parseInt(transfer);
|
||||
const assetString = await this.ReadAsset(ctx, id);
|
||||
const asset:Asset = JSON.parse(assetString);
|
||||
if(asset.Size<transferSize) {
|
||||
throw new Error(`Cannot transfer more than the user owns`);
|
||||
}
|
||||
const oldOwner = asset.Owner;
|
||||
try {
|
||||
await this.DeleteAsset(ctx, id);
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
if(asset.Size>transferSize) await this.CreateAsset(ctx, id+"0", asset.Size-transferSize, oldOwner);
|
||||
await this.CreateAsset(ctx, id+"1", transferSize, newOwner);
|
||||
// we insert data in alphabetic order using 'json-stringify-deterministic' and 'sort-keys-recursive'
|
||||
// await ctx.stub.putState(id, Buffer.from(stringify(sortKeysRecursive(asset))));
|
||||
return oldOwner;
|
||||
}
|
||||
|
||||
@Transaction(false)
|
||||
public async ReadAsset(ctx: Context, id: string): Promise<string> {
|
||||
const assetJSON = await ctx.stub.getState(id); // get the asset from chaincode state
|
||||
if (!assetJSON || assetJSON.length === 0) {
|
||||
throw new Error(`The asset ${id} does not exist`);
|
||||
}
|
||||
return assetJSON.toString();
|
||||
}
|
||||
|
||||
|
||||
@Transaction(false)
|
||||
@Returns('boolean')
|
||||
public async AssetExists(ctx: Context, id: string): Promise<boolean> {
|
||||
const assetJSON = await ctx.stub.getState(id);
|
||||
return assetJSON && assetJSON.length > 0;
|
||||
}
|
||||
|
||||
@Transaction(false)
|
||||
@Returns('string')
|
||||
public async GetAllAssets(ctx: Context): Promise<string> {
|
||||
const allResults = [];
|
||||
// range query with empty string for startKey and endKey does an open-ended query of all assets in the chaincode namespace.
|
||||
const iterator = await ctx.stub.getStateByRange('', '');
|
||||
let result = await iterator.next();
|
||||
while (!result.done) {
|
||||
const strValue = Buffer.from(result.value.value.toString()).toString('utf8');
|
||||
let record;
|
||||
try {
|
||||
record = JSON.parse(strValue);
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
record = strValue;
|
||||
}
|
||||
allResults.push(record);
|
||||
result = await iterator.next();
|
||||
}
|
||||
return JSON.stringify(allResults);
|
||||
}
|
||||
}
|
||||
41
chaincode-typescript/src/Contract/registerEnrollUser.js
Normal file
41
chaincode-typescript/src/Contract/registerEnrollUser.js
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
const { Wallets } = require('fabric-network');
|
||||
const FabricCAServices = require('fabric-ca-client');
|
||||
const path = require('path');
|
||||
const { buildCAClient, registerAndEnrollUser} = require('../../../test-application/javascript/CAUtil.js');
|
||||
const { buildCCPOrg1, buildWallet } = require('../../../test-application/javascript/AppUtil.js');
|
||||
|
||||
const mspOrg1 = 'Org1MSP';
|
||||
|
||||
|
||||
async function connectToOrg1CA(UserID) {
|
||||
console.log('\n--> Register and enrolling new user');
|
||||
const ccpOrg1 = buildCCPOrg1();
|
||||
const caOrg1Client = buildCAClient(FabricCAServices, ccpOrg1, 'ca.org1.example.com');
|
||||
|
||||
const walletPathOrg1 = path.join(__dirname, 'wallet');
|
||||
const walletOrg1 = await buildWallet(Wallets, walletPathOrg1);
|
||||
|
||||
await registerAndEnrollUser(caOrg1Client, walletOrg1, mspOrg1, UserID, 'org1.department1');
|
||||
|
||||
}
|
||||
|
||||
async function main() {
|
||||
|
||||
if (process.argv[2] === undefined ) {
|
||||
console.log('Usage: node registerEnrollUser.js userID');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const userId = process.argv[2];
|
||||
|
||||
try {
|
||||
|
||||
await connectToOrg1CA(userId);
|
||||
|
||||
} catch (error) {
|
||||
console.error(`Error in enrolling admin: ${error}`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
13
chaincode-typescript/src/Contract/userRequest.ts
Normal file
13
chaincode-typescript/src/Contract/userRequest.ts
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
import {Object, Property} from 'fabric-contract-api';
|
||||
|
||||
@Object()
|
||||
export class User {
|
||||
@Property()
|
||||
public userName: string;
|
||||
|
||||
@Property()
|
||||
public Approved: boolean;
|
||||
|
||||
@Property()
|
||||
public CreationTime: number;
|
||||
}
|
||||
1
chaincode-typescript/src/Contract/wallet/admin.id
Normal file
1
chaincode-typescript/src/Contract/wallet/admin.id
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"credentials":{"certificate":"-----BEGIN CERTIFICATE-----\nMIIB8zCCAZmgAwIBAgIUf/oQQ6bxcJi2CLPkqdXK73qabiUwCgYIKoZIzj0EAwIw\ncDELMAkGA1UEBhMCVVMxFzAVBgNVBAgTDk5vcnRoIENhcm9saW5hMQ8wDQYDVQQH\nEwZEdXJoYW0xGTAXBgNVBAoTEG9yZzEuZXhhbXBsZS5jb20xHDAaBgNVBAMTE2Nh\nLm9yZzEuZXhhbXBsZS5jb20wHhcNMjMxMDE4MDU0OTAwWhcNMjQxMDE3MDgxODAw\nWjAhMQ8wDQYDVQQLEwZjbGllbnQxDjAMBgNVBAMTBWFkbWluMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAE10NX3+ksbyj1ihsPFeyD5P8/PBIVeK+MkkYNove4Epd9\nwC0ZVJIs/6/Nw7HCuB4njyqm3IsnG19+41Mn/PvGOqNgMF4wDgYDVR0PAQH/BAQD\nAgeAMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFN9N55/92SUkWc/n6cRa4pG2P2S5\nMB8GA1UdIwQYMBaAFA+auQ7Dgia/v7BDt10XszfiPsfHMAoGCCqGSM49BAMCA0gA\nMEUCIQCeRKO13pOPWD9Wd1Z1C1wpWYw1SZwpprYNkchJ+CCgwwIgJ4sTnPD30/pK\nKrdpuRx8tuR+rHAZBMC1SjrStiJyblA=\n-----END CERTIFICATE-----\n","privateKey":"-----BEGIN PRIVATE KEY-----\r\nMIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg3YH3+eUHRb0EuPXy\r\nB3mnYSssSNDuwBrYP3hB37iXfoqhRANCAATXQ1ff6SxvKPWKGw8V7IPk/z88EhV4\r\nr4ySRg2i97gSl33ALRlUkiz/r83DscK4HiePKqbciycbX37jUyf8+8Y6\r\n-----END PRIVATE KEY-----\r\n"},"mspId":"Org1MSP","type":"X.509","version":1}
|
||||
1
chaincode-typescript/src/Contract/wallet/user123.id
Normal file
1
chaincode-typescript/src/Contract/wallet/user123.id
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"credentials":{"certificate":"-----BEGIN CERTIFICATE-----\nMIICgzCCAiqgAwIBAgIUIqIkO0oZz51bzn+uBqkv2EE1qIcwCgYIKoZIzj0EAwIw\ncDELMAkGA1UEBhMCVVMxFzAVBgNVBAgTDk5vcnRoIENhcm9saW5hMQ8wDQYDVQQH\nEwZEdXJoYW0xGTAXBgNVBAoTEG9yZzEuZXhhbXBsZS5jb20xHDAaBgNVBAMTE2Nh\nLm9yZzEuZXhhbXBsZS5jb20wHhcNMjMxMDE4MDU0OTAwWhcNMjQxMDE3MDgxOTAw\nWjBEMTAwCwYDVQQLEwRvcmcxMA0GA1UECxMGY2xpZW50MBIGA1UECxMLZGVwYXJ0\nbWVudDExEDAOBgNVBAMTB3VzZXIxMjMwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC\nAATokA8wRpsYyu90MTBwJACKhkPLwAAdPHVTC+XSOQoOXGY+W2UPrEvZxlzYNqG1\njYPffWW5gZXlD5gAXPBCuKglo4HNMIHKMA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMB\nAf8EAjAAMB0GA1UdDgQWBBTGBNj7yXfFpNA5nI+3pbbnSrpOcTAfBgNVHSMEGDAW\ngBQPmrkOw4Imv7+wQ7ddF7M34j7HxzBqBggqAwQFBgcIAQReeyJhdHRycyI6eyJo\nZi5BZmZpbGlhdGlvbiI6Im9yZzEuZGVwYXJ0bWVudDEiLCJoZi5FbnJvbGxtZW50\nSUQiOiJ1c2VyMTIzIiwiaGYuVHlwZSI6ImNsaWVudCJ9fTAKBggqhkjOPQQDAgNH\nADBEAiARDmNUggj34mLZke78XQcqsnY8eDcJFEFe6/oAcPglQgIgZsX5ETpcCRyh\n8QURT7zEP+ns8HhXGBPLdOC9T4IKlNo=\n-----END CERTIFICATE-----\n","privateKey":"-----BEGIN PRIVATE KEY-----\r\nMIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg9S/JIxNtav98ksuW\r\nxanH+3NY/voevpoJ0cuGm5E3YmGhRANCAATokA8wRpsYyu90MTBwJACKhkPLwAAd\r\nPHVTC+XSOQoOXGY+W2UPrEvZxlzYNqG1jYPffWW5gZXlD5gAXPBCuKgl\r\n-----END PRIVATE KEY-----\r\n"},"mspId":"Org1MSP","type":"X.509","version":1}
|
||||
26
chaincode-typescript/src/asset.ts
Normal file
26
chaincode-typescript/src/asset.ts
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import {Object, Property} from 'fabric-contract-api';
|
||||
|
||||
@Object()
|
||||
export class Asset {
|
||||
@Property()
|
||||
public docType?: string;
|
||||
|
||||
@Property()
|
||||
public ID: string;
|
||||
|
||||
@Property()
|
||||
public Color: string;
|
||||
|
||||
@Property()
|
||||
public Size: number;
|
||||
|
||||
@Property()
|
||||
public Owner: string;
|
||||
|
||||
@Property()
|
||||
public AppraisedValue: number;
|
||||
}
|
||||
173
chaincode-typescript/src/assetTransfer.ts
Normal file
173
chaincode-typescript/src/assetTransfer.ts
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
// Deterministic JSON.stringify()
|
||||
import {Context, Contract, Info, Returns, Transaction} from 'fabric-contract-api';
|
||||
import stringify from 'json-stringify-deterministic';
|
||||
import sortKeysRecursive from 'sort-keys-recursive';
|
||||
import {Asset} from './asset';
|
||||
|
||||
@Info({title: 'AssetTransfer', description: 'Smart contract for trading assets'})
|
||||
export class AssetTransferContract extends Contract {
|
||||
|
||||
@Transaction()
|
||||
public async InitLedger(ctx: Context): Promise<void> {
|
||||
const assets: Asset[] = [
|
||||
{
|
||||
ID: 'asset1',
|
||||
Color: 'blue',
|
||||
Size: 5,
|
||||
Owner: 'Tomoko',
|
||||
AppraisedValue: 300,
|
||||
},
|
||||
{
|
||||
ID: 'asset2',
|
||||
Color: 'red',
|
||||
Size: 5,
|
||||
Owner: 'Brad',
|
||||
AppraisedValue: 400,
|
||||
},
|
||||
{
|
||||
ID: 'asset3',
|
||||
Color: 'green',
|
||||
Size: 10,
|
||||
Owner: 'Jin Soo',
|
||||
AppraisedValue: 500,
|
||||
},
|
||||
{
|
||||
ID: 'asset4',
|
||||
Color: 'yellow',
|
||||
Size: 10,
|
||||
Owner: 'Max',
|
||||
AppraisedValue: 600,
|
||||
},
|
||||
{
|
||||
ID: 'asset5',
|
||||
Color: 'black',
|
||||
Size: 15,
|
||||
Owner: 'Adriana',
|
||||
AppraisedValue: 700,
|
||||
},
|
||||
{
|
||||
ID: 'asset6',
|
||||
Color: 'white',
|
||||
Size: 15,
|
||||
Owner: 'Michel',
|
||||
AppraisedValue: 800,
|
||||
},
|
||||
];
|
||||
|
||||
for (const asset of assets) {
|
||||
asset.docType = 'asset';
|
||||
// example of how to write to world state deterministically
|
||||
// use convetion of alphabetic order
|
||||
// we insert data in alphabetic order using 'json-stringify-deterministic' and 'sort-keys-recursive'
|
||||
// when retrieving data, in any lang, the order of data will be the same and consequently also the corresonding hash
|
||||
await ctx.stub.putState(asset.ID, Buffer.from(stringify(sortKeysRecursive(asset))));
|
||||
console.info(`Asset ${asset.ID} initialized`);
|
||||
}
|
||||
}
|
||||
|
||||
// CreateAsset issues a new asset to the world state with given details.
|
||||
@Transaction()
|
||||
public async CreateAsset(ctx: Context, id: string, color: string, size: number, owner: string, appraisedValue: number): Promise<void> {
|
||||
const exists = await this.AssetExists(ctx, id);
|
||||
if (exists) {
|
||||
throw new Error(`The asset ${id} already exists`);
|
||||
}
|
||||
|
||||
const asset = {
|
||||
ID: id,
|
||||
Color: color,
|
||||
Size: size,
|
||||
Owner: owner,
|
||||
AppraisedValue: appraisedValue,
|
||||
};
|
||||
// we insert data in alphabetic order using 'json-stringify-deterministic' and 'sort-keys-recursive'
|
||||
await ctx.stub.putState(id, Buffer.from(stringify(sortKeysRecursive(asset))));
|
||||
}
|
||||
|
||||
// ReadAsset returns the asset stored in the world state with given id.
|
||||
@Transaction(false)
|
||||
public async ReadAsset(ctx: Context, id: string): Promise<string> {
|
||||
const assetJSON = await ctx.stub.getState(id); // get the asset from chaincode state
|
||||
if (!assetJSON || assetJSON.length === 0) {
|
||||
throw new Error(`The asset ${id} does not exist`);
|
||||
}
|
||||
return assetJSON.toString();
|
||||
}
|
||||
|
||||
// UpdateAsset updates an existing asset in the world state with provided parameters.
|
||||
@Transaction()
|
||||
public async UpdateAsset(ctx: Context, id: string, color: string, size: number, owner: string, appraisedValue: number): Promise<void> {
|
||||
const exists = await this.AssetExists(ctx, id);
|
||||
if (!exists) {
|
||||
throw new Error(`The asset ${id} does not exist`);
|
||||
}
|
||||
|
||||
// overwriting original asset with new asset
|
||||
const updatedAsset = {
|
||||
ID: id,
|
||||
Color: color,
|
||||
Size: size,
|
||||
Owner: owner,
|
||||
AppraisedValue: appraisedValue,
|
||||
};
|
||||
// we insert data in alphabetic order using 'json-stringify-deterministic' and 'sort-keys-recursive'
|
||||
return ctx.stub.putState(id, Buffer.from(stringify(sortKeysRecursive(updatedAsset))));
|
||||
}
|
||||
|
||||
// DeleteAsset deletes an given asset from the world state.
|
||||
@Transaction()
|
||||
public async DeleteAsset(ctx: Context, id: string): Promise<void> {
|
||||
const exists = await this.AssetExists(ctx, id);
|
||||
if (!exists) {
|
||||
throw new Error(`The asset ${id} does not exist`);
|
||||
}
|
||||
return ctx.stub.deleteState(id);
|
||||
}
|
||||
|
||||
// AssetExists returns true when asset with given ID exists in world state.
|
||||
@Transaction(false)
|
||||
@Returns('boolean')
|
||||
public async AssetExists(ctx: Context, id: string): Promise<boolean> {
|
||||
const assetJSON = await ctx.stub.getState(id);
|
||||
return assetJSON && assetJSON.length > 0;
|
||||
}
|
||||
|
||||
// TransferAsset updates the owner field of asset with given id in the world state, and returns the old owner.
|
||||
@Transaction()
|
||||
public async TransferAsset(ctx: Context, id: string, newOwner: string): Promise<string> {
|
||||
const assetString = await this.ReadAsset(ctx, id);
|
||||
const asset = JSON.parse(assetString);
|
||||
const oldOwner = asset.Owner;
|
||||
asset.Owner = newOwner;
|
||||
// we insert data in alphabetic order using 'json-stringify-deterministic' and 'sort-keys-recursive'
|
||||
await ctx.stub.putState(id, Buffer.from(stringify(sortKeysRecursive(asset))));
|
||||
return oldOwner;
|
||||
}
|
||||
|
||||
// GetAllAssets returns all assets found in the world state.
|
||||
@Transaction(false)
|
||||
@Returns('string')
|
||||
public async GetAllAssets(ctx: Context): Promise<string> {
|
||||
const allResults = [];
|
||||
// range query with empty string for startKey and endKey does an open-ended query of all assets in the chaincode namespace.
|
||||
const iterator = await ctx.stub.getStateByRange('', '');
|
||||
let result = await iterator.next();
|
||||
while (!result.done) {
|
||||
const strValue = Buffer.from(result.value.value.toString()).toString('utf8');
|
||||
let record;
|
||||
try {
|
||||
record = JSON.parse(strValue);
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
record = strValue;
|
||||
}
|
||||
allResults.push(record);
|
||||
result = await iterator.next();
|
||||
}
|
||||
return JSON.stringify(allResults);
|
||||
}
|
||||
|
||||
}
|
||||
15
chaincode-typescript/src/index.ts
Normal file
15
chaincode-typescript/src/index.ts
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
// /*
|
||||
// * SPDX-License-Identifier: Apache-2.0
|
||||
// */
|
||||
|
||||
// import {AssetTransferContract} from './assetTransfer';
|
||||
|
||||
// export {AssetTransferContract} from './assetTransfer';
|
||||
|
||||
// export const contracts: any[] = [AssetTransferContract];
|
||||
|
||||
import {LandTransferContract} from './Contract/landTransaction';
|
||||
|
||||
export {LandTransferContract} from './Contract/landTransaction';
|
||||
|
||||
export const contracts: any[] = [LandTransferContract];
|
||||
19
chaincode-typescript/tsconfig.json
Normal file
19
chaincode-typescript/tsconfig.json
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"outDir": "dist",
|
||||
"target": "es2017",
|
||||
"moduleResolution": "node",
|
||||
"module": "commonjs",
|
||||
"esModuleInterop": true,
|
||||
"declaration": true,
|
||||
"sourceMap": true
|
||||
},
|
||||
"include": [
|
||||
"./src/**/*"
|
||||
],
|
||||
"exclude": [
|
||||
"./src/**/*.spec.ts"
|
||||
]
|
||||
}
|
||||
23
chaincode-typescript/tslint.json
Normal file
23
chaincode-typescript/tslint.json
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"defaultSeverity": "error",
|
||||
"extends": [
|
||||
"tslint:recommended"
|
||||
],
|
||||
"jsRules": {},
|
||||
"rules": {
|
||||
"indent": [true, "spaces", 4],
|
||||
"linebreak-style": [true, "LF"],
|
||||
"quotemark": [true, "single"],
|
||||
"semicolon": [true, "always"],
|
||||
"no-console": false,
|
||||
"curly": true,
|
||||
"triple-equals": true,
|
||||
"no-string-throw": true,
|
||||
"no-var-keyword": true,
|
||||
"no-trailing-whitespace": true,
|
||||
"object-literal-key-quotes": [true, "as-needed"],
|
||||
"object-literal-sort-keys": false,
|
||||
"max-line-length": false
|
||||
},
|
||||
"rulesDirectory": []
|
||||
}
|
||||
|
|
@ -31,25 +31,25 @@ services:
|
|||
networks:
|
||||
- test
|
||||
|
||||
ca_org2:
|
||||
image: hyperledger/fabric-ca:latest
|
||||
labels:
|
||||
service: hyperledger-fabric
|
||||
environment:
|
||||
- FABRIC_CA_HOME=/etc/hyperledger/fabric-ca-server
|
||||
- FABRIC_CA_SERVER_CA_NAME=ca-org2
|
||||
- FABRIC_CA_SERVER_TLS_ENABLED=true
|
||||
- FABRIC_CA_SERVER_PORT=8054
|
||||
- FABRIC_CA_SERVER_OPERATIONS_LISTENADDRESS=0.0.0.0:18054
|
||||
ports:
|
||||
- "8054:8054"
|
||||
- "18054:18054"
|
||||
command: sh -c 'fabric-ca-server start -b admin:adminpw -d'
|
||||
volumes:
|
||||
- ../organizations/fabric-ca/org2:/etc/hyperledger/fabric-ca-server
|
||||
container_name: ca_org2
|
||||
networks:
|
||||
- test
|
||||
# ca_org2:
|
||||
# image: hyperledger/fabric-ca:latest
|
||||
# labels:
|
||||
# service: hyperledger-fabric
|
||||
# environment:
|
||||
# - FABRIC_CA_HOME=/etc/hyperledger/fabric-ca-server
|
||||
# - FABRIC_CA_SERVER_CA_NAME=ca-org2
|
||||
# - FABRIC_CA_SERVER_TLS_ENABLED=true
|
||||
# - FABRIC_CA_SERVER_PORT=8054
|
||||
# - FABRIC_CA_SERVER_OPERATIONS_LISTENADDRESS=0.0.0.0:18054
|
||||
# ports:
|
||||
# - "8054:8054"
|
||||
# - "18054:18054"
|
||||
# command: sh -c 'fabric-ca-server start -b admin:adminpw -d'
|
||||
# volumes:
|
||||
# - ../organizations/fabric-ca/org2:/etc/hyperledger/fabric-ca-server
|
||||
# container_name: ca_org2
|
||||
# networks:
|
||||
# - test
|
||||
|
||||
ca_orderer:
|
||||
image: hyperledger/fabric-ca:latest
|
||||
|
|
|
|||
|
|
@ -97,44 +97,44 @@ services:
|
|||
networks:
|
||||
- test
|
||||
|
||||
peer0.org2.example.com:
|
||||
container_name: peer0.org2.example.com
|
||||
image: hyperledger/fabric-peer:latest
|
||||
labels:
|
||||
service: hyperledger-fabric
|
||||
environment:
|
||||
- FABRIC_CFG_PATH=/etc/hyperledger/peercfg
|
||||
- FABRIC_LOGGING_SPEC=INFO
|
||||
#- FABRIC_LOGGING_SPEC=DEBUG
|
||||
- CORE_PEER_TLS_ENABLED=true
|
||||
- CORE_PEER_PROFILE_ENABLED=false
|
||||
- CORE_PEER_TLS_CERT_FILE=/etc/hyperledger/fabric/tls/server.crt
|
||||
- CORE_PEER_TLS_KEY_FILE=/etc/hyperledger/fabric/tls/server.key
|
||||
- CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/tls/ca.crt
|
||||
# Peer specific variables
|
||||
- CORE_PEER_ID=peer0.org2.example.com
|
||||
- CORE_PEER_ADDRESS=peer0.org2.example.com:9051
|
||||
- CORE_PEER_LISTENADDRESS=0.0.0.0:9051
|
||||
- CORE_PEER_CHAINCODEADDRESS=peer0.org2.example.com:9052
|
||||
- CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:9052
|
||||
- CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org2.example.com:9051
|
||||
- CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org2.example.com:9051
|
||||
- CORE_PEER_LOCALMSPID=Org2MSP
|
||||
- CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/fabric/msp
|
||||
- CORE_OPERATIONS_LISTENADDRESS=peer0.org2.example.com:9445
|
||||
- CORE_METRICS_PROVIDER=prometheus
|
||||
- CHAINCODE_AS_A_SERVICE_BUILDER_CONFIG={"peername":"peer0org2"}
|
||||
- CORE_CHAINCODE_EXECUTETIMEOUT=300s
|
||||
volumes:
|
||||
- ../organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com:/etc/hyperledger/fabric
|
||||
- peer0.org2.example.com:/var/hyperledger/production
|
||||
working_dir: /root
|
||||
command: peer node start
|
||||
ports:
|
||||
- 9051:9051
|
||||
- 9445:9445
|
||||
networks:
|
||||
- test
|
||||
# peer0.org2.example.com:
|
||||
# container_name: peer0.org2.example.com
|
||||
# image: hyperledger/fabric-peer:latest
|
||||
# labels:
|
||||
# service: hyperledger-fabric
|
||||
# environment:
|
||||
# - FABRIC_CFG_PATH=/etc/hyperledger/peercfg
|
||||
# - FABRIC_LOGGING_SPEC=INFO
|
||||
# #- FABRIC_LOGGING_SPEC=DEBUG
|
||||
# - CORE_PEER_TLS_ENABLED=true
|
||||
# - CORE_PEER_PROFILE_ENABLED=false
|
||||
# - CORE_PEER_TLS_CERT_FILE=/etc/hyperledger/fabric/tls/server.crt
|
||||
# - CORE_PEER_TLS_KEY_FILE=/etc/hyperledger/fabric/tls/server.key
|
||||
# - CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/tls/ca.crt
|
||||
# # Peer specific variables
|
||||
# - CORE_PEER_ID=peer0.org2.example.com
|
||||
# - CORE_PEER_ADDRESS=peer0.org2.example.com:9051
|
||||
# - CORE_PEER_LISTENADDRESS=0.0.0.0:9051
|
||||
# - CORE_PEER_CHAINCODEADDRESS=peer0.org2.example.com:9052
|
||||
# - CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:9052
|
||||
# - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org2.example.com:9051
|
||||
# - CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org2.example.com:9051
|
||||
# - CORE_PEER_LOCALMSPID=Org2MSP
|
||||
# - CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/fabric/msp
|
||||
# - CORE_OPERATIONS_LISTENADDRESS=peer0.org2.example.com:9445
|
||||
# - CORE_METRICS_PROVIDER=prometheus
|
||||
# - CHAINCODE_AS_A_SERVICE_BUILDER_CONFIG={"peername":"peer0org2"}
|
||||
# - CORE_CHAINCODE_EXECUTETIMEOUT=300s
|
||||
# volumes:
|
||||
# - ../organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com:/etc/hyperledger/fabric
|
||||
# - peer0.org2.example.com:/var/hyperledger/production
|
||||
# working_dir: /root
|
||||
# command: peer node start
|
||||
# ports:
|
||||
# - 9051:9051
|
||||
# - 9445:9445
|
||||
# networks:
|
||||
# - test
|
||||
|
||||
cli:
|
||||
container_name: cli
|
||||
|
|
@ -155,6 +155,5 @@ services:
|
|||
- ../scripts:/opt/gopath/src/github.com/hyperledger/fabric/peer/scripts/
|
||||
depends_on:
|
||||
- peer0.org1.example.com
|
||||
- peer0.org2.example.com
|
||||
networks:
|
||||
- test
|
||||
|
|
@ -18,8 +18,8 @@ services:
|
|||
- ./docker/peercfg:/etc/hyperledger/peercfg
|
||||
- ${DOCKER_SOCK}:/host/var/run/docker.sock
|
||||
|
||||
peer0.org2.example.com:
|
||||
container_name: peer0.org2.example.com
|
||||
peer1.org1.example.com:
|
||||
container_name: peer1.org1.example.com
|
||||
image: hyperledger/fabric-peer:latest
|
||||
labels:
|
||||
service: hyperledger-fabric
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@ services:
|
|||
- ./docker/peercfg:/etc/hyperledger/peercfg
|
||||
- ${DOCKER_SOCK}:/host/var/run/docker.sock
|
||||
|
||||
peer0.org2.example.com:
|
||||
container_name: peer0.org2.example.com
|
||||
peer1.org1.example.com:
|
||||
container_name: peer1.org1.example.com
|
||||
image: hyperledger/fabric-peer:latest
|
||||
labels:
|
||||
service: hyperledger-fabric
|
||||
|
|
@ -31,6 +31,32 @@ services:
|
|||
- ./docker/peercfg:/etc/hyperledger/peercfg
|
||||
- ${DOCKER_SOCK}:/host/var/run/docker.sock
|
||||
|
||||
peer2.org1.example.com:
|
||||
container_name: peer2.org1.example.com
|
||||
image: hyperledger/fabric-peer:latest
|
||||
labels:
|
||||
service: hyperledger-fabric
|
||||
environment:
|
||||
#Generic peer variables
|
||||
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
|
||||
- CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=fabric_test
|
||||
volumes:
|
||||
- ./docker/peercfg:/etc/hyperledger/peercfg
|
||||
- ${DOCKER_SOCK}:/host/var/run/docker.sock
|
||||
|
||||
peer3.org1.example.com:
|
||||
container_name: peer3.org1.example.com
|
||||
image: hyperledger/fabric-peer:latest
|
||||
labels:
|
||||
service: hyperledger-fabric
|
||||
environment:
|
||||
#Generic peer variables
|
||||
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
|
||||
- CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=fabric_test
|
||||
volumes:
|
||||
- ./docker/peercfg:/etc/hyperledger/peercfg
|
||||
- ${DOCKER_SOCK}:/host/var/run/docker.sock
|
||||
|
||||
cli:
|
||||
container_name: cli
|
||||
image: hyperledger/fabric-tools:latest
|
||||
|
|
|
|||
|
|
@ -61,6 +61,15 @@ Organizations:
|
|||
Endorsement:
|
||||
Type: Signature
|
||||
Rule: "OR('Org1MSP.peer')"
|
||||
AnchorPeers:
|
||||
- Host: peer0.org1.example.com
|
||||
Port: 7051
|
||||
- Host: peer1.org1.example.com
|
||||
Port: 7061
|
||||
- Host: peer2.org1.example.com
|
||||
Port: 7071
|
||||
- Host: peer3.org1.example.com
|
||||
Port: 7081
|
||||
- &Org2
|
||||
# DefaultOrg defines the organization which is used in the sampleconfig
|
||||
# of the fabric.git development environment
|
||||
|
|
|
|||
|
|
@ -173,17 +173,37 @@ function createOrgs() {
|
|||
fatalln "Failed to generate certificates..."
|
||||
fi
|
||||
|
||||
infoln "Creating Org2 Identities"
|
||||
# infoln "Creating Org2 Identities"
|
||||
|
||||
set -x
|
||||
cryptogen generate --config=./organizations/cryptogen/crypto-config-org2.yaml --output="organizations"
|
||||
res=$?
|
||||
{ set +x; } 2>/dev/null
|
||||
if [ $res -ne 0 ]; then
|
||||
fatalln "Failed to generate certificates..."
|
||||
fi
|
||||
# set -x
|
||||
# cryptogen generate --config=./organizations/cryptogen/crypto-config-org2.yaml --output="organizations"
|
||||
# res=$?
|
||||
# { set +x; } 2>/dev/null
|
||||
# if [ $res -ne 0 ]; then
|
||||
# fatalln "Failed to generate certificates..."
|
||||
# fi
|
||||
|
||||
infoln "Creating Orderer Org Identities"
|
||||
#infoln "Creating Org3 Identities"
|
||||
|
||||
# set -x
|
||||
# cryptogen generate --config=./organizations/cryptogen/crypto-config-org3.yaml --output="organizations"
|
||||
# res=$?
|
||||
# { set +x; } 2>/dev/null
|
||||
# if [ $res -ne 0 ]; then
|
||||
# fatalln "Failed to generate certificates..."
|
||||
# fi
|
||||
|
||||
# infoln "Creating Org4 Identities"
|
||||
|
||||
# set -x
|
||||
# cryptogen generate --config=./organizations/cryptogen/crypto-config-org4.yaml --output="organizations"
|
||||
# res=$?
|
||||
# { set +x; } 2>/dev/null
|
||||
# if [ $res -ne 0 ]; then
|
||||
# fatalln "Failed to generate certificates..."
|
||||
# fi
|
||||
|
||||
# infoln "Creating Orderer Org Identities"
|
||||
|
||||
set -x
|
||||
cryptogen generate --config=./organizations/cryptogen/crypto-config-orderer.yaml --output="organizations"
|
||||
|
|
@ -235,9 +255,9 @@ function createOrgs() {
|
|||
|
||||
createOrg1
|
||||
|
||||
infoln "Creating Org2 Identities"
|
||||
# infoln "Creating Org2 Identities"
|
||||
|
||||
createOrg2
|
||||
# createOrg2
|
||||
|
||||
infoln "Creating Orderer Org Identities"
|
||||
|
||||
|
|
@ -245,7 +265,7 @@ function createOrgs() {
|
|||
|
||||
fi
|
||||
|
||||
infoln "Generating CCP files for Org1 and Org2"
|
||||
infoln "Generating CCP files for Org1"
|
||||
./organizations/ccp-generate.sh
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,11 +35,31 @@ CAPEM=organizations/peerOrganizations/org1.example.com/ca/ca.org1.example.com-ce
|
|||
echo "$(json_ccp $ORG $P0PORT $CAPORT $PEERPEM $CAPEM)" > organizations/peerOrganizations/org1.example.com/connection-org1.json
|
||||
echo "$(yaml_ccp $ORG $P0PORT $CAPORT $PEERPEM $CAPEM)" > organizations/peerOrganizations/org1.example.com/connection-org1.yaml
|
||||
|
||||
ORG=2
|
||||
P0PORT=9051
|
||||
CAPORT=8054
|
||||
PEERPEM=organizations/peerOrganizations/org2.example.com/tlsca/tlsca.org2.example.com-cert.pem
|
||||
CAPEM=organizations/peerOrganizations/org2.example.com/ca/ca.org2.example.com-cert.pem
|
||||
# ORG=2
|
||||
# P0PORT=9051
|
||||
# CAPORT=8054
|
||||
# PEERPEM=organizations/peerOrganizations/org2.example.com/tlsca/tlsca.org2.example.com-cert.pem
|
||||
# CAPEM=organizations/peerOrganizations/org2.example.com/ca/ca.org2.example.com-cert.pem
|
||||
|
||||
echo "$(json_ccp $ORG $P0PORT $CAPORT $PEERPEM $CAPEM)" > organizations/peerOrganizations/org2.example.com/connection-org2.json
|
||||
echo "$(yaml_ccp $ORG $P0PORT $CAPORT $PEERPEM $CAPEM)" > organizations/peerOrganizations/org2.example.com/connection-org2.yaml
|
||||
# echo "$(json_ccp $ORG $P0PORT $CAPORT $PEERPEM $CAPEM)" > organizations/peerOrganizations/org2.example.com/connection-org2.json
|
||||
# echo "$(yaml_ccp $ORG $P0PORT $CAPORT $PEERPEM $CAPEM)" > organizations/peerOrganizations/org2.example.com/connection-org2.yaml
|
||||
|
||||
# ORG=3
|
||||
# P0PORT=9151
|
||||
# CAPORT=8154
|
||||
# PEERPEM=organizations/peerOrganizations/org3.example.com/tlsca/tlsca.org3.example.com-cert.pem
|
||||
# CAPEM=organizations/peerOrganizations/org3.example.com/ca/ca.org3.example.com-cert.pem
|
||||
# PEERCOUNT=3
|
||||
|
||||
# echo "$(json_ccp $ORG $P0PORT $CAPORT $PEERPEM $CAPEM $PEERCOUNT)" > organizations/peerOrganizations/org3.example.com/connection-org3.json
|
||||
# echo "$(yaml_ccp $ORG $P0PORT $CAPORT $PEERPEM $CAPEM $PEERCOUNT)" > organizations/peerOrganizations/org3.example.com/connection-org3.yaml
|
||||
|
||||
# ORG=4
|
||||
# P0PORT=9251
|
||||
# CAPORT=8254
|
||||
# PEERPEM=organizations/peerOrganizations/org4.example.com/tlsca/tlsca.org4.example.com-cert.pem
|
||||
# CAPEM=organizations/peerOrganizations/org4.example.com/ca/ca.org4.example.com-cert.pem
|
||||
# PEERCOUNT=4
|
||||
|
||||
# echo "$(json_ccp $ORG $P0PORT $CAPORT $PEERPEM $CAPEM $PEERCOUNT)" > organizations/peerOrganizations/org4.example.com/connection-org4.json
|
||||
# echo "$(yaml_ccp $ORG $P0PORT $CAPORT $PEERPEM $CAPEM $PEERCOUNT)" > organizations/peerOrganizations/org4.example.com/connection-org4.yaml
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ PeerOrgs:
|
|||
# name collisions
|
||||
# ---------------------------------------------------------------------------
|
||||
Template:
|
||||
Count: 1
|
||||
Count: 2
|
||||
SANS:
|
||||
- localhost
|
||||
# Start: 5
|
||||
|
|
@ -58,4 +58,4 @@ PeerOrgs:
|
|||
# Count: The number of user accounts _in addition_ to Admin
|
||||
# ---------------------------------------------------------------------------
|
||||
Users:
|
||||
Count: 1
|
||||
Count: 2
|
||||
|
|
|
|||
61
test-network/organizations/cryptogen/crypto-config-org3.yaml
Executable file
61
test-network/organizations/cryptogen/crypto-config-org3.yaml
Executable file
|
|
@ -0,0 +1,61 @@
|
|||
# Copyright IBM Corp. All Rights Reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# "PeerOrgs" - Definition of organizations managing peer nodes
|
||||
# ---------------------------------------------------------------------------
|
||||
PeerOrgs:
|
||||
# ---------------------------------------------------------------------------
|
||||
# Org1
|
||||
# ---------------------------------------------------------------------------
|
||||
- Name: Org3
|
||||
Domain: org3.example.com
|
||||
EnableNodeOUs: true
|
||||
# ---------------------------------------------------------------------------
|
||||
# "Specs"
|
||||
# ---------------------------------------------------------------------------
|
||||
# Uncomment this section to enable the explicit definition of hosts in your
|
||||
# configuration. Most users will want to use Template, below
|
||||
#
|
||||
# Specs is an array of Spec entries. Each Spec entry consists of two fields:
|
||||
# - Hostname: (Required) The desired hostname, sans the domain.
|
||||
# - CommonName: (Optional) Specifies the template or explicit override for
|
||||
# the CN. By default, this is the template:
|
||||
#
|
||||
# "{{.Hostname}}.{{.Domain}}"
|
||||
#
|
||||
# which obtains its values from the Spec.Hostname and
|
||||
# Org.Domain, respectively.
|
||||
# ---------------------------------------------------------------------------
|
||||
# - Hostname: foo # implicitly "foo.org1.example.com"
|
||||
# CommonName: foo27.org5.example.com # overrides Hostname-based FQDN set above
|
||||
# - Hostname: bar
|
||||
# - Hostname: baz
|
||||
# ---------------------------------------------------------------------------
|
||||
# "Template"
|
||||
# ---------------------------------------------------------------------------
|
||||
# Allows for the definition of 1 or more hosts that are created sequentially
|
||||
# from a template. By default, this looks like "peer%d" from 0 to Count-1.
|
||||
# You may override the number of nodes (Count), the starting index (Start)
|
||||
# or the template used to construct the name (Hostname).
|
||||
#
|
||||
# Note: Template and Specs are not mutually exclusive. You may define both
|
||||
# sections and the aggregate nodes will be created for you. Take care with
|
||||
# name collisions
|
||||
# ---------------------------------------------------------------------------
|
||||
Template:
|
||||
Count: 3
|
||||
SANS:
|
||||
- localhost
|
||||
# Start: 5
|
||||
# Hostname: {{.Prefix}}{{.Index}} # default
|
||||
# ---------------------------------------------------------------------------
|
||||
# "Users"
|
||||
# ---------------------------------------------------------------------------
|
||||
# Count: The number of user accounts _in addition_ to Admin
|
||||
# ---------------------------------------------------------------------------
|
||||
Users:
|
||||
Count: 3
|
||||
61
test-network/organizations/cryptogen/crypto-config-org4.yaml
Executable file
61
test-network/organizations/cryptogen/crypto-config-org4.yaml
Executable file
|
|
@ -0,0 +1,61 @@
|
|||
# Copyright IBM Corp. All Rights Reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# "PeerOrgs" - Definition of organizations managing peer nodes
|
||||
# ---------------------------------------------------------------------------
|
||||
PeerOrgs:
|
||||
# ---------------------------------------------------------------------------
|
||||
# Org1
|
||||
# ---------------------------------------------------------------------------
|
||||
- Name: Org4
|
||||
Domain: org4.example.com
|
||||
EnableNodeOUs: true
|
||||
# ---------------------------------------------------------------------------
|
||||
# "Specs"
|
||||
# ---------------------------------------------------------------------------
|
||||
# Uncomment this section to enable the explicit definition of hosts in your
|
||||
# configuration. Most users will want to use Template, below
|
||||
#
|
||||
# Specs is an array of Spec entries. Each Spec entry consists of two fields:
|
||||
# - Hostname: (Required) The desired hostname, sans the domain.
|
||||
# - CommonName: (Optional) Specifies the template or explicit override for
|
||||
# the CN. By default, this is the template:
|
||||
#
|
||||
# "{{.Hostname}}.{{.Domain}}"
|
||||
#
|
||||
# which obtains its values from the Spec.Hostname and
|
||||
# Org.Domain, respectively.
|
||||
# ---------------------------------------------------------------------------
|
||||
# - Hostname: foo # implicitly "foo.org1.example.com"
|
||||
# CommonName: foo27.org5.example.com # overrides Hostname-based FQDN set above
|
||||
# - Hostname: bar
|
||||
# - Hostname: baz
|
||||
# ---------------------------------------------------------------------------
|
||||
# "Template"
|
||||
# ---------------------------------------------------------------------------
|
||||
# Allows for the definition of 1 or more hosts that are created sequentially
|
||||
# from a template. By default, this looks like "peer%d" from 0 to Count-1.
|
||||
# You may override the number of nodes (Count), the starting index (Start)
|
||||
# or the template used to construct the name (Hostname).
|
||||
#
|
||||
# Note: Template and Specs are not mutually exclusive. You may define both
|
||||
# sections and the aggregate nodes will be created for you. Take care with
|
||||
# name collisions
|
||||
# ---------------------------------------------------------------------------
|
||||
Template:
|
||||
Count: 4
|
||||
SANS:
|
||||
- localhost
|
||||
# Start: 5
|
||||
# Hostname: {{.Prefix}}{{.Index}} # default
|
||||
# ---------------------------------------------------------------------------
|
||||
# "Users"
|
||||
# ---------------------------------------------------------------------------
|
||||
# Count: The number of user accounts _in addition_ to Admin
|
||||
# ---------------------------------------------------------------------------
|
||||
Users:
|
||||
Count: 4
|
||||
|
|
@ -44,6 +44,21 @@ function createOrg1() {
|
|||
fabric-ca-client register --caname ca-org1 --id.name peer0 --id.secret peer0pw --id.type peer --tls.certfiles "${PWD}/organizations/fabric-ca/org1/ca-cert.pem"
|
||||
{ set +x; } 2>/dev/null
|
||||
|
||||
infoln "Registering peer1"
|
||||
set -x
|
||||
fabric-ca-client register --caname ca-org1 --id.name peer1 --id.secret peer1pw --id.type peer --tls.certfiles "${PWD}/organizations/fabric-ca/org1/ca-cert.pem"
|
||||
{ set +x; } 2>/dev/null
|
||||
|
||||
infoln "Registering peer2"
|
||||
set -x
|
||||
fabric-ca-client register --caname ca-org1 --id.name peer2 --id.secret peer2pw --id.type peer --tls.certfiles "${PWD}/organizations/fabric-ca/org1/ca-cert.pem"
|
||||
{ set +x; } 2>/dev/null
|
||||
|
||||
infoln "Registering peer3"
|
||||
set -x
|
||||
fabric-ca-client register --caname ca-org1 --id.name peer3 --id.secret peer3pw --id.type peer --tls.certfiles "${PWD}/organizations/fabric-ca/org1/ca-cert.pem"
|
||||
{ set +x; } 2>/dev/null
|
||||
|
||||
infoln "Registering user"
|
||||
set -x
|
||||
fabric-ca-client register --caname ca-org1 --id.name user1 --id.secret user1pw --id.type client --tls.certfiles "${PWD}/organizations/fabric-ca/org1/ca-cert.pem"
|
||||
|
|
|
|||
BIN
test-network_org4.zip
Normal file
BIN
test-network_org4.zip
Normal file
Binary file not shown.
Loading…
Reference in a new issue