From a50f68d5aeefe65350b4321fc9df5e7c9e0314ed Mon Sep 17 00:00:00 2001 From: Simon Stone Date: Wed, 3 Oct 2018 09:31:00 +0100 Subject: [PATCH] [FABN-948] Add top-level Package class to SDK Introduce a new top-level class called Package, for working with chaincode packages. A chaincode package is the same format as created by the "peer chaincode package" command. This commit allows a user of the SDK to: - Load a chaincode package from an existing buffer/file and get information about it - Create a new chaincode package from a directory - Save a chaincode package to a buffer/file See FABN-948 for the details. Change-Id: I499c5bf7dd03a6aedad9c28f06a6c850e1a8ce41 Signed-off-by: Simon Stone --- build/tasks/test.js | 2 +- fabric-client/lib/Client.js | 2 + fabric-client/lib/Package.js | 145 +++++++++++++++ fabric-client/lib/client-utils.js | 25 +-- fabric-client/test/Package.js | 165 ++++++++++++++++++ fabric-client/test/client-utils.js | 23 +-- .../statedb/couchdb/indexes/indexOwner.json | 1 + .../data/go/src/golang-contract/.editorconfig | 18 ++ .../data/go/src/golang-contract/chaincode.go | 32 ++++ .../go/src/golang-contract/chaincode_test.go | 35 ++++ .../test/data/go/src/golang-contract/main.go | 16 ++ .../test/data/golang-contract-metadata.cds | Bin 0 -> 970 bytes fabric-client/test/data/golang-contract.cds | Bin 0 -> 854 bytes .../test/data/java-contract-metadata.cds | Bin 0 -> 1554 bytes fabric-client/test/data/java-contract.cds | Bin 0 -> 1443 bytes .../test/data/java-contract/build.gradle | 53 ++++++ .../test/data/java-contract/settings.gradle | 7 + .../src/main/java/org/example/Chaincode.java | 40 +++++ .../src/main/java/org/example/Start.java | 15 ++ .../test/java/org/example/ChaincodeTest.java | 45 +++++ .../data/javascript-contract-metadata.cds | Bin 0 -> 1995 bytes .../test/data/javascript-contract.cds | Bin 0 -> 1883 bytes .../data/javascript-contract/.editorconfig | 18 ++ .../data/javascript-contract/.eslintignore | 7 + .../data/javascript-contract/.eslintrc.js | 39 +++++ .../test/data/javascript-contract/index.js | 9 + .../data/javascript-contract/lib/chaincode.js | 27 +++ .../data/javascript-contract/lib/start.js | 12 ++ .../data/javascript-contract/package.json | 46 +++++ .../javascript-contract/test/chaincode.js | 48 +++++ .../data/javascript-contract/test/start.js | 32 ++++ fabric-client/test/data/packager.sh | 25 +++ .../data/typescript-contract-metadata.cds | Bin 0 -> 2160 bytes .../test/data/typescript-contract.cds | Bin 0 -> 2051 bytes .../data/typescript-contract/.editorconfig | 18 ++ .../data/typescript-contract/package.json | 61 +++++++ .../typescript-contract/src/chaincode.spec.ts | 46 +++++ .../data/typescript-contract/src/chaincode.ts | 23 +++ .../data/typescript-contract/src/index.ts | 7 + .../typescript-contract/src/start.spec.ts | 30 ++++ .../data/typescript-contract/src/start.ts | 10 ++ .../data/typescript-contract/tsconfig.json | 15 ++ .../test/data/typescript-contract/tslint.json | 21 +++ fabric-client/types/index.d.ts | 10 ++ scripts/check_license.sh | 4 +- 45 files changed, 1108 insertions(+), 24 deletions(-) create mode 100644 fabric-client/lib/Package.js create mode 100644 fabric-client/test/Package.js create mode 100644 fabric-client/test/data/META-INF/statedb/couchdb/indexes/indexOwner.json create mode 100755 fabric-client/test/data/go/src/golang-contract/.editorconfig create mode 100644 fabric-client/test/data/go/src/golang-contract/chaincode.go create mode 100644 fabric-client/test/data/go/src/golang-contract/chaincode_test.go create mode 100644 fabric-client/test/data/go/src/golang-contract/main.go create mode 100755 fabric-client/test/data/golang-contract-metadata.cds create mode 100755 fabric-client/test/data/golang-contract.cds create mode 100755 fabric-client/test/data/java-contract-metadata.cds create mode 100755 fabric-client/test/data/java-contract.cds create mode 100644 fabric-client/test/data/java-contract/build.gradle create mode 100644 fabric-client/test/data/java-contract/settings.gradle create mode 100644 fabric-client/test/data/java-contract/src/main/java/org/example/Chaincode.java create mode 100644 fabric-client/test/data/java-contract/src/main/java/org/example/Start.java create mode 100644 fabric-client/test/data/java-contract/src/test/java/org/example/ChaincodeTest.java create mode 100755 fabric-client/test/data/javascript-contract-metadata.cds create mode 100755 fabric-client/test/data/javascript-contract.cds create mode 100755 fabric-client/test/data/javascript-contract/.editorconfig create mode 100644 fabric-client/test/data/javascript-contract/.eslintignore create mode 100644 fabric-client/test/data/javascript-contract/.eslintrc.js create mode 100644 fabric-client/test/data/javascript-contract/index.js create mode 100644 fabric-client/test/data/javascript-contract/lib/chaincode.js create mode 100644 fabric-client/test/data/javascript-contract/lib/start.js create mode 100644 fabric-client/test/data/javascript-contract/package.json create mode 100644 fabric-client/test/data/javascript-contract/test/chaincode.js create mode 100644 fabric-client/test/data/javascript-contract/test/start.js create mode 100755 fabric-client/test/data/packager.sh create mode 100755 fabric-client/test/data/typescript-contract-metadata.cds create mode 100755 fabric-client/test/data/typescript-contract.cds create mode 100755 fabric-client/test/data/typescript-contract/.editorconfig create mode 100644 fabric-client/test/data/typescript-contract/package.json create mode 100644 fabric-client/test/data/typescript-contract/src/chaincode.spec.ts create mode 100644 fabric-client/test/data/typescript-contract/src/chaincode.ts create mode 100644 fabric-client/test/data/typescript-contract/src/index.ts create mode 100644 fabric-client/test/data/typescript-contract/src/start.spec.ts create mode 100644 fabric-client/test/data/typescript-contract/src/start.ts create mode 100644 fabric-client/test/data/typescript-contract/tsconfig.json create mode 100644 fabric-client/test/data/typescript-contract/tslint.json diff --git a/build/tasks/test.js b/build/tasks/test.js index ddc79189d5..9db6bbfea1 100644 --- a/build/tasks/test.js +++ b/build/tasks/test.js @@ -132,7 +132,7 @@ gulp.task('test-mocha', ['mocha-fabric-client'], gulp.task('mocha-fabric-client', () => { - return gulp.src(['./fabric-client/test/**/*.js'], { read: false }) + return gulp.src(['./fabric-client/test/**/*.js', '!./fabric-client/test/data/**/*.js'], { read: false }) .pipe(mocha({ reporter: 'list', exit: true })); } ); diff --git a/fabric-client/lib/Client.js b/fabric-client/lib/Client.js index 25f0cc3597..42b6075ebb 100644 --- a/fabric-client/lib/Client.js +++ b/fabric-client/lib/Client.js @@ -14,6 +14,7 @@ const api = require('./api.js'); const BaseClient = require('./BaseClient.js'); const User = require('./User.js'); const Channel = require('./Channel.js'); +const Package = require('./Package.js'); const Packager = require('./Packager.js'); const Peer = require('./Peer.js'); const ChannelEventHub = require('./ChannelEventHub'); @@ -1844,3 +1845,4 @@ module.exports.ChannelEventHub = ChannelEventHub; module.exports.Orderer = Orderer; module.exports.Channel = Channel; module.exports.User = User; +module.exports.Package = Package; diff --git a/fabric-client/lib/Package.js b/fabric-client/lib/Package.js new file mode 100644 index 0000000000..5f3af99617 --- /dev/null +++ b/fabric-client/lib/Package.js @@ -0,0 +1,145 @@ +/** + * Copyright 2018 IBM All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict'; + +const clientUtils = require('./client-utils.js'); +const grpc = require('grpc'); +const Packager = require('./Packager.js'); +const tar = require('tar-stream'); +const utils = require('./utils.js'); +const zlib = require('zlib'); + +const _ccProto = grpc.load(__dirname + '/protos/peer/chaincode.proto').protos; +const logger = utils.getLogger('package'); + +/** + * A class representing a smart contract package. + */ +class Package { + + /** + * Find the list of file names in the specified chaincode deployment specification. + * @private + * @param {ChaincodeDeploymentSpec} chaincodeDeploymentSpec The chaincode deployment specification. + * @returns {string[]} The list of file names. + */ + static async _findFileNames(chaincodeDeploymentSpec) { + const codePackage = chaincodeDeploymentSpec.getCodePackage().toBuffer(); + const gunzip = zlib.createGunzip(); + const extract = tar.extract(); + return new Promise((resolve) => { + const fileNames = []; + extract.on('entry', (header, stream, next) => { + logger.debug('Package._findFileNames - found entry %s', header.name); + fileNames.push(header.name); + stream.on('end', () => { + next(); + }); + stream.resume(); + }); + extract.on('finish', () => { + resolve(fileNames.sort()); + }); + gunzip.pipe(extract); + gunzip.end(codePackage); + }); + } + + /** + * Load a smart contract package from the specified buffer. + * @param {Buffer} buffer A buffer containing the serialized smart contract package. + * @returns {Package} The smart contract package. + */ + static async fromBuffer(buffer) { + const chaincodeDeploymentSpec = _ccProto.ChaincodeDeploymentSpec.decode(buffer); + const fileNames = await Package._findFileNames(chaincodeDeploymentSpec); + return new Package(chaincodeDeploymentSpec, fileNames); + } + + /** + * Create a new smart contract package from the specified directory. + * @param {Object} options The options for the packager. + * @param {string} options.name The name of the smart contract. + * @param {string} options.version The version of the smart contract. + * @param {string} options.path The directory containing the smart contract. + * @param {string} options.type The type of the smart contract, one of 'golang', 'car', 'node' or 'java'. + * @param {string} [options.metadataPath] The directory containing the metadata descriptors. + * @returns {Package} The smart contract package. + */ + static async fromDirectory({ name, version, path, type, metadataPath }) { + logger.debug('Package.fromDirectory - entry - %s, %s, %s, %s', name, version, path, type); + const codePackage = await Packager.package(path, type, false, metadataPath); + logger.debug('Package.fromDirectory - code package is %s bytes', codePackage.length); + const chaincodeSpec = { + type: clientUtils.translateCCType(type), + chaincode_id: { + name, + path, + version + } + }; + logger.debug('Package.fromDirectory - built chaincode specification %s', JSON.stringify(chaincodeSpec)); + const chaincodeDeploymentSpec = new _ccProto.ChaincodeDeploymentSpec(); + chaincodeDeploymentSpec.setChaincodeSpec(chaincodeSpec); + chaincodeDeploymentSpec.setCodePackage(codePackage); + const fileNames = await Package._findFileNames(chaincodeDeploymentSpec); + return new Package(chaincodeDeploymentSpec, fileNames); + } + + /** + * Constructor. + * @private + * @param {ChaincodeDeploymentSpec} chaincodeDeploymentSpec The chaincode deployment specification. + */ + constructor(chaincodeDeploymentSpec, fileNames) { + this.chaincodeDeploymentSpec = chaincodeDeploymentSpec; + this.fileNames = fileNames; + } + + /** + * Get the name of the smart contract package. + * @returns {string} The name of the smart contract package. + */ + getName() { + return this.chaincodeDeploymentSpec.getChaincodeSpec().getChaincodeId().getName(); + } + + /** + * Get the version of the smart contract package. + * @returns {string} The version of the smart contract package. + */ + getVersion() { + return this.chaincodeDeploymentSpec.getChaincodeSpec().getChaincodeId().getVersion(); + } + + /** + * Get the type of the smart contract package. + * @returns {string} The type of the smart contract package, one of 'golang', 'car', 'node' or 'java'. + */ + getType() { + return clientUtils.ccTypeToString(this.chaincodeDeploymentSpec.getChaincodeSpec().getType()); + } + + /** + * Get the list of file names in this smart contract package. + * @returns {string[]} The list of file names in this smart contract package. + */ + getFileNames() { + return this.fileNames; + } + + /** + * Save the smart contract package to a buffer. + * @returns {Buffer} A buffer containing the serialized smart contract package. + */ + async toBuffer() { + return this.chaincodeDeploymentSpec.toBuffer(); + } + +} + +module.exports = Package; diff --git a/fabric-client/lib/client-utils.js b/fabric-client/lib/client-utils.js index 761a4a97d7..c855f2204a 100644 --- a/fabric-client/lib/client-utils.js +++ b/fabric-client/lib/client-utils.js @@ -1,15 +1,7 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 +/** + * Copyright 2018 IBM All Rights Reserved. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 */ 'use strict'; @@ -195,6 +187,17 @@ module.exports.translateCCType = (type) => { return value; }; +module.exports.ccTypeToString = (ccType) => { + const map = {}; + map[_ccProto.ChaincodeSpec.Type.GOLANG] = 'golang'; + map[_ccProto.ChaincodeSpec.Type.CAR] = 'car'; + map[_ccProto.ChaincodeSpec.Type.JAVA] = 'java'; + map[_ccProto.ChaincodeSpec.Type.NODE] = 'node'; + const value = map[ccType]; + + return value; +}; + /* * This function will create a timestamp from the current time */ diff --git a/fabric-client/test/Package.js b/fabric-client/test/Package.js new file mode 100644 index 0000000000..645266ec03 --- /dev/null +++ b/fabric-client/test/Package.js @@ -0,0 +1,165 @@ +/** + * Copyright 2018 IBM All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict'; + +const fs = require('fs'); +const Package = require('..').Package; +const path = require('path'); + +const chai = require('chai'); +chai.should(); +chai.use(require('chai-as-promised')); + +const languages = ['golang', 'javascript', 'typescript', 'java']; + +const languageToType = { + golang: 'golang', + javascript: 'node', + typescript: 'node', + java: 'java' +}; + +const fileNames = { + golang: [ + 'src/golang-contract/chaincode.go', + 'src/golang-contract/chaincode_test.go', + 'src/golang-contract/main.go' + ], + javascript: [ + 'src/.editorconfig', + 'src/.eslintignore', + 'src/.eslintrc.js', + 'src/index.js', + 'src/lib/chaincode.js', + 'src/lib/start.js', + 'src/package.json', + 'src/test/chaincode.js', + 'src/test/start.js' + ], + typescript: [ + 'src/.editorconfig', + 'src/package.json', + 'src/src/chaincode.spec.ts', + 'src/src/chaincode.ts', + 'src/src/index.ts', + 'src/src/start.spec.ts', + 'src/src/start.ts', + 'src/tsconfig.json', + 'src/tslint.json' + ], + java: [ + 'src/build.gradle', + 'src/settings.gradle', + 'src/src/main/java/org/example/Chaincode.java', + 'src/src/main/java/org/example/Start.java', + 'src/src/test/java/org/example/ChaincodeTest.java' + ] +}; + +const metadataFileNames = [ + 'META-INF/statedb/couchdb/indexes/indexOwner.json' +]; + +describe('Package', () => { + + let GOPATH; + + beforeEach(() => { + GOPATH = process.env.GOPATH; + process.env.GOPATH = path.resolve(__dirname, 'data', 'go'); + }); + + afterEach(() => { + process.env.GOPATH = GOPATH; + }); + + describe('#fromBuffer', () => { + + for (const language of languages) { + + const type = languageToType[language]; + + it(`should load a smart contract package from a buffer [${language}]`, async () => { + const pkgFile = path.resolve(__dirname, 'data', `${language}-contract.cds`); + const pkgBuffer = fs.readFileSync(pkgFile); + const pkg = await Package.fromBuffer(pkgBuffer); + pkg.getName().should.equal('my-contract'); + pkg.getVersion().should.equal('1.2.3'); + pkg.getType().should.equal(type); + pkg.getFileNames().should.deep.equal(fileNames[language]); + }); + + it(`should load a smart contract package from a buffer with metadata [${language}]`, async () => { + const pkgFile = path.resolve(__dirname, 'data', `${language}-contract-metadata.cds`); + const pkgBuffer = fs.readFileSync(pkgFile); + const pkg = await Package.fromBuffer(pkgBuffer); + pkg.getName().should.equal('my-contract'); + pkg.getVersion().should.equal('1.2.3'); + pkg.getType().should.equal(type); + pkg.getFileNames().should.deep.equal(metadataFileNames.concat(fileNames[language])); + }); + + } + + }); + + describe('#fromDirectory', () => { + + for (const language of languages) { + + const type = languageToType[language]; + + it(`should create a smart contract package from a directory [${language}]`, async () => { + let pkgDirectory; + if (language === 'golang') { + pkgDirectory = `${language}-contract`; + } else { + pkgDirectory = path.resolve(__dirname, 'data', `${language}-contract`); + } + const pkg = await Package.fromDirectory({ name: 'my-contract', version: '1.2.3', path: pkgDirectory, type }); + pkg.getName().should.equal('my-contract'); + pkg.getVersion().should.equal('1.2.3'); + pkg.getType().should.equal(type); + pkg.getFileNames().should.deep.equal(fileNames[language]); + }); + + it(`should create a smart contract package from a directory with metadata [${language}]`, async () => { + let pkgDirectory; + if (language === 'golang') { + pkgDirectory = `${language}-contract`; + } else { + pkgDirectory = path.resolve(__dirname, 'data', `${language}-contract`); + } + const metaDirectory = path.resolve(__dirname, 'data', 'META-INF'); + const pkg = await Package.fromDirectory({ name: 'my-contract', version: '1.2.3', path: pkgDirectory, type, metadataPath: metaDirectory }); + pkg.getName().should.equal('my-contract'); + pkg.getVersion().should.equal('1.2.3'); + pkg.getType().should.equal(type); + pkg.getFileNames().should.deep.equal(metadataFileNames.concat(fileNames[language])); + }); + + } + + }); + + describe('#toBuffer', async () => { + + for (const language of languages) { + + it(`should save a smart contract package to a buffer [${language}]`, async () => { + const pkgFile = path.resolve(__dirname, 'data', `${language}-contract.cds`); + const pkgBuffer1 = fs.readFileSync(pkgFile); + const pkg = await Package.fromBuffer(pkgBuffer1); + const pkgBuffer2 = await pkg.toBuffer(); + Buffer.compare(pkgBuffer1, pkgBuffer2).should.equal(0); + }); + + } + + }); + +}); diff --git a/fabric-client/test/client-utils.js b/fabric-client/test/client-utils.js index e337b002ff..68d3bc8bc0 100644 --- a/fabric-client/test/client-utils.js +++ b/fabric-client/test/client-utils.js @@ -1,15 +1,7 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at +/** + * Copyright 2018 IBM All Rights Reserved. * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 */ 'use strict'; @@ -358,6 +350,15 @@ describe('client-utils', () => { }); }); + describe('#ccTypeToString', () => { + it('should return the correct string', () => { + ClientUtils.ccTypeToString(ClientUtils.__get__('_ccProto.ChaincodeSpec.Type.GOLANG')).should.equal('golang'); + ClientUtils.ccTypeToString(ClientUtils.__get__('_ccProto.ChaincodeSpec.Type.CAR')).should.equal('car'); + ClientUtils.ccTypeToString(ClientUtils.__get__('_ccProto.ChaincodeSpec.Type.JAVA')).should.equal('java'); + ClientUtils.ccTypeToString(ClientUtils.__get__('_ccProto.ChaincodeSpec.Type.NODE')).should.equal('node'); + }); + }); + describe('#buildCurrentTimestamp', () => { let setSecondsStub; let setNanosStub; diff --git a/fabric-client/test/data/META-INF/statedb/couchdb/indexes/indexOwner.json b/fabric-client/test/data/META-INF/statedb/couchdb/indexes/indexOwner.json new file mode 100644 index 0000000000..305f090444 --- /dev/null +++ b/fabric-client/test/data/META-INF/statedb/couchdb/indexes/indexOwner.json @@ -0,0 +1 @@ +{"index":{"fields":["docType","owner"]},"ddoc":"indexOwnerDoc", "name":"indexOwner","type":"json"} diff --git a/fabric-client/test/data/go/src/golang-contract/.editorconfig b/fabric-client/test/data/go/src/golang-contract/.editorconfig new file mode 100755 index 0000000000..b046e3959d --- /dev/null +++ b/fabric-client/test/data/go/src/golang-contract/.editorconfig @@ -0,0 +1,18 @@ +# +# Copyright 2018 IBM All Rights Reserved. +# +# 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 diff --git a/fabric-client/test/data/go/src/golang-contract/chaincode.go b/fabric-client/test/data/go/src/golang-contract/chaincode.go new file mode 100644 index 0000000000..9f8a34b590 --- /dev/null +++ b/fabric-client/test/data/go/src/golang-contract/chaincode.go @@ -0,0 +1,32 @@ +/** + * Copyright 2018 IBM All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package main + +import ( + "fmt" + + "github.com/hyperledger/fabric/core/chaincode/shim" + sc "github.com/hyperledger/fabric/protos/peer" +) + +// Chaincode is the definition of the chaincode structure. +type Chaincode struct { +} + +// Init is called when the chaincode is instantiated by the blockchain network. +func (cc *Chaincode) Init(stub shim.ChaincodeStubInterface) sc.Response { + fcn, params := stub.GetFunctionAndParameters() + fmt.Println("Init()", fcn, params) + return shim.Success(nil) +} + +// Invoke is called as a result of an application request to run the chaincode. +func (cc *Chaincode) Invoke(stub shim.ChaincodeStubInterface) sc.Response { + fcn, params := stub.GetFunctionAndParameters() + fmt.Println("Invoke()", fcn, params) + return shim.Success(nil) +} diff --git a/fabric-client/test/data/go/src/golang-contract/chaincode_test.go b/fabric-client/test/data/go/src/golang-contract/chaincode_test.go new file mode 100644 index 0000000000..3e6ee46fa3 --- /dev/null +++ b/fabric-client/test/data/go/src/golang-contract/chaincode_test.go @@ -0,0 +1,35 @@ +/** + * Copyright 2018 IBM All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package main + +import ( + "testing" + + "github.com/hyperledger/fabric/core/chaincode/shim" +) + +func TestInit(t *testing.T) { + cc := new(Chaincode) + stub := shim.NewMockStub("chaincode", cc) + res := stub.MockInit("1", [][]byte{[]byte("initFunc")}) + if res.Status != shim.OK { + t.Error("Init failed", res.Status, res.Message) + } +} + +func TestInvoke(t *testing.T) { + cc := new(Chaincode) + stub := shim.NewMockStub("chaincode", cc) + res := stub.MockInit("1", [][]byte{[]byte("initFunc")}) + if res.Status != shim.OK { + t.Error("Init failed", res.Status, res.Message) + } + res = stub.MockInvoke("1", [][]byte{[]byte("invokeFunc")}) + if res.Status != shim.OK { + t.Error("Invoke failed", res.Status, res.Message) + } +} diff --git a/fabric-client/test/data/go/src/golang-contract/main.go b/fabric-client/test/data/go/src/golang-contract/main.go new file mode 100644 index 0000000000..69e342267f --- /dev/null +++ b/fabric-client/test/data/go/src/golang-contract/main.go @@ -0,0 +1,16 @@ +/** + * Copyright 2018 IBM All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package main + +import "github.com/hyperledger/fabric/core/chaincode/shim" + +func main() { + err := shim.Start(new(Chaincode)) + if err != nil { + panic(err) + } +} diff --git a/fabric-client/test/data/golang-contract-metadata.cds b/fabric-client/test/data/golang-contract-metadata.cds new file mode 100755 index 0000000000000000000000000000000000000000..9790ebcd4e1a33bec0d8528baf700d11dfd0bedd GIT binary patch literal 970 zcmV;*12y~#D+mD+B?=E`Z){<1XDwrIZgg^CV{{S=ZFwzYZ*FvQVPkX}1u-r%E;AYc z8kz?miwFP!00000|Lm7tZz4Ar$8(E6#aUm?ATl!~EIdNmi#+>Mp*Fiw$VH_ns*L9h zxD58xKC=`dzI$bp5{R0lNw-05`QI3g?ejK1KM&_0ug;DKpFgFJ1Ytf(rK#m4AEip? z_$#{g_+_rqCONgz1p4A&F?JBj?O{gtJ;yU zM_J|^8IA1+*EteJ@ra#G@VDbXL`xoCFz+vUp|H#y?_cxW$g4$#yv2=w@%(1h;(2Z) z@AJFk@WDvl0aRiQREvdGcFpsjW&FdLhvQ@A;(2Bf4DasOam`_mO zGo>6T?MP@+{(gngA}kn{Moz;j&`5J*rwJ=+Eg_N;nj3#{@DMqwN8qzhHZw!2M*~f0 z3n4KECzDHbmC+7i$r^>!EvSSQGY9>5;P)rrA$_W~^ckP&{K8Knp>=<1Sug@p!DRi%<5)ZF4P zH97(^VC#EDd$1JV!>bn~IDJ+*_TAIZ(WCtTiO|tszXYD*f2Y&F_x+dkx^EBse+})4 z|NdYpJ$~sO5VJKRuFz4y6+!dXWO5bzrkB$9y2g2QM-bKs?C=cmUHcj5=SEIFJR-jF zz*`_?=m8z8?p^aSc-Px sw}ydV_2wODRR#i7LMs`ewf~LQKIou>4ti9-1pom5|8G=+(Eu0#0LX*a`~Uy| literal 0 HcmV?d00001 diff --git a/fabric-client/test/data/golang-contract.cds b/fabric-client/test/data/golang-contract.cds new file mode 100755 index 0000000000000000000000000000000000000000..ea5b2486cdc98193aa14e76c8e4f6d54e5fe192a GIT binary patch literal 854 zcmV-c1F8H9D+mD+B?=E`Z){<1XDwrIZgg^CV{{S=ZFwzYZ*FvQVPkX}1u-r%E;AYc z8m0yxiwFP!00000|Lm6EZ`(Ey$MY)w6<0k;h9l9b8xIBgkaa&0Y}tai4+Dx~psABg zSSGdOseuvXe;-I^juR}&(q##@`TIgaJl-$pK9nb2Hm+5++1Ji8Db1yxD`T~*uxQ-g z6G)DvJRFbrq?B@UcypCfj@}$>o`d$}Xfk;%_dq^H@Q2iURiQl( zo8+(7e~HS$K)?XryKY6MnKK;7(N}Q%^$8rcEu4i{9?sAsea5N~5Ur=D-~6)wqtR$R z?jKiZ+0+KQ|@QSmXT_uF$b@UGxVLa9^pbH zwYEd(6se_$x9=dFFTO|quD3c=d}OQBu!)T1vs@(gl8aL^mRp;pF=U<&VarP{5<>3D zuG5(ITBG-wHEq6W#b>v`t!5|>3J87Qa_F$Kpt`O#TE(6d{??;sU@|{$lfAdO-hS{Tctmv_8?V zf7Ao~m#-(c|Njps02@cE*8l(j literal 0 HcmV?d00001 diff --git a/fabric-client/test/data/java-contract-metadata.cds b/fabric-client/test/data/java-contract-metadata.cds new file mode 100755 index 0000000000000000000000000000000000000000..e089fa4c795339fda6cdc3ffc835e3a60646ab68 GIT binary patch literal 1554 zcmV+t2JQI@DF_4-BMJ>_VRm6HV{dMBa$#e15({m4En{zPbaG*1bQ%RQE;24N8UPyP z3m=OJ000000095&Szk}%I1uMKpTdf?YRa`vS_-VnaXOY|b*z>@qP^2ed;8!z)7FsK zJ$q6>sNel$C$tGHu&@X0>H2$UT6@Nx8IL_brw4oeo#y`GhtMEHhzB8886U@kP{a5MbM^UsAwcDMIXoW;ine4I13^KhE zMaH0#(7IF3AR7+v8E0;M@%)eA%6ALwcdz`RfFw44_p=`>-oKoH-|&@Pc>l|+;m5J! ze%D{5!+XX32Jt0Jq0;U*e6-44-{y-y^IqGqiRnnQIDzMwN+*;SKEEkkBOpc9Bkpy`kewBSuXWQBJH;58jYI0!=2;aZ%6&w zo#Wd>uj@W+B%`;jwOkg#;QkHy(@YBN=ARwfYTqqsM@|(#6R5hyv&of)Zkzt(yw@;M zMxfFQ?@u{M1Rd1fuar$e7Cjc3PKZB7oS1GHO1Q{OB{WKpLaro&#IQVeXe67Mu|gC2 zZmgM|Jzu)$Sg@*6Hk~iE`!RgDU)Id21_uWjkSewd5-kK;I5j2W+V6mv=|DW$2K3H4H5L-lqDHM zC{5{XdoMKbBDULPC=xKi%?|3CDOX7Xylk|E?dxlRAQrky1U3j<@Fa_&OUUPn6Ed{)CoC79-Rs&-ZP!!h zc!>W;?e!b?|JLT_a{s>wo|*qMe#S;XO7v{Y^F(S%0kJ7XGZYE^Bn&Rvzs}OBW#M$5 zknfm*tw(9}FdI}fEJ>%UTb?(`28rM~)gyCx0vBlc45`dXt~|$k3Y~dhP%qJ_kG-SA zzB&U5nqcwVCKAreJ%N8U^Xpp`rK5p8Dv3QdOA2{wP>fVk>0KIxl&TErL<@>h&#e!E6CD zEvpMfC7ky%&cT>#XM@KDW~$EMhYO7}>RW>I^w=!l*!_=ifBnxdp5IgZSH6M&uXS$K z|8{%%{{Kbr8uh{NHi#ObVnnyXMrq*!+v$9b-VF zW$L#jig)4kpm?r+?Rw!z(G%_%w{8p%YS3#s^+Yw=Lx!2T^G?#w--qY))&3}-n(nxC ze;(undT~lF?lhbi_lnY?xpiA^PIk#Qu_3O~VCt+Y>79>32Dj;No#Ghei6fvnt+##t zU5aHETv4_5&e!moMOR4foV9EBhMsfkE)kBdFQk}Dq`kj0mY5)qH0}MqySvxxHLRvJ zB5$4#K6^OU1tVWZ`}?E)2=8pvpUc0JTW)dxl{8wikR_H_;s?V&0RRC1|3@j}+5jj3 E06c*M1ONa4 literal 0 HcmV?d00001 diff --git a/fabric-client/test/data/java-contract.cds b/fabric-client/test/data/java-contract.cds new file mode 100755 index 0000000000000000000000000000000000000000..453132e066b7f050426ced95483038143172d46a GIT binary patch literal 1443 zcmV;U1zh?HDF_4-BMJ>_VRm6HV{dMBa$#e15({m4En{zPbaG*1bQ%RQE;24N8UPyg z3LlFI000000095&SzmA4HW1IVJ_Qk=u$;w|?EG=zEW^^Y!&zpg_ak}tqhd47z>xH}X-&WSb?)L6Ze~p9>;moq+2AN(9Lt{`$=-#Mjkd4Q;j8i#ZKK~~Y zY;1UBgB+^tN{e`cq!)Idlh-fak%J^5C$`Cu6EL8s5K)gf?cwpuzdCOP2Wg=5Is%De zEI<#)LB{w5Iz1YCWFzprEXiXb4f*5|LWqb+i>s8z0w?*1o~en{AY({UCaIaQNL{qZ z6todal2(s~bh}j2W=EB44K7(7%{&@6^OL5s2A1-8ZTY>c2^O<9sNgxZwOx0gZ#FR|Sx zW08RImpiCyrd%Zn@Ve7hY~QH{@FSrIMBpZYOP=Hr3<&wq(432nC@3QeTtsxE)zJLd zu3l&DGFk_)P>GA|Bu}cnU`6K%Ecum)R4n`IuoqIKc}n(4*B<4X%)I6=hcKT2Kc~e3 zG)Iyw5I=!TY1|~YuYvc}S@6ddTmKCp3K^S+q5yZ)|FGNdFV+8@?cUC+{y&C1Z2i|t z;jva{z>&(b9;8i~onco#y%P zb^HC*`F|97VE)heIg5eR=-Hm zk#JG(@z+1i*4ujxqoa{cmBgmannBU(mm}3ohF1n5r7B07X(2I@zBMg1W`(D}9!)`O z5kcMW6EK;Q28fUX{RT$FU_PoxGej+9Ovc=jcH2o~z~6GoEp_v2?$~AgxzPTFWK6Tv z)GUr|10ZPQ-x9*uUw1CG$umQqnZM=wrk#1S9FL+p(3)NO?e?CxV77p{md%Bt5-x^0 z=U~h{SpVyQnW}U6?x1l_eF-@C$7Z&w%0G_WUjK`W=eN}UwJ+fRTie&_f3Fv=>i=WN zQ`G-Py>(k`sj3=eC^(ra5fQsF{UURI_(+(JO+5kI5?QOk)Gj9aPHUCVzC`BdAHm=) z{Qnfp{qw+G{C{U>Yw7&=cKf@l^Zyv~g#6!e@LUR{c6U|OygdAi-UDMmqh;#XHOg<{ z^j-Pf_}ulvk)nItF|OSh?zEtDI(1JoIz)!Kx$#bNT6_;L=&OCHXHAzb-9HZs0=>wR zi#rYH<-MYoH21FSRb-d!6AN*Z22v7kbXAyF@s;zR+TBBfa`3XNmC(r0MXF!^2m@;ik2;P87}6;Iq52 xE*bd>?Qci>E26WgKU93Ru-xMQC);SnLRPYpm3(LNZvX%Q|NjNu$tM6L0015u+wTAX literal 0 HcmV?d00001 diff --git a/fabric-client/test/data/java-contract/build.gradle b/fabric-client/test/data/java-contract/build.gradle new file mode 100644 index 0000000000..17881c67fd --- /dev/null +++ b/fabric-client/test/data/java-contract/build.gradle @@ -0,0 +1,53 @@ +/** + * Copyright 2018 IBM All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +plugins { + id 'com.github.johnrengelman.shadow' version '2.0.4' + id 'java-library' + id 'jacoco' +} + +dependencies { + implementation 'org.hyperledger.fabric-chaincode-java:fabric-chaincode-shim:1.3.0-SNAPSHOT' + implementation 'org.json:json:20180813' + testImplementation 'junit:junit:4.12' + testImplementation 'org.mockito:mockito-core:2.+' +} + +repositories { + jcenter() + maven { + url "https://nexus.hyperledger.org/content/repositories/snapshots/" + } +} + +shadowJar { + baseName = 'chaincode' + version = null + classifier = null + manifest { + attributes 'Main-Class': 'org.example.Start' + } +} + +jacocoTestCoverageVerification { + afterEvaluate { + classDirectories = files(classDirectories.files.collect { + fileTree(dir: it, exclude: [ + 'org/example/Start.*' + ]) + }) + } + violationRules { + rule { + limit { + minimum = 1.0 + } + } + } +} + +check.dependsOn jacocoTestReport, jacocoTestCoverageVerification diff --git a/fabric-client/test/data/java-contract/settings.gradle b/fabric-client/test/data/java-contract/settings.gradle new file mode 100644 index 0000000000..4a4e7a930a --- /dev/null +++ b/fabric-client/test/data/java-contract/settings.gradle @@ -0,0 +1,7 @@ +/** + * Copyright 2018 IBM All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +rootProject.name = 'my-contract' diff --git a/fabric-client/test/data/java-contract/src/main/java/org/example/Chaincode.java b/fabric-client/test/data/java-contract/src/main/java/org/example/Chaincode.java new file mode 100644 index 0000000000..1cf59da3e3 --- /dev/null +++ b/fabric-client/test/data/java-contract/src/main/java/org/example/Chaincode.java @@ -0,0 +1,40 @@ +/** + * Copyright 2018 IBM All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.example; + +import java.util.List; + +import org.hyperledger.fabric.shim.ChaincodeBase; +import org.hyperledger.fabric.shim.ChaincodeStub; +import org.json.*; + +public class Chaincode extends ChaincodeBase { + + public Chaincode() { + JSONTokener tokener = new JSONTokener("{}"); + JSONObject root = new JSONObject(tokener); + System.out.println(root); + } + + @Override + public Response init(ChaincodeStub stub) { + String fcn = stub.getFunction(); + List params = stub.getParameters(); + System.out.printf("init() %s %s\n", fcn, params.toArray()); + + return ChaincodeBase.newSuccessResponse(); + } + + @Override + public Response invoke(ChaincodeStub stub) { + String fcn = stub.getFunction(); + List params = stub.getParameters(); + System.out.printf("invoke() %s %s\n", fcn, params.toArray()); + return ChaincodeBase.newSuccessResponse(); + } + +} diff --git a/fabric-client/test/data/java-contract/src/main/java/org/example/Start.java b/fabric-client/test/data/java-contract/src/main/java/org/example/Start.java new file mode 100644 index 0000000000..69be5e38e8 --- /dev/null +++ b/fabric-client/test/data/java-contract/src/main/java/org/example/Start.java @@ -0,0 +1,15 @@ +/** + * Copyright 2018 IBM All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.example; + +public class Start { + + public static void main(String[] args) { + new Chaincode().start(args); + } + +} diff --git a/fabric-client/test/data/java-contract/src/test/java/org/example/ChaincodeTest.java b/fabric-client/test/data/java-contract/src/test/java/org/example/ChaincodeTest.java new file mode 100644 index 0000000000..e8bb6f1613 --- /dev/null +++ b/fabric-client/test/data/java-contract/src/test/java/org/example/ChaincodeTest.java @@ -0,0 +1,45 @@ +/** + * Copyright 2018 IBM All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.example; + +import org.junit.Test; +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +import java.util.ArrayList; + +import org.hyperledger.fabric.shim.ChaincodeStub; +import org.hyperledger.fabric.shim.Chaincode.Response; +import org.hyperledger.fabric.shim.Chaincode.Response.Status; + +public class ChaincodeTest { + + @Test + public void testInit() { + Chaincode cc = new Chaincode(); + ChaincodeStub stub = mock(ChaincodeStub.class); + when(stub.getFunction()).thenReturn("initFunc"); + when(stub.getParameters()).thenReturn(new ArrayList()); + Response res = cc.init(stub); + assertEquals(Status.SUCCESS, res.getStatus()); + } + + @Test + public void testInvoke() { + Chaincode cc = new Chaincode(); + ChaincodeStub stub = mock(ChaincodeStub.class); + when(stub.getFunction()).thenReturn("initFunc"); + when(stub.getParameters()).thenReturn(new ArrayList()); + Response res = cc.init(stub); + assertEquals(Status.SUCCESS, res.getStatus()); + when(stub.getFunction()).thenReturn("invokeFunc"); + when(stub.getParameters()).thenReturn(new ArrayList()); + res = cc.invoke(stub); + assertEquals(Status.SUCCESS, res.getStatus()); + } + +} diff --git a/fabric-client/test/data/javascript-contract-metadata.cds b/fabric-client/test/data/javascript-contract-metadata.cds new file mode 100755 index 0000000000000000000000000000000000000000..5f7ceace7b118043079466bc02310b0fcd38988d GIT binary patch literal 1995 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", + "npm": ">=5" + }, + "scripts": { + "lint": "eslint .", + "pretest": "npm run lint", + "test": "nyc mocha --recursive", + "start": "node lib/start.js" + }, + "engineStrict": true, + "author": "Simon Stone", + "license": "Apache-2.0", + "dependencies": { + "fabric-shim": "1.3.0-snapshot.17" + }, + "devDependencies": { + "chai": "^4.1.2", + "eslint": "^4.19.1", + "mocha": "^5.2.0", + "nyc": "^12.0.2", + "sinon": "^6.0.0", + "sinon-chai": "^3.2.0" + }, + "nyc": { + "exclude": [ + "coverage/**", + "test/**" + ], + "reporter": [ + "text-summary", + "html" + ], + "all": true, + "check-coverage": true, + "statements": 100, + "branches": 100, + "functions": 100, + "lines": 100 + } +} diff --git a/fabric-client/test/data/javascript-contract/test/chaincode.js b/fabric-client/test/data/javascript-contract/test/chaincode.js new file mode 100644 index 0000000000..d22af64a26 --- /dev/null +++ b/fabric-client/test/data/javascript-contract/test/chaincode.js @@ -0,0 +1,48 @@ +/** + * Copyright 2018 IBM All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict'; + +const { ChaincodeStub } = require('fabric-shim'); +const { Chaincode } = require('..'); + +const chai = require('chai'); +const sinon = require('sinon'); +const sinonChai = require('sinon-chai'); + +chai.should(); +chai.use(sinonChai); + +describe('Chaincode', () => { + + describe('#Init', () => { + + it('should work', async () => { + const cc = new Chaincode(); + const stub = sinon.createStubInstance(ChaincodeStub); + stub.getFunctionAndParameters.returns({ fcn: 'initFunc', params: [] }); + const res = await cc.Init(stub); + res.status.should.equal(ChaincodeStub.RESPONSE_CODE.OK); + }); + + }); + + describe('#Invoke', async () => { + + it('should work', async () => { + const cc = new Chaincode(); + const stub = sinon.createStubInstance(ChaincodeStub); + stub.getFunctionAndParameters.returns({ fcn: 'initFunc', params: [] }); + let res = await cc.Init(stub); + res.status.should.equal(ChaincodeStub.RESPONSE_CODE.OK); + stub.getFunctionAndParameters.returns({ fcn: 'invokeFunc', params: [] }); + res = await cc.Invoke(stub); + res.status.should.equal(ChaincodeStub.RESPONSE_CODE.OK); + }); + + }); + +}); diff --git a/fabric-client/test/data/javascript-contract/test/start.js b/fabric-client/test/data/javascript-contract/test/start.js new file mode 100644 index 0000000000..22ad8997a6 --- /dev/null +++ b/fabric-client/test/data/javascript-contract/test/start.js @@ -0,0 +1,32 @@ +/** + * Copyright 2018 IBM All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +'use strict'; + +const { Shim } = require('fabric-shim'); +const { Chaincode } = require('..'); + +const chai = require('chai'); +const sinon = require('sinon'); +const sinonChai = require('sinon-chai'); + +chai.should(); +chai.use(sinonChai); + +describe('start', () => { + + afterEach(() => { + sinon.restore(); + delete require.cache[require.resolve('../lib/start')]; + }); + + it('should work', () => { + const startStub = sinon.stub(Shim, 'start'); + require('../lib/start'); + startStub.should.have.been.calledOnceWithExactly(sinon.match.instanceOf(Chaincode)); + }); + +}); diff --git a/fabric-client/test/data/packager.sh b/fabric-client/test/data/packager.sh new file mode 100755 index 0000000000..b535f66e0e --- /dev/null +++ b/fabric-client/test/data/packager.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +# +# Copyright 2018 IBM All Rights Reserved. +# +# SPDX-License-Identifier: Apache-2.0 +# +set -ex +cd $(dirname $0) +export GOPATH=$PWD/go +peer chaincode package -l golang -n my-contract -v 1.2.3 -p golang-contract golang-contract.cds +cp -rf META-INF go/src/golang-contract/ +peer chaincode package -l golang -n my-contract -v 1.2.3 -p golang-contract golang-contract-metadata.cds +rm -rf go/src/golang-contract/META-INF +peer chaincode package -l node -n my-contract -v 1.2.3 -p javascript-contract javascript-contract.cds +cp -rf META-INF javascript-contract/ +peer chaincode package -l node -n my-contract -v 1.2.3 -p javascript-contract javascript-contract-metadata.cds +rm -rf javascript-contract/META-INF +peer chaincode package -l node -n my-contract -v 1.2.3 -p typescript-contract typescript-contract.cds +cp -rf META-INF typescript-contract/ +peer chaincode package -l node -n my-contract -v 1.2.3 -p typescript-contract typescript-contract-metadata.cds +rm -rf typescript-contract/META-INF +peer chaincode package -l java -n my-contract -v 1.2.3 -p java-contract java-contract.cds +cp -rf META-INF java-contract/ +peer chaincode package -l java -n my-contract -v 1.2.3 -p java-contract java-contract-metadata.cds +rm -rf java-contract/META-INF diff --git a/fabric-client/test/data/typescript-contract-metadata.cds b/fabric-client/test/data/typescript-contract-metadata.cds new file mode 100755 index 0000000000000000000000000000000000000000..9aadc41a53bfa4d41ae6df304e520cbf52944518 GIT binary patch literal 2160 zcmV-$2#@y)F9-q>DGC#Gd2nTOV{&P5bS-0VZgg^CV{{S=ZFwzYZ*FvQVPkX}1u-r% zE;AYc8oUr6iwFP!00000|LhxKZ`(SqpZzNY??cicR-80#cj@)vc54R|_ulKU47dY| zu25tq)@n`3;))bSi6TYOw34)kA!1rcD)^Mm_P#!Z z{V+Tl4)?+^43CfMzXpbbgYr2H!@aP77#W@ogkH=EjUgD|(0k^2QV5Msk(L>F-c{$?W8Bc*D7{Poogy_S6v{^Sf73Sf zfJZlCdXq42{!XSIjfqrXIAwYoJomI@>5Z0zC5+E*7BSOcITb@Ou0ZOWDdQx$;jqX# z6=L8ty8aZ8DM=J~-&-YHh2PHKz6dUUf7Mf(Xow~~Dl!^Jlb+GdJt+5kx!@r2dnNdn zjPaEH_lFJp9}I>^;m-cI0S~@aus?e6rwo!v`J*d867=nI4u01cM)CgjW7m%&LH&`x z+74%e`d#F6l0vQB@A}$w9{Fa!_>VuAJ^g54&i^@~w`2xiY~N486ZSu-`T}?U508$I zclN&xc<>NHg%u+|T?SNeEeX|r*P-q}DkiwW_VEB86zvfxD%o7;xVNCnE-7KQEn-T$ z0|dWU1yV2PjL%d9A7Ncm0G}}qhQdkbBovXA@R!r)Ih|{sr>^zTw~dcE4<}oLN5Z%^ z)LNM*6j0=z?9N9mV+);5uYN4a6R!5fN zu(GGC6vcjf*AMXlKH5N`7$EDa-+0Er%tmi8-iZ>hje(@g;R~4RBcR zv=ZnDhxJZRNs@0>i#%?2c1Ds*({CcpOs%n5f&u;q9@G`)1g&)!SmNx69G?c@zHSip9!1 znsLl8R&7#%U=5@p68;U3A9_Kw5={`@1xUS(1T}9ZAJ3zf-~Jj8(_NK zawDOIkhiTaB5KKLNm%tWRB)vcrRWrKSgaPw$hc0Y%sQXCnPMt|XuI?mTxr57v}+1! za4>!G4D_qqtGwXRYa&Ss8l=J!bSAlKKcFe)Bh+G?S;|%y%?*_rp{r~3xKSzz3Y{Xd zAk54Jn`LRMbpa$OY}{a`ay?-9kddS=G=6hFetr4-`26PO<=HvD{7;368QrTr)Rb{2 zZeeY$e?p}susxN0$sCNHo}R_p3{1BzY%BBM_jccZ8rIMMuX^-bc;fu;55hq+|34h= z&i}2zw$J|yu0c)-g>F42=%R7V(vL(29^6|#G$Be=!ULAh6BjCP7@%tA6~k* zQGNLR5qd2}$`t&Q@MYD@JI`%>QsITrqjBP&@?}-`Zy1OKFym9vZdn2LTiq(Z3bFHn zb}g{VCYuC6YU6w=iB=X>0%b zq@LVZ&sa2vFY*sW>Txv*VS>K4QBD`-Gpa>yR*L56D}s_=ai5OK9pDK7$CM-qM3TY?+Mk((yb*{HsQdr#6#uQ||A)unVCVn00e^k} z?=FsJd$t=X)}4R&^I&XWD_8patqOpitp7deH{-v4xV!&t1@ihID$+SiKwi#^*T|Lk z^&-<}Ocn(@wU_@y&cMF-2Q>)$$Mq71C`;gtiD0s#NXXV0tkD<@6=^DXz1AfHnh;6y z&bEjbRq6^DUw{4YyGW(e>E*BZuZxP74YdLl;<6&gb^3YIQqKO%BB*aN##8sd@bG9Y z|I^={|675FqNr+0vP6&J4kXjIJPf21vMkBF*T5rHHy^ieMiPwi0*@f7+uVEgCQDp} zR$;TUXjpM^9|0K7wh#vSwi;jgT{OII6tYYtklVn1Lr|gr^_5>G{E!I^DUr8TmWzZ@5 miaKKws20-9@#-gXiaXfB4tDSpz#jns0RR6xd>6w2IsgFrFgi>C literal 0 HcmV?d00001 diff --git a/fabric-client/test/data/typescript-contract.cds b/fabric-client/test/data/typescript-contract.cds new file mode 100755 index 0000000000000000000000000000000000000000..8f57eecd6cfda05f482bb694797d40c6e0a21d36 GIT binary patch literal 2051 zcmV+e2>ka7F9-q>DGC#Gd2nTOV{&P5bS-0VZgg^CV{{S=ZFwzYZ*FvQVPkX}1u-r% zE;AYc8qW_OiwFP!00000|Lj`tZreB#&u2Xa;eN1VSd8pA$)0mrT(8Xn!R=j&_<%bg zNCSo%TWl!OC8;>RAn$%4Dan%THpOn@Znhqvjm#MihkxcrayVMiJq$53Qc)=;Y`XLO z6!oL%a5&tFq9{5#tpBw%9PF3hQ55Y&{e$RWxPzh>uw{iZZHU^5BCU-S(Ep;GHe@pS zik{N={O>EFH^Ce9PRJz;|IYXS3I zQ(*>9XOMheto&jBU*c)t!@+xEu$c>CET8^9(yU7@jeIMvb`DjiIO>!;@=Z#LxvK!8HaxVCy z+83{~HhO*r#zrw}ZL;{8b4X?qsciKzOQk?#>ovv1albEE?s7X=u9q2Dyr--=wG(oq z7!7s8QoqXfaTIDnW;&4u_mAqf#c=oji>m%+7BkR$G$G8Y`Z&aWJgg2wF5u?KNgPzx zbXB5QZy);+-p7Y)Bs3F#>3=-H5$=CUA}o#B$IIbxVl^`dRZiW$S|zcd-mU?T>XnuT z9pb27=_yO{rRtbR&C1?Ma%=icrtPV7HYYH^f5C(Lgn5H2lLYq$M2;z!WwB$`ouVkZ zZq#zu4^`ofjsEnb&rf1w^p4$J1M@NnQ|8Usf?*AL1y>2%^-EY1EASeATmjKk=3j&r}he8kN zU9r5zCc8n8Xrg3_+7;k$AFmNE1#$bhRMtgABfDI4p8Z_bc3g*cIoo}&sB-TECpvH$l6(V!Xs8xFVo z|3+xj`~R6RpeBSuuYM-zp>e{}FPsblxOaLeCt6pI2P~a&e^g%6KmqCQ)=P5?FX3%e zZ+>@#J}8+o4SywKQAK%=+zyip6he;{#J`4RRrt3GBnQmIM0VQFfZcYls;?sKG0=?# z))}RsOI?p^yHjG__v?@|;kS0_@%2OKtEK|~eH8Bbv47_q-hT#B^ZqwH93E`(e-rew z_@CqU+AH1i$kF~2oTFYV75?vI&CehE+4+|9-+t5o4-WUEt^aR=Hgx{`%Hi&nhJBpF zG-EnsVnCe|nsl1M0)OXMpp8_u=s*k{3?K!cGo}DjJAjwPF9lliJLt4AUV3SJ_v*MF z+*plRG@CEt4@8-9H3(r3eH}YFJ(TyTc5-u8G+SQ^l=_PMbVBX`-v9_q3Fi=>3kv^X zCON$))bNELOPmrz6U_3c$N6M=0pHy{{*&FW|L9c5|L=7ETZ#VbjS%Y=AAUbs-#6N){=HNJ(3AOp`~BwmuODsie;c7Z|A)$S#yF_+S@Dcqd9Rn5 zdCydluv2^dCu$1r;UDxM>L1lp7~+h>g+0M!MUs%qF<6nY94gaPih8a~43rZ^^2#oW z4^{FCm{@)OZ~2o-x4V}=@n01gEo*WGD#B$(j<59Ngr&Uymq}1B(#BKwzv$p_CH~Xj z?*AL1ha#zJLNac~a0iMRmmUU6NmZug-5U_GuDg$4HzNhsc|pVw*M07jzR0-G&?gtA~bHjYO6k1>`n#Im8wDUw>&;1wUufKuXkYRV5Qs4mB|i zDWj76B&1x7@HtuNnwXGb9`A0Ae132>l_yg!m9CM&V-%Zl2;JkNUS$gzYNME#h9*&R zzE=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": "node dist/start.js", + "build": "tsc", + "build:watch": "tsc -w", + "prepublishOnly": "npm run build" + }, + "engineStrict": true, + "author": "Simon Stone", + "license": "Apache-2.0", + "dependencies": { + "fabric-shim": "1.3.0-snapshot.17" + }, + "devDependencies": { + "@types/chai": "^4.1.4", + "@types/mocha": "^5.2.3", + "@types/node": "^10.3.6", + "@types/sinon": "^5.0.1", + "@types/sinon-chai": "^3.2.0", + "chai": "^4.1.2", + "mocha": "^5.2.0", + "nyc": "^12.0.2", + "sinon": "^6.0.0", + "sinon-chai": "^3.2.0", + "ts-node": "^7.0.0", + "tslint": "^5.10.0", + "typescript": "^2.9.2" + }, + "nyc": { + "extension": [ + ".ts", + ".tsx" + ], + "exclude": [ + "coverage/**", + "dist/**" + ], + "reporter": [ + "text-summary", + "html" + ], + "all": true, + "check-coverage": true, + "statements": 100, + "branches": 100, + "functions": 100, + "lines": 100 + } +} diff --git a/fabric-client/test/data/typescript-contract/src/chaincode.spec.ts b/fabric-client/test/data/typescript-contract/src/chaincode.spec.ts new file mode 100644 index 0000000000..1e23f34e57 --- /dev/null +++ b/fabric-client/test/data/typescript-contract/src/chaincode.spec.ts @@ -0,0 +1,46 @@ +/** + * Copyright 2018 IBM All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +import { ChaincodeStub } from 'fabric-shim'; +import { Chaincode } from '.'; + +import * as chai from 'chai'; +import * as sinon from 'sinon'; +import * as sinonChai from 'sinon-chai'; + +chai.should(); +chai.use(sinonChai); + +describe('Chaincode', () => { + + describe('#Init', () => { + + it('should work', async () => { + const cc = new Chaincode(); + const stub = sinon.createStubInstance(ChaincodeStub); + stub.getFunctionAndParameters.returns({ fcn: 'initFunc', params: [] }); + const res = await cc.Init(stub); + res.status.should.equal(ChaincodeStub.RESPONSE_CODE.OK); + }); + + }); + + describe('#Invoke', async () => { + + it('should work', async () => { + const cc = new Chaincode(); + const stub = sinon.createStubInstance(ChaincodeStub); + stub.getFunctionAndParameters.returns({ fcn: 'initFunc', params: [] }); + let res = await cc.Init(stub); + res.status.should.equal(ChaincodeStub.RESPONSE_CODE.OK); + stub.getFunctionAndParameters.returns({ fcn: 'invokeFunc', params: [] }); + res = await cc.Invoke(stub); + res.status.should.equal(ChaincodeStub.RESPONSE_CODE.OK); + }); + + }); + +}); diff --git a/fabric-client/test/data/typescript-contract/src/chaincode.ts b/fabric-client/test/data/typescript-contract/src/chaincode.ts new file mode 100644 index 0000000000..14db9cbdec --- /dev/null +++ b/fabric-client/test/data/typescript-contract/src/chaincode.ts @@ -0,0 +1,23 @@ +/** + * Copyright 2018 IBM All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +import { ChaincodeInterface, ChaincodeStub, Shim } from 'fabric-shim'; + +export class Chaincode implements ChaincodeInterface { + + public async Init(stub: ChaincodeStub): Promise { + const { fcn, params } = stub.getFunctionAndParameters(); + console.info('Init()', fcn, params); + return Shim.success(); + } + + public async Invoke(stub: ChaincodeStub): Promise { + const { fcn, params } = stub.getFunctionAndParameters(); + console.info('Invoke()', fcn, params); + return Shim.success(); + } + +} diff --git a/fabric-client/test/data/typescript-contract/src/index.ts b/fabric-client/test/data/typescript-contract/src/index.ts new file mode 100644 index 0000000000..c02209193e --- /dev/null +++ b/fabric-client/test/data/typescript-contract/src/index.ts @@ -0,0 +1,7 @@ +/** + * Copyright 2018 IBM All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +export { Chaincode } from './chaincode'; diff --git a/fabric-client/test/data/typescript-contract/src/start.spec.ts b/fabric-client/test/data/typescript-contract/src/start.spec.ts new file mode 100644 index 0000000000..1523fbd511 --- /dev/null +++ b/fabric-client/test/data/typescript-contract/src/start.spec.ts @@ -0,0 +1,30 @@ +/** + * Copyright 2018 IBM All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +import { Shim } from 'fabric-shim'; +import { Chaincode } from '.'; + +import * as chai from 'chai'; +import * as sinon from 'sinon'; +import * as sinonChai from 'sinon-chai'; + +chai.should(); +chai.use(sinonChai); + +describe('start', () => { + + afterEach(() => { + sinon.restore(); + delete require.cache[require.resolve('../src/start')]; + }); + + it('should work', () => { + const startStub = sinon.stub(Shim, 'start'); + require('../src/start'); + startStub.should.have.been.calledOnceWithExactly(sinon.match.instanceOf(Chaincode)); + }); + +}); diff --git a/fabric-client/test/data/typescript-contract/src/start.ts b/fabric-client/test/data/typescript-contract/src/start.ts new file mode 100644 index 0000000000..ebc096a0ac --- /dev/null +++ b/fabric-client/test/data/typescript-contract/src/start.ts @@ -0,0 +1,10 @@ +/** + * Copyright 2018 IBM All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +import { Shim } from 'fabric-shim'; +import { Chaincode } from '.'; + +Shim.start(new Chaincode()); diff --git a/fabric-client/test/data/typescript-contract/tsconfig.json b/fabric-client/test/data/typescript-contract/tsconfig.json new file mode 100644 index 0000000000..2d74e90773 --- /dev/null +++ b/fabric-client/test/data/typescript-contract/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "outDir": "dist", + "target": "es2017", + "moduleResolution": "node", + "module": "commonjs", + "declaration": true + }, + "include": [ + "./src/**/*" + ], + "exclude": [ + "./src/**/*.spec.ts" + ] +} diff --git a/fabric-client/test/data/typescript-contract/tslint.json b/fabric-client/test/data/typescript-contract/tslint.json new file mode 100644 index 0000000000..33ccbf3c64 --- /dev/null +++ b/fabric-client/test/data/typescript-contract/tslint.json @@ -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": [] +} diff --git a/fabric-client/types/index.d.ts b/fabric-client/types/index.d.ts index 065fb2958f..a1461039ee 100644 --- a/fabric-client/types/index.d.ts +++ b/fabric-client/types/index.d.ts @@ -584,4 +584,14 @@ declare namespace Client { timestamp: number; } + + export class Package { + static fromBuffer(buffer: Buffer): Promise; + static fromDirectory(options: { name: string, version: string, path: string, type: ChaincodeType, metadataPath?: string }): Promise; + getName(): string; + getVersion(): string; + getType(): ChaincodeType; + getFileNames(): string[]; + toBuffer(): Promise; + } } diff --git a/scripts/check_license.sh b/scripts/check_license.sh index aff39dc5a9..a897086d16 100755 --- a/scripts/check_license.sh +++ b/scripts/check_license.sh @@ -17,7 +17,7 @@ function filterExcludedFiles { | grep -v "\.pem$" \ | grep -v "\.block$" \ | grep -v "\.tx$" \ - | grep -v "\.txt$" \ + | grep -v "\.txt$" \ | grep -v "_sk$" \ | grep -v "\.key$" \ | grep -v "\.gen\.go$" \ @@ -27,6 +27,8 @@ function filterExcludedFiles { | grep -v "\.yaml$" \ | grep -v "\.json$" \ | grep -v "\.gradle$" \ + | grep -v "\.cds$" \ + | grep -v "\.jar$" \ | sort -u` }