Revert "Remove Typescript References (#258)" (#261)

This reverts commit 7a23d7872a.
This commit is contained in:
Arnaud J Le Hors 2020-07-23 17:06:57 +02:00 committed by GitHub
parent 7a23d7872a
commit 7771b4f216
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
48 changed files with 1508 additions and 5 deletions

View file

@ -28,7 +28,7 @@ The asset transfer series provides a series of smart contracts and applications
| **Smart Contract** | **Description** | **Tutorial** | **Smart contract languages** | **Application languages** | | **Smart Contract** | **Description** | **Tutorial** | **Smart contract languages** | **Application languages** |
| -----------|------------------------------|----------|---------|---------| | -----------|------------------------------|----------|---------|---------|
| [Basic](asset-transfer-basic) | The Basic sample smart contract that allows you to create and transfer an asset by putting data on the ledger and retrieving it. This sample is recommended for new Fabric users. | **Coming soon** | Go, JavaScript | JavaScript | | [Basic](asset-transfer-basic) | The Basic sample smart contract that allows you to create and transfer an asset by putting data on the ledger and retrieving it. This sample is recommended for new Fabric users. | **Coming soon** | Go, JavaScript, Typescript | JavaScript, Typescript |
| [Ledger queries](asset-transfer-ledger-queries) | The ledger queries sample demonstrates how to deploy an index with your chaincode and issue rich queries when you are using CouchDB as your state database. | **Coming soon** | Go | **Coming soon** | | [Ledger queries](asset-transfer-ledger-queries) | The ledger queries sample demonstrates how to deploy an index with your chaincode and issue rich queries when you are using CouchDB as your state database. | **Coming soon** | Go | **Coming soon** |
| [Private data](asset-transfer-private-data) | This sample demonstrates the use of private data collections and how the private data hash can be used to verify an agreement before executing a transfer | **Coming soon** | Go | **Coming soon** | | [Private data](asset-transfer-private-data) | This sample demonstrates the use of private data collections and how the private data hash can be used to verify an agreement before executing a transfer | **Coming soon** | Go | **Coming soon** |
| [Secured agreement](asset-transfer-secured-agreement) | Smart contract that uses private data, state based endorsement, and access control to establish the ownership of an asset, guarantee immutability, and securely transfer an asset with the consent of both the buyer and the owner, while keeping the asset details private. | [Secured asset transfer in Fabric](https://hyperledger-fabric.readthedocs.io/en/master/secured_private_asset_transfer_tutorial.html) | Go | **Coming soon** | | [Secured agreement](asset-transfer-secured-agreement) | Smart contract that uses private data, state based endorsement, and access control to establish the ownership of an asset, guarantee immutability, and securely transfer an asset with the consent of both the buyer and the owner, while keeping the asset details private. | [Secured asset transfer in Fabric](https://hyperledger-fabric.readthedocs.io/en/master/secured_private_asset_transfer_tutorial.html) | Go | **Coming soon** |

View file

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

View file

@ -0,0 +1,59 @@
{
"name": "asset-transfer-basic",
"version": "1.0.0",
"description": "Asset-Transfer-Basic application implemented in TypeScript",
"engines": {
"node": ">=8",
"npm": ">=5"
},
"scripts": {
"lint": "tslint -c tslint.json 'src/**/*.ts'",
"pretest": "npm run lint",
"test": "nyc mocha -r ts-node/register src/**/*.spec.ts",
"build": "tsc",
"build:watch": "tsc -w",
"prepublishOnly": "npm run build"
},
"engineStrict": true,
"author": "Hyperledger",
"license": "Apache-2.0",
"dependencies": {
"fabric-ca-client": "^2.1.0",
"fabric-network": "^2.1.0"
},
"devDependencies": {
"@types/chai": "^4.1.7",
"@types/mocha": "^5.2.5",
"@types/node": "^10.12.10",
"@types/sinon": "^5.0.7",
"@types/sinon-chai": "^3.2.1",
"chai": "^4.2.0",
"mocha": "^5.2.0",
"nyc": "^14.1.1",
"sinon": "^7.1.1",
"sinon-chai": "^3.3.0",
"ts-node": "^7.0.1",
"tslint": "^5.11.0",
"typescript": "^3.1.6"
},
"nyc": {
"extension": [
".ts",
".tsx"
],
"exclude": [
"coverage/**",
"dist/**"
],
"reporter": [
"text-summary",
"html"
],
"all": true,
"check-coverage": true,
"statements": 100,
"branches": 100,
"functions": 100,
"lines": 100
}
}

View file

@ -0,0 +1,56 @@
/*
* SPDX-License-Identifier: Apache-2.0
*/
import * as FabricCAServices from 'fabric-ca-client';
import { Wallets, X509Identity } from 'fabric-network';
import * as fs from 'fs';
import * as path from 'path';
async function main() {
try {
// load the network configuration
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 ccp = JSON.parse(fs.readFileSync(ccpPath, 'utf8'));
// Create a new CA client for interacting with the CA.
const caInfo = ccp.certificateAuthorities['ca.org1.example.com'];
const caTLSCACerts = caInfo.tlsCACerts.pem;
const ca = new FabricCAServices(caInfo.url, { trustedRoots: caTLSCACerts, verify: false }, caInfo.caName);
// Create a new file system based wallet for managing identities.
const walletPath = path.join(path.resolve(__dirname, '..'), 'wallet');
const wallet = await Wallets.newFileSystemWallet(walletPath);
console.log(`Wallet path: ${walletPath}`);
// Check to see if we've already enrolled the admin user.
const identity = await wallet.get('admin');
if (identity) {
console.log('An identity for the admin user "admin" already exists in the wallet');
return;
}
// Enroll the admin user, and import the new identity into the wallet.
const enrollment = await ca.enroll({ enrollmentID: 'admin', enrollmentSecret: 'adminpw' });
const x509Identity: X509Identity = {
credentials: {
certificate: enrollment.certificate,
privateKey: enrollment.key.toBytes(),
},
mspId: 'Org1MSP',
type: 'X.509',
};
await wallet.put('admin', x509Identity);
console.log('Successfully enrolled admin user "admin" and imported it into the wallet');
} catch (error) {
console.error(`Failed to enroll admin user "admin": ${error}`);
process.exit(1);
}
}
main();

View file

@ -0,0 +1,59 @@
/*
* SPDX-License-Identifier: Apache-2.0
*/
import { Gateway, Wallets } from 'fabric-network';
import * as path from 'path';
import * as fs from 'fs';
async function main() {
try {
// load the network configuration
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 ccp = JSON.parse(fs.readFileSync(ccpPath, 'utf8'));
// Create a new file system based wallet for managing identities.
const walletPath = path.join(path.resolve(__dirname, '..'), 'wallet');
const wallet = await Wallets.newFileSystemWallet(walletPath);
console.log(`Wallet path: ${walletPath}`);
// Check to see if we've already enrolled the user.
const identity = await wallet.get('appUser');
if (!identity) {
console.log('An identity for the user "appUser" does not exist in the wallet');
console.log('Run the registerUser.ts application before retrying');
return;
}
// Create a new gateway for connecting to our peer node.
const gateway = new Gateway();
await gateway.connect(ccp, { wallet, identity: 'appUser', discovery: { enabled: true, asLocalhost: true } });
// Get the network (channel) our contract is deployed to.
const network = await gateway.getNetwork('mychannel');
// Get the contract from the network.
const contract = network.getContract('basic');
// Submit the specified transaction. (several example transactions are listed below)
// createAsset creates an asset with ID asset1, color yellow, owner Dave, size 5 and appraizedValue of 130 requires 6 arguments.
// ex: ('createAsset', 'asset1', 'yellow', 'Dave', 5, 1300)
// transferAsset transfers an asset with ID asset1 to new owner Tom - requires 2 arguments.
// ex: ('transferAsset', 'asset1', 'Tom')
await contract.submitTransaction('createAsset', 'asset13', 'yellow', "5", 'Tom', "1300");
console.log(`Transaction has been submitted`);
// Disconnect from the gateway.
await gateway.disconnect();
} catch (error) {
console.error(`Failed to submit transaction: ${error}`);
process.exit(1);
}
}
main();

View file

@ -0,0 +1,57 @@
/*
* SPDX-License-Identifier: Apache-2.0
*/
import { Gateway, Wallets } from 'fabric-network';
import * as path from 'path';
import * as fs from 'fs';
async function main() {
try {
// load the network configuration
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 ccp = JSON.parse(fs.readFileSync(ccpPath, 'utf8'));
// Create a new file system based wallet for managing identities.
const walletPath = path.join(path.resolve(__dirname, '..'), 'wallet');
const wallet = await Wallets.newFileSystemWallet(walletPath);
console.log(`Wallet path: ${walletPath}`);
// Check to see if we've already enrolled the user.
const identity = await wallet.get('appUser');
if (!identity) {
console.log('An identity for the user "appUser" does not exist in the wallet');
console.log('Run the registerUser.ts application before retrying');
return;
}
// Create a new gateway for connecting to our peer node.
const gateway = new Gateway();
await gateway.connect(ccp, { wallet, identity: 'appUser', discovery: { enabled: true, asLocalhost: true } });
// Get the network (channel) our contract is deployed to.
const network = await gateway.getNetwork('mychannel');
// Get the contract from the network.
const contract = network.getContract('basic');
// Evaluate the specified transaction. (several example transactions are listed below)
// getAsset returns an asset with given assetID asset4 - requires 1 argument.
// ex: ('getAsset', 'asset4')
// getAllAssets returns all assets in the world state - requires no arguments.
// ex: ('getAllAssets')
const result = await contract.evaluateTransaction('getAllAssets');
console.log(`Transaction has been evaluated, result is: ${result.toString()}`);
} catch (error) {
console.error(`Failed to evaluate transaction: ${error}`);
process.exit(1);
}
}
main();

View file

@ -0,0 +1,68 @@
/*
* SPDX-License-Identifier: Apache-2.0
*/
import { Wallets, X509Identity } from 'fabric-network';
import * as FabricCAServices from 'fabric-ca-client';
import * as path from 'path';
import * as fs from 'fs';
async function main() {
try {
// load the network configuration
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}`);
}
let ccp = JSON.parse(fs.readFileSync(ccpPath, 'utf8'));
// Create a new CA client for interacting with the CA.
const caURL = ccp.certificateAuthorities['ca.org1.example.com'].url;
const ca = new FabricCAServices(caURL);
// Create a new file system based wallet for managing identities.
const walletPath = path.join(path.resolve(__dirname, '..'), 'wallet');
const wallet = await Wallets.newFileSystemWallet(walletPath);
console.log(`Wallet path: ${walletPath}`);
// Check to see if we've already enrolled the user.
const userIdentity = await wallet.get('appUser');
if (userIdentity) {
console.log('An identity for the user "appUser" already exists in the wallet');
return;
}
// Check to see if we've already enrolled the admin user.
const adminIdentity = await wallet.get('admin');
if (!adminIdentity) {
console.log('An identity for the admin user "admin" does not exist in the wallet');
console.log('Run the enrollAdmin.ts application 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, 'admin');
// Register the user, enroll the user, and import the new identity into the wallet.
const secret = await ca.register({ affiliation: 'org1.department1', enrollmentID: 'appUser', role: 'client' }, adminUser);
const enrollment = await ca.enroll({ enrollmentID: 'appUser', enrollmentSecret: secret });
const x509Identity: X509Identity = {
credentials: {
certificate: enrollment.certificate,
privateKey: enrollment.key.toBytes(),
},
mspId: 'Org1MSP',
type: 'X.509',
};
await wallet.put('appUser', x509Identity);
console.log('Successfully registered and enrolled admin user "appUser" and imported it into the wallet');
} catch (error) {
console.error(`Failed to register user "appUser": ${error}`);
process.exit(1);
}
}
main();

View file

@ -0,0 +1,16 @@
{
"compilerOptions": {
"outDir": "dist",
"target": "es2017",
"moduleResolution": "node",
"module": "commonjs",
"declaration": true,
"sourceMap": true
},
"include": [
"./src/**/*"
],
"exclude": [
"./src/**/*.spec.ts"
]
}

View file

@ -0,0 +1,22 @@
{
"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"],
"max-line-length": false
},
"rulesDirectory": []
}

View file

@ -0,0 +1,16 @@
#
# SPDX-License-Identifier: Apache-2.0
#
# Coverage directory used by tools like istanbul
coverage
# Dependency directories
node_modules/
jspm_packages/
package-lock.json
# Compiled TypeScript files
dist

View file

@ -0,0 +1,62 @@
{
"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": "fabric-chaincode-node start",
"build": "tsc",
"build:watch": "tsc -w",
"prepublishOnly": "npm run build"
},
"engineStrict": true,
"author": "Hyperledger",
"license": "Apache-2.0",
"dependencies": {
"fabric-contract-api": "^2.0.0",
"fabric-shim": "^2.0.0"
},
"devDependencies": {
"@types/chai": "^4.1.7",
"@types/mocha": "^5.2.5",
"@types/node": "^10.12.10",
"@types/sinon": "^5.0.7",
"@types/sinon-chai": "^3.2.1",
"chai": "^4.2.0",
"mocha": "^5.2.0",
"nyc": "^14.1.1",
"sinon": "^7.1.1",
"sinon-chai": "^3.3.0",
"ts-node": "^7.0.1",
"tslint": "^5.11.0",
"typescript": "^3.1.6"
},
"nyc": {
"extension": [
".ts",
".tsx"
],
"exclude": [
"coverage/**",
"dist/**"
],
"reporter": [
"text-summary",
"html"
],
"all": true,
"check-coverage": true,
"statements": 100,
"branches": 100,
"functions": 100,
"lines": 100
}
}

View file

@ -0,0 +1,12 @@
/*
* SPDX-License-Identifier: Apache-2.0
*/
export class Asset {
public docType?: string;
public ID: string;
public Color: string;
public Size: number;
public Owner: string;
public AppraisedValue: number;
}

View file

@ -0,0 +1,153 @@
/*
* SPDX-License-Identifier: Apache-2.0
*/
import { Context, Contract } from 'fabric-contract-api';
import { Asset } from './asset';
export class AssetTransfer extends Contract {
public async initLedger(ctx: Context) {
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 (let i = 0; i < assets.length; i++) {
assets[i].docType = 'asset';
await ctx.stub.putState(assets[i].ID, Buffer.from(JSON.stringify(assets[i])));
console.info('Added <--> ', assets[i]);
}
}
// createAsset issues a new asset to the world state with given details.
public async createAsset(ctx: Context, id: string, color: string, size: number, owner: string, appraisedValue: number) {
const asset = {
ID: id,
Color: color,
Size: size,
Owner: owner,
AppraisedValue: appraisedValue,
};
await ctx.stub.putState(id, Buffer.from(JSON.stringify(asset)));
}
// readAsset returns the asset stored in the world state with given id.
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.
public async updateAsset(ctx: Context, id: string, color: string, size: number, owner: string, appraisedValue: number) {
const exists = await this.assetExists(ctx, id);
if (!exists) {
throw new Error(`The asset ${id} does not exist`);
}
// overwritting original asset with new asset
let updatedAsset = {
ID: id,
Color: color,
Size: size,
Owner: owner,
AppraisedValue: appraisedValue,
};
return ctx.stub.putState(id, Buffer.from(JSON.stringify(updatedAsset)));
}
// deleteAsset deletes an given asset from the world state.
public async deleteAsset(ctx: Context, id: string) {
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.
public async assetExists(ctx: Context, id: string): Promise<boolean> {
const assetJSON = await ctx.stub.getState(id);
if (!assetJSON || assetJSON.length === 0) {
return false;
}
return true;
}
// transferAsset updates the owner field of asset with given id in the world state.
public async transferAsset(ctx: Context, id: string, newOwner: string) {
let assetString = await this.readAsset(ctx, id);
let asset = JSON.parse(assetString);
asset.Owner = newOwner;
await ctx.stub.putState(id, Buffer.from(JSON.stringify(asset)));
}
// getAllAssets returns all assets found in the world state.
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.
for await (const { key, value } of ctx.stub.getStateByRange("", "")) {
const strValue = Buffer.from(value).toString('utf8');
let record;
try {
record = JSON.parse(strValue);
} catch (err) {
console.log(err);
record = strValue;
}
allResults.push({ Key: key, Record: record });
}
console.info(allResults);
return JSON.stringify(allResults);
}
}

View file

@ -0,0 +1,8 @@
/*
* SPDX-License-Identifier: Apache-2.0
*/
import { AssetTransfer } from './assetTransfer';
export { AssetTransfer } from './assetTransfer';
export const contracts: any[] = [AssetTransfer];

View file

@ -0,0 +1,16 @@
{
"compilerOptions": {
"outDir": "dist",
"target": "es2017",
"moduleResolution": "node",
"module": "commonjs",
"declaration": true,
"sourceMap": true
},
"include": [
"./src/**/*"
],
"exclude": [
"./src/**/*.spec.ts"
]
}

View file

@ -0,0 +1,21 @@
{
"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"]
},
"rulesDirectory": []
}

View file

@ -6,7 +6,7 @@ This folder contains example smart contracts that are used by the Hyperledger Fa
| **Smart Contract** | **Description** | **Tutorial** | **Languages** | | **Smart Contract** | **Description** | **Tutorial** | **Languages** |
| -----------|------------------------------|----------|---------| | -----------|------------------------------|----------|---------|
| [fabcar](fabcar) | Basic smart contract that allows you to add and change data on the ledger using the Fabric contract API. Also contains an example on how to run chaincode as an external service. | [Writing your first application](https://hyperledger-fabric.readthedocs.io/en/master/write_first_app.html) | Go, Java, JavaScript | | [fabcar](fabcar) | Basic smart contract that allows you to add and change data on the ledger using the Fabric contract API. Also contains an example on how to run chaincode as an external service. | [Writing your first application](https://hyperledger-fabric.readthedocs.io/en/master/write_first_app.html) | Go, Java, JavaScript, Typescript |
| [marbles02](marbles02) | Sample that demonstrates how to deploy an index and use rich queries when you are using CouchDB as your state database. | [Using CouchDB](https://hyperledger-fabric.readthedocs.io/en/master/couchdb_tutorial.html) | Go | | [marbles02](marbles02) | Sample that demonstrates how to deploy an index and use rich queries when you are using CouchDB as your state database. | [Using CouchDB](https://hyperledger-fabric.readthedocs.io/en/master/couchdb_tutorial.html) | Go |
| [marbles02_private](marbles02_private) | Sample that demonstrates the use of private data collections. | [Private data tutorial](https://hyperledger-fabric.readthedocs.io/en/master/private_data_tutorial.html) | Go | | [marbles02_private](marbles02_private) | Sample that demonstrates the use of private data collections. | [Private data tutorial](https://hyperledger-fabric.readthedocs.io/en/master/private_data_tutorial.html) | Go |
| [marbles_transfer](marbles_transfer) | Smart contract that demonstrates the use of private data, state based endorsement, and access control to securely transfer an asset between two parties | [Marbles private asset transfer scenario](marbles_transfer/README.md) | Go | | [marbles_transfer](marbles_transfer) | Smart contract that demonstrates the use of private data, state based endorsement, and access control to securely transfer an asset between two parties | [Marbles private asset transfer scenario](marbles_transfer/README.md) | Go |

View file

@ -40,6 +40,9 @@ build/Release
node_modules/ node_modules/
jspm_packages/ jspm_packages/
# TypeScript v1 declaration files
typings/
# Optional npm cache directory # Optional npm cache directory
.npm .npm

View file

@ -40,6 +40,9 @@ build/Release
node_modules/ node_modules/
jspm_packages/ jspm_packages/
# TypeScript v1 declaration files
typings/
# Optional npm cache directory # Optional npm cache directory
.npm .npm

View file

@ -0,0 +1,16 @@
#
# SPDX-License-Identifier: Apache-2.0
#
root = true
[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false

81
chaincode/fabcar/typescript/.gitignore vendored Normal file
View file

@ -0,0 +1,81 @@
#
# SPDX-License-Identifier: Apache-2.0
#
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
# parcel-bundler cache (https://parceljs.org/)
.cache
# next.js build output
.next
# nuxt.js build output
.nuxt
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless
# Compiled TypeScript files
dist

View file

@ -0,0 +1,62 @@
{
"name": "fabcar",
"version": "1.0.0",
"description": "FabCar contract implemented in TypeScript",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
"engines": {
"node": ">=8",
"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": "fabric-chaincode-node start",
"build": "tsc",
"build:watch": "tsc -w",
"prepublishOnly": "npm run build"
},
"engineStrict": true,
"author": "Hyperledger",
"license": "Apache-2.0",
"dependencies": {
"fabric-contract-api": "^2.0.0",
"fabric-shim": "^2.0.0"
},
"devDependencies": {
"@types/chai": "^4.1.7",
"@types/mocha": "^5.2.5",
"@types/node": "^10.12.10",
"@types/sinon": "^5.0.7",
"@types/sinon-chai": "^3.2.1",
"chai": "^4.2.0",
"mocha": "^5.2.0",
"nyc": "^14.1.1",
"sinon": "^7.1.1",
"sinon-chai": "^3.3.0",
"ts-node": "^7.0.1",
"tslint": "^5.11.0",
"typescript": "^3.1.6"
},
"nyc": {
"extension": [
".ts",
".tsx"
],
"exclude": [
"coverage/**",
"dist/**"
],
"reporter": [
"text-summary",
"html"
],
"all": true,
"check-coverage": true,
"statements": 100,
"branches": 100,
"functions": 100,
"lines": 100
}
}

View file

@ -0,0 +1,11 @@
/*
* SPDX-License-Identifier: Apache-2.0
*/
export class Car {
public docType?: string;
public color: string;
public make: string;
public model: string;
public owner: string;
}

View file

@ -0,0 +1,140 @@
/*
* SPDX-License-Identifier: Apache-2.0
*/
import { Context, Contract } from 'fabric-contract-api';
import { Car } from './car';
export class FabCar extends Contract {
public async initLedger(ctx: Context) {
console.info('============= START : Initialize Ledger ===========');
const cars: Car[] = [
{
color: 'blue',
make: 'Toyota',
model: 'Prius',
owner: 'Tomoko',
},
{
color: 'red',
make: 'Ford',
model: 'Mustang',
owner: 'Brad',
},
{
color: 'green',
make: 'Hyundai',
model: 'Tucson',
owner: 'Jin Soo',
},
{
color: 'yellow',
make: 'Volkswagen',
model: 'Passat',
owner: 'Max',
},
{
color: 'black',
make: 'Tesla',
model: 'S',
owner: 'Adriana',
},
{
color: 'purple',
make: 'Peugeot',
model: '205',
owner: 'Michel',
},
{
color: 'white',
make: 'Chery',
model: 'S22L',
owner: 'Aarav',
},
{
color: 'violet',
make: 'Fiat',
model: 'Punto',
owner: 'Pari',
},
{
color: 'indigo',
make: 'Tata',
model: 'Nano',
owner: 'Valeria',
},
{
color: 'brown',
make: 'Holden',
model: 'Barina',
owner: 'Shotaro',
},
];
for (let i = 0; i < cars.length; i++) {
cars[i].docType = 'car';
await ctx.stub.putState('CAR' + i, Buffer.from(JSON.stringify(cars[i])));
console.info('Added <--> ', cars[i]);
}
console.info('============= END : Initialize Ledger ===========');
}
public async queryCar(ctx: Context, carNumber: string): Promise<string> {
const carAsBytes = await ctx.stub.getState(carNumber); // get the car from chaincode state
if (!carAsBytes || carAsBytes.length === 0) {
throw new Error(`${carNumber} does not exist`);
}
console.log(carAsBytes.toString());
return carAsBytes.toString();
}
public async createCar(ctx: Context, carNumber: string, make: string, model: string, color: string, owner: string) {
console.info('============= START : Create Car ===========');
const car: Car = {
color,
docType: 'car',
make,
model,
owner,
};
await ctx.stub.putState(carNumber, Buffer.from(JSON.stringify(car)));
console.info('============= END : Create Car ===========');
}
public async queryAllCars(ctx: Context): Promise<string> {
const startKey = '';
const endKey = '';
const allResults = [];
for await (const {key, value} of ctx.stub.getStateByRange(startKey, endKey)) {
const strValue = Buffer.from(value).toString('utf8');
let record;
try {
record = JSON.parse(strValue);
} catch (err) {
console.log(err);
record = strValue;
}
allResults.push({ Key: key, Record: record });
}
console.info(allResults);
return JSON.stringify(allResults);
}
public async changeCarOwner(ctx: Context, carNumber: string, newOwner: string) {
console.info('============= START : changeCarOwner ===========');
const carAsBytes = await ctx.stub.getState(carNumber); // get the car from chaincode state
if (!carAsBytes || carAsBytes.length === 0) {
throw new Error(`${carNumber} does not exist`);
}
const car: Car = JSON.parse(carAsBytes.toString());
car.owner = newOwner;
await ctx.stub.putState(carNumber, Buffer.from(JSON.stringify(car)));
console.info('============= END : changeCarOwner ===========');
}
}

View file

@ -0,0 +1,8 @@
/*
* SPDX-License-Identifier: Apache-2.0
*/
import { FabCar } from './fabcar';
export { FabCar } from './fabcar';
export const contracts: any[] = [ FabCar ];

View file

@ -0,0 +1,16 @@
{
"compilerOptions": {
"outDir": "dist",
"target": "es2017",
"moduleResolution": "node",
"module": "commonjs",
"declaration": true,
"sourceMap": true
},
"include": [
"./src/**/*"
],
"exclude": [
"./src/**/*.spec.ts"
]
}

View file

@ -0,0 +1,21 @@
{
"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"]
},
"rulesDirectory": []
}

View file

@ -40,6 +40,9 @@ build/Release
node_modules/ node_modules/
jspm_packages/ jspm_packages/
# TypeScript v1 declaration files
typings/
# Optional npm cache directory # Optional npm cache directory
.npm .npm

View file

@ -60,6 +60,14 @@ jobs:
- template: templates/install-deps.yml - template: templates/install-deps.yml
- template: templates/fabcar/azure-pipelines-javascript.yml - template: templates/fabcar/azure-pipelines-javascript.yml
- job: Fabcar_TypeScript
displayName: FabCar (TypeScript)
pool:
vmImage: ubuntu-18.04
steps:
- template: templates/install-deps.yml
- template: templates/fabcar/azure-pipelines-typescript.yml
- job: TestNetwork - job: TestNetwork
displayName: Test Network displayName: Test Network
pool: pool:

View file

@ -0,0 +1,22 @@
#
# SPDX-License-Identifier: Apache-2.0
#
steps:
- script: ./startFabric.sh typescript
workingDirectory: fabcar
displayName: Start Fabric
- script: retry -- npm install
workingDirectory: fabcar/typescript
displayName: Install FabCar Application Dependencies
- script: npm run build
workingDirectory: fabcar/typescript
displayName: Build FabCar application
- script: |
set -ex
node dist/enrollAdmin
node dist/registerUser
node dist/invoke
node dist/query
workingDirectory: fabcar/typescript
displayName: Run FabCar Application

View file

@ -7,6 +7,7 @@ steps:
./network.sh up createChannel -s couchdb -i ${FABRIC_VERSION} # FABRIC_VERSION is set in ci/azure-pipelines.yml ./network.sh up createChannel -s couchdb -i ${FABRIC_VERSION} # FABRIC_VERSION is set in ci/azure-pipelines.yml
./network.sh deployCC -ccn basic -ccv 1 -ccl javascript -cci initLedger ./network.sh deployCC -ccn basic -ccv 1 -ccl javascript -cci initLedger
./network.sh deployCC -ccn basic -ccv 2 -ccl golang -cci initLedger ./network.sh deployCC -ccn basic -ccv 2 -ccl golang -cci initLedger
./network.sh deployCC -ccn basic -ccv 3 -ccl typescript -cci initLedger
./network.sh deployCC -ccn secure -ccv 1 -ccl golang ./network.sh deployCC -ccn secure -ccv 1 -ccl golang
./network.sh down ./network.sh down
workingDirectory: test-network workingDirectory: test-network

View file

@ -40,6 +40,9 @@ build/Release
node_modules/ node_modules/
jspm_packages/ jspm_packages/
# TypeScript v1 declaration files
typings/
# Optional npm cache directory # Optional npm cache directory
.npm .npm

View file

@ -40,6 +40,9 @@ build/Release
node_modules/ node_modules/
jspm_packages/ jspm_packages/
# TypeScript v1 declaration files
typings/
# Optional npm cache directory # Optional npm cache directory
.npm .npm

View file

@ -40,6 +40,9 @@ build/Release
node_modules/ node_modules/
jspm_packages/ jspm_packages/
# TypeScript v1 declaration files
typings/
# Optional npm cache directory # Optional npm cache directory
.npm .npm

View file

@ -15,3 +15,4 @@ popd
# clean out any old identites in the wallets # clean out any old identites in the wallets
rm -rf javascript/wallet/* rm -rf javascript/wallet/*
rm -rf java/wallet/* rm -rf java/wallet/*
rm -rf typescript/wallet/*

View file

@ -19,15 +19,18 @@ elif [ "$CC_SRC_LANGUAGE" = "javascript" ]; then
CC_SRC_PATH="../chaincode/fabcar/javascript/" CC_SRC_PATH="../chaincode/fabcar/javascript/"
elif [ "$CC_SRC_LANGUAGE" = "java" ]; then elif [ "$CC_SRC_LANGUAGE" = "java" ]; then
CC_SRC_PATH="../chaincode/fabcar/java" CC_SRC_PATH="../chaincode/fabcar/java"
elif [ "$CC_SRC_LANGUAGE" = "typescript" ]; then
CC_SRC_PATH="../chaincode/fabcar/typescript/"
else else
echo The chaincode language ${CC_SRC_LANGUAGE} is not supported by this script echo The chaincode language ${CC_SRC_LANGUAGE} is not supported by this script
echo Supported chaincode languages are: go, java, and javascript echo Supported chaincode languages are: go, java, javascript, and typescript
exit 1 exit 1
fi fi
# clean out any old identites in the wallets # clean out any old identites in the wallets
rm -rf javascript/wallet/* rm -rf javascript/wallet/*
rm -rf java/wallet/* rm -rf java/wallet/*
rm -rf typescript/wallet/*
rm -rf go/wallet/* rm -rf go/wallet/*
# launch network; create channel and join peer to channel # launch network; create channel and join peer to channel
@ -67,6 +70,31 @@ JavaScript:
return all cars, but you can update the application to evaluate other transactions: return all cars, but you can update the application to evaluate other transactions:
node query node query
TypeScript:
Start by changing into the "typescript" directory:
cd typescript
Next, install all required packages:
npm install
Next, compile the TypeScript code into JavaScript:
npm run build
Then run the following applications to enroll the admin user, and register a new user
called appUser which will be used by the other applications to interact with the deployed
FabCar contract:
node dist/enrollAdmin
node dist/registerUser
You can run the invoke application as follows. By default, the invoke application will
create a new car, but you can update the application to submit other transactions:
node dist/invoke
You can run the query application as follows. By default, the query application will
return all cars, but you can update the application to evaluate other transactions:
node dist/query
Java: Java:
Start by changing into the "java" directory: Start by changing into the "java" directory:

16
fabcar/typescript/.editorconfig Executable file
View file

@ -0,0 +1,16 @@
#
# SPDX-License-Identifier: Apache-2.0
#
root = true
[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false

83
fabcar/typescript/.gitignore vendored Normal file
View file

@ -0,0 +1,83 @@
#
# SPDX-License-Identifier: Apache-2.0
#
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
# parcel-bundler cache (https://parceljs.org/)
.cache
# next.js build output
.next
# nuxt.js build output
.nuxt
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless
# Compiled TypeScript files
dist
wallet
!wallet/.gitkeep

View file

@ -0,0 +1,59 @@
{
"name": "fabcar",
"version": "1.0.0",
"description": "FabCar application implemented in TypeScript",
"engines": {
"node": ">=8",
"npm": ">=5"
},
"scripts": {
"lint": "tslint -c tslint.json 'src/**/*.ts'",
"pretest": "npm run lint",
"test": "nyc mocha -r ts-node/register src/**/*.spec.ts",
"build": "tsc",
"build:watch": "tsc -w",
"prepublishOnly": "npm run build"
},
"engineStrict": true,
"author": "Hyperledger",
"license": "Apache-2.0",
"dependencies": {
"fabric-ca-client": "^2.1.0",
"fabric-network": "^2.1.0"
},
"devDependencies": {
"@types/chai": "^4.1.7",
"@types/mocha": "^5.2.5",
"@types/node": "^10.12.10",
"@types/sinon": "^5.0.7",
"@types/sinon-chai": "^3.2.1",
"chai": "^4.2.0",
"mocha": "^5.2.0",
"nyc": "^14.1.1",
"sinon": "^7.1.1",
"sinon-chai": "^3.3.0",
"ts-node": "^7.0.1",
"tslint": "^5.11.0",
"typescript": "^3.1.6"
},
"nyc": {
"extension": [
".ts",
".tsx"
],
"exclude": [
"coverage/**",
"dist/**"
],
"reporter": [
"text-summary",
"html"
],
"all": true,
"check-coverage": true,
"statements": 100,
"branches": 100,
"functions": 100,
"lines": 100
}
}

View file

@ -0,0 +1,52 @@
/*
* SPDX-License-Identifier: Apache-2.0
*/
import * as FabricCAServices from 'fabric-ca-client';
import { Wallets, X509Identity } from 'fabric-network';
import * as fs from 'fs';
import * as path from 'path';
async function main() {
try {
// load the network configuration
const ccpPath = path.resolve(__dirname, '..', '..', '..','test-network','organizations','peerOrganizations','org1.example.com', 'connection-org1.json');
const ccp = JSON.parse(fs.readFileSync(ccpPath, 'utf8'));
// Create a new CA client for interacting with the CA.
const caInfo = ccp.certificateAuthorities['ca.org1.example.com'];
const caTLSCACerts = caInfo.tlsCACerts.pem;
const ca = new FabricCAServices(caInfo.url, { trustedRoots: caTLSCACerts, verify: false }, caInfo.caName);
// Create a new file system based wallet for managing identities.
const walletPath = path.join(process.cwd(), 'wallet');
const wallet = await Wallets.newFileSystemWallet(walletPath);
console.log(`Wallet path: ${walletPath}`);
// Check to see if we've already enrolled the admin user.
const identity = await wallet.get('admin');
if (identity) {
console.log('An identity for the admin user "admin" already exists in the wallet');
return;
}
// Enroll the admin user, and import the new identity into the wallet.
const enrollment = await ca.enroll({ enrollmentID: 'admin', enrollmentSecret: 'adminpw' });
const x509Identity: X509Identity = {
credentials: {
certificate: enrollment.certificate,
privateKey: enrollment.key.toBytes(),
},
mspId: 'Org1MSP',
type: 'X.509',
};
await wallet.put('admin', x509Identity);
console.log('Successfully enrolled admin user "admin" and imported it into the wallet');
} catch (error) {
console.error(`Failed to enroll admin user "admin": ${error}`);
process.exit(1);
}
}
main();

View file

@ -0,0 +1,53 @@
/*
* SPDX-License-Identifier: Apache-2.0
*/
import { Gateway, Wallets } from 'fabric-network';
import * as path from 'path';
import * as fs from 'fs';
async function main() {
try {
// load the network configuration
const ccpPath = path.resolve(__dirname, '..', '..', '..','test-network','organizations','peerOrganizations','org1.example.com', 'connection-org1.json');
const ccp = JSON.parse(fs.readFileSync(ccpPath, 'utf8'));
// Create a new file system based wallet for managing identities.
const walletPath = path.join(process.cwd(), 'wallet');
const wallet = await Wallets.newFileSystemWallet(walletPath);
console.log(`Wallet path: ${walletPath}`);
// Check to see if we've already enrolled the user.
const identity = await wallet.get('appUser');
if (!identity) {
console.log('An identity for the user "appUser" does not exist in the wallet');
console.log('Run the registerUser.ts application before retrying');
return;
}
// Create a new gateway for connecting to our peer node.
const gateway = new Gateway();
await gateway.connect(ccp, { wallet, identity: 'appUser', discovery: { enabled: true, asLocalhost: true } });
// Get the network (channel) our contract is deployed to.
const network = await gateway.getNetwork('mychannel');
// Get the contract from the network.
const contract = network.getContract('fabcar');
// Submit the specified transaction.
// createCar transaction - requires 5 argument, ex: ('createCar', 'CAR12', 'Honda', 'Accord', 'Black', 'Tom')
// changeCarOwner transaction - requires 2 args , ex: ('changeCarOwner', 'CAR12', 'Dave')
await contract.submitTransaction('createCar', 'CAR12', 'Honda', 'Accord', 'Black', 'Tom');
console.log(`Transaction has been submitted`);
// Disconnect from the gateway.
await gateway.disconnect();
} catch (error) {
console.error(`Failed to submit transaction: ${error}`);
process.exit(1);
}
}
main();

View file

@ -0,0 +1,51 @@
/*
* SPDX-License-Identifier: Apache-2.0
*/
import { Gateway, Wallets } from 'fabric-network';
import * as path from 'path';
import * as fs from 'fs';
async function main() {
try {
// load the network configuration
const ccpPath = path.resolve(__dirname, '..', '..', '..','test-network','organizations','peerOrganizations','org1.example.com', 'connection-org1.json');
const ccp = JSON.parse(fs.readFileSync(ccpPath, 'utf8'));
// Create a new file system based wallet for managing identities.
const walletPath = path.join(process.cwd(), 'wallet');
const wallet = await Wallets.newFileSystemWallet(walletPath);
console.log(`Wallet path: ${walletPath}`);
// Check to see if we've already enrolled the user.
const identity = await wallet.get('appUser');
if (!identity) {
console.log('An identity for the user "appUser" does not exist in the wallet');
console.log('Run the registerUser.ts application before retrying');
return;
}
// Create a new gateway for connecting to our peer node.
const gateway = new Gateway();
await gateway.connect(ccp, { wallet, identity: 'appUser', discovery: { enabled: true, asLocalhost: true } });
// Get the network (channel) our contract is deployed to.
const network = await gateway.getNetwork('mychannel');
// Get the contract from the network.
const contract = network.getContract('fabcar');
// Evaluate the specified transaction.
// queryCar transaction - requires 1 argument, ex: ('queryCar', 'CAR4')
// queryAllCars transaction - requires no arguments, ex: ('queryAllCars')
const result = await contract.evaluateTransaction('queryAllCars');
console.log(`Transaction has been evaluated, result is: ${result.toString()}`);
} catch (error) {
console.error(`Failed to evaluate transaction: ${error}`);
process.exit(1);
}
}
main();

View file

@ -0,0 +1,64 @@
/*
* SPDX-License-Identifier: Apache-2.0
*/
import { Wallets, X509Identity } from 'fabric-network';
import * as FabricCAServices from 'fabric-ca-client';
import * as path from 'path';
import * as fs from 'fs';
async function main() {
try {
// load the network configuration
const ccpPath = path.resolve(__dirname, '..', '..', '..','test-network','organizations','peerOrganizations','org1.example.com', 'connection-org1.json');
let ccp = JSON.parse(fs.readFileSync(ccpPath, 'utf8'));
// Create a new CA client for interacting with the CA.
const caURL = ccp.certificateAuthorities['ca.org1.example.com'].url;
const ca = new FabricCAServices(caURL);
// Create a new file system based wallet for managing identities.
const walletPath = path.join(process.cwd(), 'wallet');
const wallet = await Wallets.newFileSystemWallet(walletPath);
console.log(`Wallet path: ${walletPath}`);
// Check to see if we've already enrolled the user.
const userIdentity = await wallet.get('appUser');
if (userIdentity) {
console.log('An identity for the user "appUser" already exists in the wallet');
return;
}
// Check to see if we've already enrolled the admin user.
const adminIdentity = await wallet.get('admin');
if (!adminIdentity) {
console.log('An identity for the admin user "admin" does not exist in the wallet');
console.log('Run the enrollAdmin.ts application 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, 'admin');
// Register the user, enroll the user, and import the new identity into the wallet.
const secret = await ca.register({ affiliation: 'org1.department1', enrollmentID: 'appUser', role: 'client' }, adminUser);
const enrollment = await ca.enroll({ enrollmentID: 'appUser', enrollmentSecret: secret });
const x509Identity: X509Identity = {
credentials: {
certificate: enrollment.certificate,
privateKey: enrollment.key.toBytes(),
},
mspId: 'Org1MSP',
type: 'X.509',
};
await wallet.put('appUser', x509Identity);
console.log('Successfully registered and enrolled admin user "appUser" and imported it into the wallet');
} catch (error) {
console.error(`Failed to register user "appUser": ${error}`);
process.exit(1);
}
}
main();

View file

@ -0,0 +1,16 @@
{
"compilerOptions": {
"outDir": "dist",
"target": "es2017",
"moduleResolution": "node",
"module": "commonjs",
"declaration": true,
"sourceMap": true
},
"include": [
"./src/**/*"
],
"exclude": [
"./src/**/*.spec.ts"
]
}

View file

@ -0,0 +1,22 @@
{
"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"],
"max-line-length": false
},
"rulesDirectory": []
}

View file

View file

@ -41,7 +41,7 @@ function printHelp() {
echo " Used with "$'\e[0;32m'network.sh deployCC$'\e[0m' echo " Used with "$'\e[0;32m'network.sh deployCC$'\e[0m'
echo " -c <channel name> - deploy chaincode to channel" echo " -c <channel name> - deploy chaincode to channel"
echo " -ccn <name> - the short name of the chaincode to deploy: basic (default),ledger, private, secured" echo " -ccn <name> - the short name of the chaincode to deploy: basic (default),ledger, private, secured"
echo " -ccl <language> - the programming language of the chaincode to deploy: go (default), java, and javascript" echo " -ccl <language> - the programming language of the chaincode to deploy: go (default), java, javascript, typescript"
echo " -ccv <version> - chaincode version. 1.0 (default)" echo " -ccv <version> - chaincode version. 1.0 (default)"
echo " -ccs <sequence> - chaincode definition sequence. Must be an integer, 1 (default), 2, 3, etc" echo " -ccs <sequence> - chaincode definition sequence. Must be an integer, 1 (default), 2, 3, etc"
echo " -ccp <path> - Optional, path to the chaincode. When provided the -ccn will be used as the deployed name and not the short name of the known chaincodes." echo " -ccp <path> - Optional, path to the chaincode. When provided the -ccn will be used as the deployed name and not the short name of the known chaincodes."

View file

@ -62,6 +62,8 @@ if [ "$CC_SRC_PATH" = "NA" ]; then
CC_SRC_PATH="$CC_SRC_PATH/chaincode-java/" CC_SRC_PATH="$CC_SRC_PATH/chaincode-java/"
elif [ "$CC_SRC_LANGUAGE" = "javascript" ]; then elif [ "$CC_SRC_LANGUAGE" = "javascript" ]; then
CC_SRC_PATH="$CC_SRC_PATH/chaincode-javascript/" CC_SRC_PATH="$CC_SRC_PATH/chaincode-javascript/"
elif [ "$CC_SRC_LANGUAGE" = "typescript" ]; then
CC_SRC_PATH="$CC_SRC_PATH/chaincode-typescript/"
fi fi
# check that the language is available for the sample chaincode # check that the language is available for the sample chaincode
@ -99,9 +101,19 @@ elif [ "$CC_SRC_LANGUAGE" = "java" ]; then
elif [ "$CC_SRC_LANGUAGE" = "javascript" ]; then elif [ "$CC_SRC_LANGUAGE" = "javascript" ]; then
CC_RUNTIME_LANGUAGE=node CC_RUNTIME_LANGUAGE=node
elif [ "$CC_SRC_LANGUAGE" = "typescript" ]; then
CC_RUNTIME_LANGUAGE=node
echo Compiling TypeScript code into JavaScript ...
pushd $CC_SRC_PATH
npm install
npm run build
popd
echo Finished compiling TypeScript code into JavaScript
else else
echo The chaincode language ${CC_SRC_LANGUAGE} is not supported by this script echo The chaincode language ${CC_SRC_LANGUAGE} is not supported by this script
echo Supported chaincode languages are: go, java, and javascript echo Supported chaincode languages are: go, java, javascript, and typescript
exit 1 exit 1
fi fi