├── .editorconfig ├── .eslintignore ├── .eslintrc ├── .gitattributes ├── .github ├── settings.yml └── workflows │ ├── pull_request.yaml │ ├── push.yaml │ ├── release.yaml │ ├── scan.yaml │ ├── schedule.yaml │ ├── test.yaml │ └── vulnerability-scan.yaml ├── .gitignore ├── CHANGELOG.md ├── CODEOWNERS ├── CODE_OF_CONDUCT.md ├── COMPATIBILITY.md ├── CONTRIBUTING.md ├── LICENSE ├── MAINTAINERS.md ├── README.md ├── RELEASING.md ├── SECURITY.md ├── TUTORIAL.md ├── apis ├── fabric-contract-api │ ├── .npmignore │ ├── LICENSE │ ├── README.md │ ├── index.js │ ├── lib │ │ ├── annotations │ │ │ ├── default.js │ │ │ ├── index.js │ │ │ ├── info.js │ │ │ ├── object.js │ │ │ ├── transaction.js │ │ │ └── utils.js │ │ ├── context.js │ │ ├── contract.js │ │ ├── jsontransactionserializer.js │ │ └── logger.js │ ├── package.json │ ├── schema │ │ ├── contract-schema.json │ │ ├── data.json │ │ ├── example-full.json │ │ ├── helloworld.json │ │ └── testschema.json │ ├── test │ │ ├── typescript │ │ │ └── smartcontract.ts │ │ └── unit │ │ │ ├── annotations │ │ │ ├── default.js │ │ │ ├── info.js │ │ │ ├── object.js │ │ │ ├── transaction.js │ │ │ └── utils.js │ │ │ ├── context.js │ │ │ ├── contract.js │ │ │ ├── data.json │ │ │ ├── index.js │ │ │ ├── jsontransactionserializer.js │ │ │ ├── logger.js │ │ │ └── metadata.json │ ├── tsconfig.json │ └── types │ │ └── index.d.ts └── fabric-shim-api │ ├── LICENSE │ ├── README.md │ ├── index.js │ ├── package.json │ ├── tsconfig.json │ └── types │ └── index.d.ts ├── common ├── config │ └── rush │ │ ├── command-line.json │ │ └── pnpm-lock.yaml └── scripts │ ├── install-run-rush-pnpm.js │ ├── install-run-rush.js │ ├── install-run-rushx.js │ └── install-run.js ├── docker └── fabric-nodeenv │ ├── Dockerfile │ ├── README.md │ ├── build.sh │ ├── docker.js │ ├── package.json │ └── start.sh ├── docs ├── 404.md ├── README.md ├── _config.yml ├── _includes │ ├── apidocs.html │ ├── footer.html │ └── header.html ├── _jsdoc.json ├── _jsdoc │ ├── index.md │ ├── static │ │ └── contract-schema.json │ └── tutorials │ │ ├── annotated-contract-metadata.md │ │ ├── data-types-and-contracts.md │ │ ├── deep-dive-contract-interface.md │ │ ├── tutorials.json │ │ ├── using-chaincodeinterface.md │ │ ├── using-contractinterface.md │ │ ├── using-iterators.md │ │ └── using-typescript-decorators.md ├── index.md └── package.json ├── libraries ├── fabric-ledger │ ├── .eslintignore │ ├── .eslintrc.js │ ├── .npmignore │ ├── package.json │ ├── src │ │ ├── Collection.ts │ │ ├── Ledger.ts │ │ └── index.ts │ ├── test │ │ └── unit │ │ │ └── Ledger.spec.ts │ └── tsconfig.json └── fabric-shim │ ├── .npmignore │ ├── LICENSE │ ├── README.md │ ├── cli.js │ ├── index.js │ ├── lib │ ├── chaincode.js │ ├── cmds │ │ ├── metadata.js │ │ ├── metadata │ │ │ ├── generateCommand.js │ │ │ └── lib │ │ │ │ └── generate.js │ │ ├── serverCommand.js │ │ └── startCommand.js │ ├── contract-spi │ │ ├── bootstrap.js │ │ ├── chaincodefromcontract.js │ │ ├── datamarshall.js │ │ └── systemcontract.js │ ├── handler.js │ ├── iterators.js │ ├── logger.js │ ├── server.js │ ├── stub.js │ └── utils │ │ ├── statebased.js │ │ └── utils.js │ ├── package.json │ ├── startup.sh │ ├── test │ ├── typescript │ │ └── chaincode.ts │ └── unit │ │ ├── chaincode.js │ │ ├── cli.js │ │ ├── client-identity.js │ │ ├── cmds │ │ ├── chaincode.js │ │ ├── metadata.js │ │ ├── metadata │ │ │ ├── generateCommand.js │ │ │ └── lib │ │ │ │ └── generate.js │ │ └── serverCommand.js │ │ ├── contract-spi │ │ ├── bootstrap.js │ │ ├── chaincodefromcontract.js │ │ ├── datamarshall.js │ │ └── systemcontract.js │ │ ├── handler.js │ │ ├── iterators.js │ │ ├── logger.js │ │ ├── module.js │ │ ├── server.js │ │ ├── stub.js │ │ ├── test-ca.base64 │ │ ├── test-ca.pem │ │ ├── test-cert.base64 │ │ ├── test-cert.pem │ │ ├── test-key.base64 │ │ ├── test-key.pem │ │ └── utils │ │ ├── statebased.js │ │ └── utils.js │ ├── tsconfig.json │ └── types │ └── index.d.ts ├── release_notes ├── v1.1.0-alpha.txt ├── v1.1.0-preview.txt ├── v1.1.0.txt ├── v1.2.0.txt ├── v1.3.0.txt ├── v1.4.0-beta.txt ├── v1.4.0.txt ├── v2.0.0-alpha.txt ├── v2.0.0-beta.txt ├── v2.0.0.txt ├── v2.1.0.txt ├── v2.1.1.txt ├── v2.1.2.txt ├── v2.1.3.txt ├── v2.1.4.txt ├── v2.2.0.txt ├── v2.3.0.txt ├── v2.4.0-beta.txt ├── v2.4.0.txt ├── v2.4.1.txt ├── v2.4.2.txt ├── v2.5.0.txt ├── v2.5.1.txt └── v2.5.2.txt ├── rush.json ├── test ├── chaincodes │ ├── annotations │ │ ├── package.json │ │ ├── src │ │ │ ├── index.ts │ │ │ └── test_contract │ │ │ │ ├── expected-metadata.json │ │ │ │ └── test_contract.ts │ │ └── tsconfig.json │ ├── clientidentity │ │ ├── chaincode.js │ │ ├── index.js │ │ └── package.json │ ├── crosschaincode │ │ ├── chaincode.js │ │ ├── index.js │ │ └── package.json │ ├── crosschaincode2 │ │ ├── chaincode.js │ │ ├── index.js │ │ └── package.json │ ├── crud │ │ ├── chaincode.js │ │ ├── index.js │ │ └── package.json │ ├── events │ │ ├── chaincode.js │ │ ├── index.js │ │ └── package.json │ ├── ledger │ │ ├── chaincode.js │ │ ├── index.js │ │ └── package.json │ ├── privateData │ │ ├── chaincode.js │ │ ├── collection-config │ │ │ └── collection.json │ │ ├── index.js │ │ └── package.json │ ├── query │ │ ├── chaincode.js │ │ ├── index.js │ │ └── package.json │ ├── scenario │ │ ├── index.js │ │ ├── package.json │ │ ├── removevalues.js │ │ ├── scenariocontext.js │ │ └── updatevalues.js │ └── server │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── index.js │ │ └── package │ │ ├── connection.json │ │ └── metadata.json ├── constants.js ├── e2e │ ├── package.json │ ├── scenario.js │ └── server.js ├── fixtures │ ├── channel-init.sh │ └── kill-chaincode-node.sh └── fv │ ├── annotations.js │ ├── clientidentity.js │ ├── crosschaincode.js │ ├── crosschaincode2.js │ ├── crud.js │ ├── events.js │ ├── ledger.js │ ├── package.json │ ├── privateData.js │ ├── query.js │ └── utils.js └── tools ├── getEdgeDocker.sh ├── logfiles.sh ├── monitordocker.sh ├── scripts ├── changelog.sh ├── gittag.sh ├── multiarch.sh ├── startFabric.sh └── updateversions.sh └── toolchain ├── fabric.js ├── index.js ├── network ├── README.md ├── crypto-material │ ├── configtx.yaml │ ├── core.yaml │ ├── crypto-config.yaml │ └── rename_sk.sh ├── docker-compose │ ├── docker-compose-base.yaml │ ├── docker-compose-cli.yaml │ ├── docker-compose-tls.yaml │ └── docker-compose.yaml └── external │ ├── build │ ├── detect │ └── release ├── package.json ├── shell ├── cmd.js ├── docker.js └── npm.js ├── test ├── devmode.js └── inversionOfControl.js ├── utils.js └── verdaccio ├── config.yaml └── index.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # 2 | # Licensed under the Apache License, Version 2.0 (the "License"); 3 | # you may not use this file except in compliance with the License. 4 | # You may obtain a copy of the License at 5 | # 6 | # http://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, 10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | # See the License for the specific language governing permissions and 12 | # limitations under the License. 13 | # 14 | 15 | root = true 16 | 17 | [*] 18 | indent_style = space 19 | indent_size = 4 20 | end_of_line = lf 21 | charset = utf-8 22 | trim_trailing_whitespace = true 23 | insert_final_newline = true 24 | 25 | [*.md] 26 | indent_size = 2 27 | 28 | [*.{yaml,yml}] 29 | indent_size = 2 30 | 31 | [*.{mj,cj,j,t}s] 32 | quote_type = single 33 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | bundle.js 2 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "es6": true, 4 | "node": true, 5 | "mocha": true 6 | }, 7 | "extends": [ "eslint:recommended", "@rushstack/eslint-config"], 8 | "overrides": [ 9 | { 10 | "files": ["**/test/typescript/*.ts"], 11 | "rules": { 12 | "no-unused-vars": "off", 13 | "@typescript-eslint/no-unused-vars": "off", 14 | "@typescript-eslint/no-floating-promises": "off" 15 | } 16 | }, 17 | { 18 | "files": ["**/index.d.ts"], 19 | "rules": { 20 | "max-len": "warn" 21 | } 22 | } 23 | ], 24 | "parserOptions": { 25 | "ecmaVersion": 9, 26 | "sourceType": "module" 27 | }, 28 | "rules": { 29 | "array-bracket-spacing": ["error", "never"], 30 | "arrow-spacing": ["error"], 31 | "brace-style": ["error"], 32 | "comma-spacing": ["error"], 33 | "curly": ["error"], 34 | "dot-notation": ["error"], 35 | "eqeqeq": ["error"], 36 | "indent": [ 37 | "error", 38 | 4, 39 | { 40 | "SwitchCase": 1 41 | } 42 | ], 43 | "keyword-spacing": "error", 44 | "linebreak-style": ["error", "unix"], 45 | "max-len": [ 46 | "error", 47 | { 48 | "code": 150, 49 | "ignoreTrailingComments": true, 50 | "ignoreUrls": true, 51 | "ignoreStrings": true, 52 | "ignoreTemplateLiterals": true, 53 | "ignoreRegExpLiterals": true 54 | } 55 | ], 56 | "no-console": ["warn"], 57 | "no-shadow": ["error"], 58 | "no-throw-literal": ["error"], 59 | "no-trailing-spaces": ["error"], 60 | "no-useless-call": ["error"], 61 | "no-unused-vars": [ 62 | "error", 63 | { 64 | "args": "none" 65 | } 66 | ], 67 | "no-var": ["error"], 68 | "no-with": ["error"], 69 | "object-curly-spacing": ["error", "never"], 70 | "operator-linebreak": ["error"], 71 | "prefer-const": ["error"], 72 | "quotes": ["error", "single"], 73 | "semi": ["error", "always"], 74 | "spaced-comment": ["error", "always"], 75 | "space-before-blocks": [ 76 | "error", 77 | { 78 | "functions": "always", 79 | "keywords": "always", 80 | "classes": "always" 81 | } 82 | ], 83 | "space-infix-ops": ["error"], 84 | "space-in-parens": ["error", "never"], 85 | "yoda": "error", 86 | "@typescript-eslint/no-explicit-any": "warn", 87 | "@typescript-eslint/explicit-member-accessibility": "off", 88 | "@typescript-eslint/explicit-function-return-type": "off", 89 | "@typescript-eslint/interface-name-prefix": "off", 90 | "@typescript-eslint/no-namespace": "off", 91 | "@typescript-eslint/typedef": "off" 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.json linguist-language=JSON-with-Comments -------------------------------------------------------------------------------- /.github/settings.yml: -------------------------------------------------------------------------------- 1 | repository: 2 | name: fabric-chaincode-node 3 | description: Hyperledger Fabric Node.js Smart Contracts issues in JIRA please 4 | https://jira.hyperledger.org 5 | homepage: https://wiki.hyperledger.org/display/fabric 6 | default_branch: main 7 | has_downloads: true 8 | has_issues: true 9 | has_projects: false 10 | has_wiki: false 11 | archived: false 12 | private: false 13 | allow_squash_merge: true 14 | allow_merge_commit: false 15 | allow_rebase_merge: true 16 | -------------------------------------------------------------------------------- /.github/workflows/pull_request.yaml: -------------------------------------------------------------------------------- 1 | # Copyright the Hyperledger Fabric contributors. All rights reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | name: Pull request 5 | 6 | on: 7 | pull_request: 8 | branches: 9 | - main 10 | workflow_dispatch: 11 | 12 | concurrency: 13 | group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} 14 | cancel-in-progress: true 15 | 16 | jobs: 17 | test: 18 | uses: ./.github/workflows/test.yaml 19 | 20 | scan: 21 | uses: ./.github/workflows/scan.yaml 22 | 23 | pull-request: 24 | needs: test 25 | name: Pull request success 26 | runs-on: ubuntu-latest 27 | steps: 28 | - run: "true" 29 | -------------------------------------------------------------------------------- /.github/workflows/push.yaml: -------------------------------------------------------------------------------- 1 | # Copyright the Hyperledger Fabric contributors. All rights reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | name: Push 5 | 6 | on: 7 | push: 8 | branches: 9 | - main 10 | workflow_dispatch: 11 | 12 | jobs: 13 | test: 14 | uses: ./.github/workflows/test.yaml 15 | -------------------------------------------------------------------------------- /.github/workflows/scan.yaml: -------------------------------------------------------------------------------- 1 | name: "Security vulnerability scan" 2 | 3 | on: 4 | workflow_call: 5 | inputs: 6 | ref: 7 | description: Branch, tag or SHA to scan. 8 | type: string 9 | required: false 10 | default: "" 11 | 12 | permissions: 13 | contents: read 14 | 15 | jobs: 16 | # Job to handle the auditing of the code 17 | # NPM audit is run on a 'fake' installation of the libraries 18 | # Pulling in all the dependencies it will be able to run NPM AUDIT, and if that returns a 19 | # error code the job will fail. 20 | scan: 21 | runs-on: ubuntu-latest 22 | steps: 23 | - uses: actions/checkout@v4 24 | with: 25 | ref: ${{ inputs.ref }} 26 | - uses: actions/setup-node@v4 27 | with: 28 | node-version: 18 29 | - name: Install 30 | run: node common/scripts/install-run-rush.js install 31 | - name: Build packages 32 | run: node common/scripts/install-run-rush.js publish --include-all --pack --release-folder tgz --publish 33 | - name: Start local NPM registry 34 | run: node common/scripts/install-run-rush.js start-verdaccio # script will check for the ci variable and use built images 35 | - name: Deploy scan project 36 | run: | 37 | mkdir -p audit 38 | cd audit 39 | npm init --yes 40 | npm install --save --package-lock-only --registry http://localhost:4873 fabric-shim fabric-shim-api fabric-contract-api 41 | - name: Scan 42 | working-directory: audit 43 | run: npm audit --omit=dev 44 | -------------------------------------------------------------------------------- /.github/workflows/schedule.yaml: -------------------------------------------------------------------------------- 1 | # Copyright the Hyperledger Fabric contributors. All rights reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | name: Scheduled build 5 | 6 | on: 7 | schedule: 8 | - cron: "5 2 * * 6" 9 | workflow_dispatch: 10 | 11 | jobs: 12 | test: 13 | uses: ./.github/workflows/test.yaml 14 | -------------------------------------------------------------------------------- /.github/workflows/vulnerability-scan.yaml: -------------------------------------------------------------------------------- 1 | name: "Security vulnerability scan" 2 | 3 | on: 4 | schedule: 5 | - cron: "55 2 * * *" 6 | workflow_dispatch: 7 | 8 | permissions: 9 | contents: read 10 | 11 | jobs: 12 | latest-release-version: 13 | name: Get latest release tag 14 | runs-on: ubuntu-latest 15 | outputs: 16 | tag_name: ${{ steps.tag-name.outputs.value }} 17 | steps: 18 | - id: tag-name 19 | run: echo "value=$(curl --location --silent --fail "https://api.github.com/repos/${GITHUB_REPOSITORY}/releases/latest" | jq --raw-output '.tag_name')" >> "${GITHUB_OUTPUT}" 20 | 21 | scan: 22 | name: Scan ${{ needs.latest-release-version.outputs.tag_name }} 23 | needs: latest-release-version 24 | uses: ./.github/workflows/scan.yaml 25 | with: 26 | ref: ${{ needs.latest-release-version.outputs.tag_name }} 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | coverage 2 | node_modules 3 | **/node_modules/* 4 | npm-debug.log 5 | .DS_Store 6 | test/.DS_Store 7 | # ignore vscode config 8 | .vscode 9 | # ignore webstorm config 10 | .idea 11 | yarn.lock 12 | .nyc_output 13 | **/typescript/*.js 14 | **/typescript/*.js.map 15 | 16 | fabric*.tgz 17 | install-fabric.sh 18 | 19 | libraries/fabric-ledger/lib 20 | 21 | # Crypto material 22 | tools/toolchain/network/crypto-material/*.block 23 | tools/toolchain/network/crypto-material/*.tx 24 | tools/toolchain/network/crypto-material/crypto-config 25 | tools/toolchain/network/crypto-material/core.yaml 26 | 27 | # Rush files 28 | common/temp/** 29 | **/.rush/temp/** 30 | **/*.build.error.log 31 | **/*.build.log 32 | **/*.test_fv.log 33 | 34 | package-deps.json 35 | test-results.xml 36 | docker.log 37 | 38 | # jsdoc output 39 | docs/gen 40 | fabric-samples 41 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: Apache-2.0 2 | 3 | # Fabric Chaincode Node maintainers 4 | * @hyperledger/fabric-chaincode-node-maintainers 5 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | Code of Conduct Guidelines 2 | ========================== 3 | 4 | Please review the Hyperledger [Code of 5 | Conduct](https://wiki.hyperledger.org/community/hyperledger-project-code-of-conduct) 6 | before participating. It is important that we keep things civil. 7 | 8 | Creative Commons License
This work is licensed under a Creative Commons Attribution 4.0 International License. 9 | -------------------------------------------------------------------------------- /COMPATIBILITY.md: -------------------------------------------------------------------------------- 1 | # Support and Compatibility 2 | 3 | Github is used for code base management and [issue](https://github.com/hyperledger/fabric-chaincode-node/issues) tracking. 4 | 5 | ## Summary of Compatibility 6 | 7 | This table shows the summary of the compatibility of the Node chaincode packages, together with the Node.js runtime they require. 8 | 9 | | Node chaincode version | Minimum supported Node.js | Node.js runtime | Docker image platforms | 10 | | ---------------------- | ------------------------- | --------------- | ---------------------- | 11 | | v1.4 | 8 | 8 | amd64 | 12 | | v2.2 | 12 | 12 | amd64 | 13 | | v2.5.0 - v2.5.4 | 18 | 18 | amd64, arm64 | 14 | | v2.5.5 - v2.5.7 | 18 | 20 | amd64, arm64 | 15 | | v2.5.8+ | 18 | 22 | amd64, arm64 | 16 | 17 | The Node runtime provided by the chaincode Docker image determines the maximum Node version (and features) that smart contract code can exploit when using the default Node chaincode container. 18 | 19 | Subject to a suitable runtime environment, the Node chaincode libraries can be used to communicate with Fabric peers at different LTS versions. The level of functionality is determined by the Fabric version in use and channel capabilities. 20 | 21 | All Docker images, chaincode libraries and tools are tested using amd64 (x86-64) only. 22 | 23 | ## Chaincode builder 24 | 25 | The default Fabric chaincode builder creates a Docker container to run deployed smart contracts. Node chaincode Docker containers are built using the `hyperledger/fabric-nodeenv` Docker image, tagged with the same major and minor version as the Fabric peer version. For example, Fabric v2.5 creates Node chaincode containers using the `hyperledger/fabric-nodeenv:2.5` Docker image. Fabric v3 continues to use the v2.5 Node chaincode image. 26 | 27 | A different chaincode Docker image can be specified using the CORE_CHAINCODE_NODE_RUNTIME environment variable on the Fabric peer. For example, CORE_CHAINCODE_NODE_RUNTIME=example/customNodeRuntime:latest. 28 | 29 | With Fabric v2 and later, an alternative chaincode builder can be configured on the Fabric peer. In this case the configured chaincode builder controls how chaincode is launched. See the [Fabric documentation](https://hyperledger-fabric.readthedocs.io/en/release-2.5/cc_launcher.html) for further details. 30 | 31 | ## Chaincode packaging 32 | 33 | When using the `hyperledger/fabric-nodeenv` Node chaincode Docker images at v2 (and later), deployed chaincode is installed with npm as follows: 34 | 35 | - If a `package-lock.json` or a `npm-shrinkwrap.json` file is present, `npm ci --only=production` will be used. 36 | - Otherwise, `npm install --production` will be used. 37 | 38 | When using the v1.4 `hyperledger/fabric-nodeenv` Node chaincode Docker images, deployed chaincode is installed with `npm install --production`. 39 | -------------------------------------------------------------------------------- /MAINTAINERS.md: -------------------------------------------------------------------------------- 1 | # Maintainers 2 | 3 | **Active maintainers** 4 | 5 | | Name | GitHub | Chat | email | 6 | | ------------ | ---------------------------------- | --------------- | -------------------------- | 7 | | Dave Enyeart | [denyeart][denyeart] | denyeart | | 8 | | Mark Lewis | [bestbeforetoday][bestbeforetoday] | bestbeforetoday | | 9 | 10 | **Emeritus maintainers** 11 | 12 | | Name | GitHub | Chat | email | 13 | | --------------- | -------------------------- | ------------ | -------------------------- | 14 | | Matthew B White | [mbwhite][mbwhite] | mbwhite | | 15 | | James Taylor | [jt-nti][jt-nti] | jtonline | | 16 | | Andrew Hurt | [awjh-ibm][awjh-ibm] | awjh-ibm | | 17 | | Bret Harrison | [harrisob][harrisob] | bretharrison | | 18 | | Chaoyi Zhao | [zhaochy1990][zhaochy1990] | zhaochy | | 19 | | David Kelsey | [davidkel][davidkel] | davidkel | | 20 | 21 | Also: Please see the [Release Manager section](https://github.com/hyperledger/fabric/blob/main/MAINTAINERS.md) 22 | 23 | Creative Commons License
This work is licensed under a Creative Commons Attribution 4.0 International License. 24 | 25 | [awjh-ibm]: https://github.com/awjh-ibm 26 | [harrisob]: https://github.com/harrisob 27 | [zhaochy1990]: https://github.com/zhaochy1990 28 | [davidkel]: https://github.com/davidkel 29 | [mbwhite]: https://github.com/mbwhite 30 | [jt-nti]: https://github.com/jt-nti 31 | [bestbeforetoday]: https://github.com/bestbeforetoday 32 | [denyeart]: https://github.com/denyeart 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Hyperledger Fabric - Node.js Contracts 2 | 3 | [![Build Status](https://dev.azure.com/Hyperledger/Fabric-Chaincode-Node/_apis/build/status/Fabric-Chaincode-Node?branchName=main)](https://dev.azure.com/Hyperledger/Fabric-Chaincode-Node/_build/latest?definitionId=33&branchName=main) 4 | [![fabric-contract-api npm module](https://img.shields.io/npm/v/fabric-shim?label=fabric-contract-api)](https://www.npmjs.com/package/fabric-contract-api) 5 | [![fabric-shim npm module](https://img.shields.io/npm/v/fabric-shim?label=fabric-shim)](https://www.npmjs.com/package/fabric-shim) 6 | [![fabric-shim-api npm module](https://img.shields.io/npm/v/fabric-shim?label=fabric-shim-api)](https://www.npmjs.com/package/fabric-shim-api) 7 | [![Discord](https://img.shields.io/discord/905194001349627914?label=discord)](https://discordapp.com/channels/905194001349627914/943090527920877598) 8 | 9 | This is the project to support the writing of Contracts with the node.js runtime. 10 | 11 | ## Documentation 12 | 13 | As an application developer, to learn about how to implement **"Smart Contracts"** for Hyperledger Fabric using Node.js, please visit the [API documentation](https://hyperledger.github.io/fabric-chaincode-node/) and follow the tutorial links. 14 | 15 | - [API documentation](https://hyperledger.github.io/fabric-chaincode-node/) 16 | - [Full Documenation on Hyperledger Fabric](https://hyperledger-fabric.readthedocs.io/) 17 | - [Samples repository](https://github.com/hyperledger/fabric-samples) 18 | - [Quick-start tutorial](TUTORIAL.md) 19 | 20 | ## Compatibility 21 | 22 | For details on what Nodejs runtime and versions of Hyperledger Fabric can be used please see the [compatibility document](COMPATIBILITY.md). 23 | 24 | ## npm Shrinkwrap 25 | 26 | In line with the advice from [npm on shrinkwrap](https://docs.npmjs.com/cli/v8/configuring-npm/npm-shrinkwrap-json) the modules published do not contain a `npm-shrinkwrap.json` file. 27 | 28 | It is **STRONGLY** recommended therefore that after testing, and before putting your contract into production a `npm-shrinkwrap.json` file is created. When the chaincode is install it will be via a `npm install --production` command. 29 | 30 | ## Contributing 31 | 32 | If you are interested in contributing updates to this project, please start with the [contributing guide](CONTRIBUTING.md). 33 | 34 | There is also a [release guide](RELEASING.md) describing the process for publishing new versions. 35 | 36 | --- 37 | 38 | ## License 39 | 40 | Hyperledger Project source code files are made available under the Apache 41 | License, Version 2.0 (Apache-2.0), located in the [LICENSE](LICENSE) file. 42 | Hyperledger Project documentation files are made available under the Creative 43 | Commons Attribution 4.0 International License (CC-BY-4.0), available at http://creativecommons.org/licenses/by/4.0/. 44 | -------------------------------------------------------------------------------- /RELEASING.md: -------------------------------------------------------------------------------- 1 | # Releasing 2 | 3 | The following artifacts are created as a result of releasing Fabric Chaincode Node: 4 | 5 | - docker images 6 | - [fabric-nodeenv](https://hub.docker.com/r/hyperledger/fabric-nodeenv) 7 | - npm modules 8 | - [fabric-contract-api](https://www.npmjs.com/package/fabric-contract-api) 9 | - [fabric-shim](https://www.npmjs.com/package/fabric-shim) 10 | - [fabric-shim-api](https://www.npmjs.com/package/fabric-shim-api) 11 | 12 | **Note:** A docker image with a matching V.R version is required before releasing a new version of Fabric. 13 | 14 | ## Before releasing 15 | 16 | It's useful to create an issue to keep track of each release, for example [FABCN-377 Release v2.0.0 chaincode-node](https://jira.hyperledger.org/browse/FABCN-377). 17 | 18 | The following tasks are required before releasing: 19 | 20 | - Update version numbers in package.json files to the required version 21 | - Update `tag` in package.json files to the required value, e.g. `beta`, or `latest` 22 | - Update test, sample, and docs files to match the new version 23 | - Create a new release notes file 24 | - Update the `CHANGELOG.md` file 25 | 26 | The `changelog.sh` script in `tools/scripts` will prepopulate the changelog but you must check and edit the file manually afterwards as required 27 | 28 | The `tools/scripts/updateversions.sh` script will update the version in all the `package.json` files. Pass the new version as the first argument. 29 | 30 | ```bash 31 | ./tools/scripts/updateversions.sh 2.4.1 32 | ``` 33 | 34 | See the [Prepare 2.1.4 release](https://github.com/hyperledger/fabric-chaincode-node/pull/174) pull request for an example, although be careful to search for all versions in the codebase as they're easy to miss and things change! 35 | 36 | ## Create release 37 | 38 | Creating a GitHub release on the [releases page](https://github.com/hyperledger/fabric-chaincode-node/releases) will trigger the build to publish the new release. 39 | 40 | When drafting the release, create a new tag for the new version (with a `v` prefix), e.g. `v2.1.4` 41 | 42 | See previous releases for examples of the title and description. 43 | 44 | ## After releasing 45 | 46 | - Update version numbers in package.json files to the next version appended with a `-unstable` pre-release label. e.g. `1.2.3-unstable` 47 | - Update `tag` in package.json files to `unstable` 48 | - Update test, sample, and docs files to match the new version 49 | 50 | See the [Bump version to 2.1.5](https://github.com/hyperledger/fabric-chaincode-node/pull/175) pull request for an example. It should include almost all the files changed to prepare for the release, except for the release notes and changelog which do not need updating. 51 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Hyperledger Security Policy 2 | 3 | ## Reporting a Security Bug 4 | 5 | If you think you have discovered a security issue in any of the Hyperledger projects, we'd love to hear from you. We will take all security bugs seriously and if confirmed upon investigation we will patch it within a reasonable amount of time and release a public security bulletin discussing the impact and credit the discoverer. 6 | 7 | There are two ways to report a security bug. The easiest is to email a description of the flaw and any related information (e.g. reproduction steps, version) to [security at hyperledger dot org](mailto:security@hyperledger.org). 8 | 9 | The other way is to file a confidential security bug in our [JIRA bug tracking system](https://jira.hyperledger.org). Be sure to set the “Security Level” to “Security issue”. 10 | 11 | The process by which the Hyperledger Security Team handles security bugs is documented further in our [Defect Response page](https://wiki.hyperledger.org/display/SEC/Defect+Response) on our [wiki](https://wiki.hyperledger.org). 12 | 13 | -------------------------------------------------------------------------------- /apis/fabric-contract-api/.npmignore: -------------------------------------------------------------------------------- 1 | test 2 | fabric-contract-api*.tgz -------------------------------------------------------------------------------- /apis/fabric-contract-api/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | # Copyright IBM Corp. All Rights Reserved. 3 | # 4 | # SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 'use strict'; 7 | 8 | /** 9 | * This is the class that all contracts should extend. A Smart Contract will consist of one or more of these 10 | * @see {@link fabric-contract-api.Contract} 11 | */ 12 | module.exports.Contract = require('./lib/contract.js'); 13 | module.exports.Context = require('./lib/context.js'); 14 | 15 | Object.assign(module.exports, require('./lib/annotations')); 16 | 17 | module.exports.JSONSerializer = require('./lib/jsontransactionserializer.js'); 18 | -------------------------------------------------------------------------------- /apis/fabric-contract-api/lib/annotations/default.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright IBM Corp. All Rights Reserved. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | const Logger = require('../logger'); 8 | const logger = Logger.getLogger('./lib/annotations/default.js'); 9 | require('reflect-metadata'); 10 | 11 | module.exports.Default = function Default () { 12 | 13 | return (target) => { 14 | logger.info('@Default args:', 'Target ->', target.name); 15 | 16 | let dflt = Reflect.getMetadata('fabric:default', global); 17 | 18 | logger.debug('Existing fabric:default', dflt); 19 | 20 | if (dflt) { 21 | throw new Error('A default has already been specified'); 22 | } 23 | 24 | const contract = new(target); 25 | 26 | dflt = contract.getName(); 27 | 28 | Reflect.defineMetadata('fabric:default', dflt, global); 29 | 30 | logger.debug('Updated fabric:default', dflt); 31 | }; 32 | }; 33 | -------------------------------------------------------------------------------- /apis/fabric-contract-api/lib/annotations/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright IBM Corp. All Rights Reserved. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | 'use strict'; 8 | Object.assign(module.exports, require('./transaction'), require('./object'), require('./info'), require('./default')); 9 | -------------------------------------------------------------------------------- /apis/fabric-contract-api/lib/annotations/info.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright IBM Corp. All Rights Reserved. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | const Logger = require('../logger'); 8 | const logger = Logger.getLogger('./lib/annotations/info.js'); 9 | require('reflect-metadata'); 10 | 11 | module.exports.Info = function Info (info = {}) { 12 | return (target) => { 13 | logger.info('@Info args:', `Info -> ${info},`, 'Target ->', target.name); 14 | 15 | const data = Reflect.getMetadata('fabric:info', global) || {}; 16 | 17 | logger.debug('Existing fabric:info', data); 18 | 19 | if (!info.name) { 20 | info.name = target.name; 21 | } 22 | if (!info.version) { 23 | info.version = ''; 24 | } 25 | 26 | data[target.name] = {}; 27 | Object.assign(data[target.name], info); 28 | 29 | Reflect.defineMetadata('fabric:info', data, global); 30 | 31 | logger.debug('Updated fabric:info', data); 32 | }; 33 | }; 34 | 35 | -------------------------------------------------------------------------------- /apis/fabric-contract-api/lib/annotations/object.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright IBM Corp. All Rights Reserved. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | const Logger = require('../logger'); 8 | const logger = Logger.getLogger('./lib/annotations/object.js'); 9 | const utils = require('./utils'); 10 | require('reflect-metadata'); 11 | 12 | const getProto = function (prototype) { 13 | return Object.getPrototypeOf(prototype); 14 | }; 15 | 16 | module.exports.Object = function Object (opts) { 17 | return (target) => { 18 | logger.info('@Object args: Target -> %s', target.constructor.name); 19 | 20 | const objects = Reflect.getMetadata('fabric:objects', global) || {}; 21 | 22 | logger.debug('Existing fabric:objects %s', objects); 23 | 24 | const properties = Reflect.getMetadata('fabric:object-properties', target.prototype) || {}; 25 | 26 | logger.debug('Existing fabric:object-properties for target', properties); 27 | 28 | // check for the presence of a supertype 29 | const supertype = getProto(target.prototype).constructor.name; 30 | 31 | if (supertype === 'Object') { 32 | objects[target.name] = { 33 | '$id': target.name, 34 | type: 'object', 35 | cnstr: target, 36 | properties: properties 37 | }; 38 | 39 | // add in the discriminator property name if one has been supplied in the object annotations 40 | if (opts && opts.discriminator) { 41 | objects[target.name].discriminator = {propertyName: opts.discriminator}; 42 | } 43 | } else { 44 | objects[target.name] = { 45 | '$id': target.name, 46 | cnstr: target, 47 | allOf: [ 48 | { 49 | type: 'object', 50 | properties: properties 51 | }, 52 | { 53 | '$ref': `${supertype}` 54 | } 55 | ] 56 | }; 57 | } 58 | 59 | Reflect.defineMetadata('fabric:objects', objects, global); 60 | 61 | logger.debug('Updated fabric:objects', objects); 62 | }; 63 | }; 64 | 65 | module.exports.Property = function Property (name, type) { 66 | return (target, propertyKey) => { 67 | logger.debug('@Property args:', `Property Key -> ${propertyKey}, Name -> ${name}, Type -> ${type},`, 'Target ->', target.constructor.name); 68 | 69 | const properties = Reflect.getOwnMetadata('fabric:object-properties', target) || {}; 70 | 71 | logger.debug('Existing fabric:object-properties for target', properties); 72 | 73 | if (!name || !type) { 74 | name = propertyKey; 75 | 76 | const metaType = Reflect.getMetadata('design:type', target, propertyKey); 77 | type = typeof metaType === 'function' ? metaType.name : metaType.toString(); 78 | } 79 | 80 | properties[name] = utils.generateSchema(type, false); 81 | 82 | Reflect.defineMetadata('fabric:object-properties', properties, target); 83 | 84 | logger.debug('Updated fabric:object-properties for target', properties); 85 | }; 86 | }; 87 | -------------------------------------------------------------------------------- /apis/fabric-contract-api/lib/annotations/utils.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright IBM Corp. All Rights Reserved. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | const refPath = '#/components/schemas/'; 8 | 9 | module.exports.appendOrUpdate = function appendOrUpdate(arr, primaryField, id, data) { 10 | const objExists = arr.some((obj) => { 11 | if (obj[primaryField] === id) { 12 | Object.assign(obj, data); 13 | return true; 14 | } 15 | }); 16 | 17 | if (!objExists) { 18 | const obj = data; 19 | data[primaryField] = id; 20 | arr.push(obj); 21 | } 22 | }; 23 | 24 | module.exports.findByValue = function findByValue(arr, primaryField, id) { 25 | for (const el of arr) { 26 | if (el[primaryField] === id) { 27 | return el; 28 | } 29 | } 30 | 31 | return null; 32 | }; 33 | 34 | const generateSchema = (type, fullPath = true) => { 35 | if (isPrimitive(type)) { 36 | return { 37 | type: type.toLowerCase() 38 | }; 39 | } else if (isArray(type)) { 40 | const subType = getSubArray(type); 41 | 42 | return { 43 | type: 'array', 44 | items: generateSchema(subType, fullPath) 45 | }; 46 | } else if (isMap(type)) { 47 | const subType = getSubMap(type); 48 | 49 | return { 50 | type: 'object', 51 | additionalProperties: generateSchema(subType, fullPath) 52 | }; 53 | } 54 | 55 | return { 56 | $ref: (fullPath ? refPath : '') + type 57 | }; 58 | }; 59 | module.exports.generateSchema = generateSchema; 60 | 61 | // there appears to be confusions within the meta data handling 62 | // whether string or String is correct. 63 | // string is the preferred for JSON Schema 64 | function isPrimitive(type) { 65 | const lowerCase = type.toLowerCase(); 66 | switch (lowerCase) { 67 | case 'string': 68 | case 'number': 69 | case 'boolean': 70 | return lowerCase; 71 | 72 | default: 73 | return undefined; 74 | } 75 | } 76 | 77 | // Like Array 78 | function isArrowedArray(type) { 79 | return /^Array<[A-z].*>$/.test(type); 80 | } 81 | 82 | // Like number[] 83 | function isBracketArray(type) { 84 | return /^[A-z].*(\[\])+?/.test(type); 85 | } 86 | 87 | // determine if string representation of type 88 | // is in format of an arrray descriptor 89 | function isArray(type) { 90 | return isArrowedArray(type) || isBracketArray(type); 91 | } 92 | 93 | function getSubArray(type) { 94 | if (isArrowedArray(type)) { 95 | return type.replace('Array<', '').replace('>', ''); 96 | } 97 | 98 | return type.replace('[]', ''); 99 | } 100 | 101 | function isMap(type) { 102 | return /^Map<[A-z].*,\s?[A-z].*>$/.test(type); 103 | } 104 | 105 | function getSubMap(type) { 106 | return type.replace(/^Map<[A-z].*?,\s?/, '').replace('>', ''); 107 | } 108 | -------------------------------------------------------------------------------- /apis/fabric-contract-api/lib/context.js: -------------------------------------------------------------------------------- 1 | /* 2 | # Copyright IBM Corp. All Rights Reserved. 3 | # 4 | # SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | 'use strict'; 8 | 9 | /** 10 | * The Context class provides the transactional context per a transactional execution. 11 | * 12 | * This can be subclassed to provided additional functional behaviour to support 13 | * smart contract execution. 14 | * 15 | * An example would be to provide additional help to map application object ids to world state 16 | * composite keys. 17 | * 18 | * In the constructor, do not reference the stub or clientidentity functions. 19 | * 20 | * @example 21 | * class ScenarioContext extends Context{ 22 | 23 | constructor(){ 24 | super(); 25 | } 26 | 27 | 28 | generateKey(){ 29 | return this.stub.createCompositeKey('type',['keyvalue']); 30 | } 31 | 32 | } 33 | * 34 | * @memberof fabric-contract-api 35 | */ 36 | class Context { 37 | 38 | constructor() { 39 | } 40 | 41 | /** 42 | * This sets the chaincode stub object with api to use for worldstate access. 43 | * MUST NOT BE CALLED FROM SMART CONTRACT CODE 44 | * 45 | * @param {ChaincodeStub} stub chaincode stub instance 46 | */ 47 | setChaincodeStub(stub) { 48 | this.stub = stub; 49 | } 50 | 51 | /** 52 | * This sets the ClientIdentity object to use for information on the transaction invoking identity 53 | * MUST NOT BE CALLED FROM SMART CONTRACT CODE 54 | * 55 | * @param {ClientIdentity} clientIdentity chaincode stub instance 56 | */ 57 | setClientIdentity(clientIdentity) { 58 | this.clientIdentity = clientIdentity; 59 | } 60 | } 61 | 62 | module.exports = Context; 63 | -------------------------------------------------------------------------------- /apis/fabric-contract-api/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fabric-contract-api", 3 | "version": "2.5.9", 4 | "tag": "latest", 5 | "description": "A node.js implementation of Hyperledger Fabric chaincode shim, to allow endorsing peers and user-provided chaincodes to communicate with each other", 6 | "main": "index.js", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/hyperledger/fabric-chaincode-node" 10 | }, 11 | "scripts": { 12 | "buildt": "tsc --project test/typescript", 13 | "test": "nyc mocha --recursive 'test/unit/**/*.js'", 14 | "build": "npm run lint && npm run test:unit && npm run test:schema", 15 | "lint": "eslint ./lib ./types ./test/typescript/*.ts --ext .js --ext .ts", 16 | "test:unit": "npm run test", 17 | "test:schema": "ajv compile -s ./schema/contract-schema.json && ajv validate -s ./schema/contract-schema.json -d ./schema/example-full.json" 18 | }, 19 | "keywords": [ 20 | "fabric-shim", 21 | "Hyperledger Fabric", 22 | "Fabric Shim" 23 | ], 24 | "engines": { 25 | "node": ">=18" 26 | }, 27 | "license": "Apache-2.0", 28 | "types": "./types/index.d.ts", 29 | "nyc": { 30 | "exclude": [ 31 | "coverage/**", 32 | "test/**", 33 | "gulpfile.js" 34 | ], 35 | "reporter": [ 36 | "text-summary", 37 | "html", 38 | "cobertura" 39 | ], 40 | "all": true, 41 | "check-coverage": true, 42 | "statements": 100, 43 | "branches": 100, 44 | "functions": 100, 45 | "lines": 100 46 | }, 47 | "dependencies": { 48 | "fabric-shim-api": "2.5.9", 49 | "class-transformer": "^0.4.0", 50 | "fast-safe-stringify": "^2.1.1", 51 | "get-params": "^0.1.2", 52 | "reflect-metadata": "^0.1.13", 53 | "winston": "^3.7.2" 54 | }, 55 | "devDependencies": { 56 | "ajv": "^6.12.2", 57 | "ajv-cli": "^3.2.1", 58 | "ajv-formats": "2.1.1", 59 | "chai": "^4.3.4", 60 | "chai-as-promised": "^7.1.1", 61 | "chai-things": "^0.2.0", 62 | "eslint": "^6.6.0", 63 | "gulp": "^4.0.2", 64 | "gulp-debug": "~4.0.0", 65 | "gulp-eslint": "~6.0.0", 66 | "mocha": "9.1.3", 67 | "nyc": "15.1.0", 68 | "rewire": "6.0.0", 69 | "sinon": "13.0.1", 70 | "typescript": "4.4.4" 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /apis/fabric-contract-api/schema/data.json: -------------------------------------------------------------------------------- 1 | { 2 | "firstName": "John", 3 | "lastName": "Doe", 4 | "age": 21 5 | } -------------------------------------------------------------------------------- /apis/fabric-contract-api/schema/helloworld.json: -------------------------------------------------------------------------------- 1 | { 2 | "contracts": { 3 | "Greeting": { 4 | "name": "Greeting", 5 | "contractInstance": { 6 | "name": "Greeting" 7 | }, 8 | "transactions": [ 9 | { 10 | "tag": [ 11 | "SUBMIT", 12 | "submitTx" 13 | ], 14 | "parameters": [], 15 | "name": "instantiate" 16 | }, 17 | { 18 | "tag": [ 19 | "SUBMIT", 20 | "submitTx" 21 | ], 22 | "parameters": [ 23 | { 24 | "name": "text", 25 | "description": "", 26 | "schema": { 27 | "type": "string" 28 | } 29 | } 30 | ], 31 | "name": "setGreetingText" 32 | }, 33 | { 34 | "tag": [ 35 | "SUBMIT", 36 | "submitTx" 37 | ], 38 | "parameters": [ 39 | { 40 | "name": "greeting", 41 | "description": "", 42 | "schema": { 43 | "$ref": "#/components/schemas/greeting" 44 | } 45 | } 46 | ], 47 | "name": "setGreeting" 48 | }, 49 | { 50 | "returns": [ 51 | { 52 | "name": "success", 53 | "schema": { 54 | "$ref": "#/components/schemas/greeting" 55 | } 56 | } 57 | ], 58 | "name": "getGreeting", 59 | "tag": [ 60 | "SUBMIT", 61 | "submitTx" 62 | ], 63 | "parameters": [] 64 | } 65 | ], 66 | "info": { 67 | "title": "", 68 | "version": "" 69 | } 70 | }, 71 | "org.hyperledger.fabric": { 72 | "name": "org.hyperledger.fabric", 73 | "contractInstance": { 74 | "name": "org.hyperledger.fabric" 75 | }, 76 | "transactions": [ 77 | { 78 | "name": "setMetadata" 79 | }, 80 | { 81 | "name": "GetMetadata" 82 | } 83 | ], 84 | "info": { 85 | "title": "", 86 | "version": "" 87 | } 88 | } 89 | }, 90 | "info": { 91 | "version": "0.0.1", 92 | "title": "helloworld-ts" 93 | }, 94 | "components": { 95 | "schemas": { 96 | "Greeting": { 97 | "$id": "Greeting", 98 | "properties": [ 99 | { 100 | "name": "text", 101 | "schema": { 102 | "type": "string" 103 | } 104 | } 105 | ] 106 | } 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /apis/fabric-contract-api/schema/testschema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$id": "https://example.com/person.schema.json", 3 | "$schema": "http://json-schema.org/draft-04/schema#", 4 | "title": "Person", 5 | "type": "object", 6 | "properties": { 7 | "firstName": { 8 | "type": "string", 9 | "description": "The person's first name." 10 | }, 11 | "lastName": { 12 | "type": "string", 13 | "description": "The person's last name." 14 | }, 15 | "age": { 16 | "description": "Age in years which must be equal to or greater than zero.", 17 | "type": "integer", 18 | "minimum": 0 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /apis/fabric-contract-api/test/typescript/smartcontract.ts: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 IBM All Rights Reserved. 3 | 4 | SPDX-License-Identifier: Apache-2.0 5 | 6 | */ 7 | 8 | import {Contract, Context} from 'fabric-contract-api'; 9 | import {ChaincodeStub, ClientIdentity} from 'fabric-shim-api'; 10 | 11 | export class ScenarioContext extends Context { 12 | customFunction(): void { 13 | 14 | } 15 | } 16 | 17 | export default class TestContractOne extends Contract { 18 | constructor() { 19 | super('org.papernet.commercialpaper'); 20 | } 21 | 22 | beforeTransaction(ctx: ScenarioContext) { 23 | // test that the context super class properties are available 24 | const stubApi: ChaincodeStub = ctx.stub; 25 | const clientIdentity: ClientIdentity = ctx.clientIdentity; 26 | 27 | // tests that the functions in the subclasses context be called 28 | ctx.customFunction(); 29 | 30 | // This proves that typescript is enforcing the 31 | // return type of Promise 32 | return Promise.resolve(); 33 | } 34 | 35 | afterTransaction(ctx: ScenarioContext, result: any) { 36 | // This proves that typescript is enforcing the 37 | // return type of Promise 38 | return Promise.resolve(); 39 | } 40 | 41 | aroundTransaction(ctx: ScenarioContext, fn: Function, parameters: any) { 42 | // This proves that typescript is enforcing the 43 | // return type of Promise 44 | return super.aroundTransaction(ctx, fn, parameters); 45 | } 46 | 47 | unknownTransaction(ctx: ScenarioContext) { 48 | // This proves that typescript is enforcing the 49 | // return type of Promise 50 | return Promise.resolve(); 51 | } 52 | 53 | createContext() { 54 | return new ScenarioContext(); 55 | } 56 | 57 | async Transaction(ctx: ScenarioContext) { 58 | // test that the context super class properties are available 59 | const stubApi: ChaincodeStub = ctx.stub; 60 | const clientIdentity: ClientIdentity = ctx.clientIdentity; 61 | 62 | // test that the name returns a string 63 | const ns: string = this.getName(); 64 | } 65 | } 66 | 67 | export class TestContractTwo extends Contract { 68 | constructor() { 69 | super(); 70 | } 71 | 72 | async Transaction(ctx: Context) { 73 | const stubApi: ChaincodeStub = ctx.stub; 74 | const clientIdentity: ClientIdentity = ctx.clientIdentity; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /apis/fabric-contract-api/test/unit/annotations/default.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright IBM Corp. All Rights Reserved. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | const sinon = require('sinon'); 8 | const rewire = require('rewire'); 9 | 10 | const chai = require('chai'); 11 | const expect = chai.expect; 12 | 13 | const DefaultAnnotations = rewire('./../../../lib/annotations/default'); 14 | const Default = DefaultAnnotations.Default; 15 | 16 | describe ('Default.js', () => { 17 | 18 | const mockTarget = class { 19 | constructor() {} 20 | 21 | getName() { 22 | return 'jeremy'; 23 | } 24 | }; 25 | 26 | let defineMetadataStub; 27 | let getMetadataStub; 28 | beforeEach(() => { 29 | getMetadataStub = sinon.stub(Reflect, 'getMetadata'); 30 | defineMetadataStub = sinon.stub(Reflect, 'defineMetadata'); 31 | }); 32 | 33 | afterEach(() => { 34 | getMetadataStub.restore(); 35 | defineMetadataStub.restore(); 36 | }); 37 | 38 | describe('Default', () => { 39 | 40 | let dflt; 41 | 42 | beforeEach(() => { 43 | dflt = Default(); 44 | }); 45 | 46 | it ('should add set value for default when none set', () => { 47 | getMetadataStub 48 | .onFirstCall().returns(undefined); 49 | 50 | dflt(mockTarget); 51 | 52 | sinon.assert.calledOnce(getMetadataStub); 53 | sinon.assert.calledWith(getMetadataStub, 'fabric:default', global); 54 | sinon.assert.calledOnce(defineMetadataStub); 55 | sinon.assert.calledWith(defineMetadataStub, 'fabric:default', 56 | 'jeremy' 57 | ); 58 | }); 59 | 60 | it ('should error when default already set', () => { 61 | getMetadataStub 62 | .onFirstCall().returns('theresa'); 63 | 64 | expect(() => { 65 | dflt(mockTarget); 66 | }).to.throw('A default has already been specified'); 67 | 68 | sinon.assert.calledOnce(getMetadataStub); 69 | sinon.assert.calledWith(getMetadataStub, 'fabric:default', global); 70 | sinon.assert.notCalled(defineMetadataStub); 71 | }); 72 | }); 73 | }); 74 | -------------------------------------------------------------------------------- /apis/fabric-contract-api/test/unit/annotations/info.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright IBM Corp. All Rights Reserved. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | const sinon = require('sinon'); 8 | const rewire = require('rewire'); 9 | 10 | const InfoAnnotations = rewire('./../../../lib/annotations/info'); 11 | const Info = InfoAnnotations.Info; 12 | 13 | 14 | describe ('Info.js', () => { 15 | 16 | const mockTarget = { 17 | name: 'steve' 18 | }; 19 | 20 | let defineMetadataStub; 21 | let getMetadataStub; 22 | beforeEach(() => { 23 | getMetadataStub = sinon.stub(Reflect, 'getMetadata'); 24 | defineMetadataStub = sinon.stub(Reflect, 'defineMetadata'); 25 | }); 26 | 27 | afterEach(() => { 28 | getMetadataStub.restore(); 29 | defineMetadataStub.restore(); 30 | }); 31 | 32 | describe('Info', () => { 33 | 34 | let info; 35 | 36 | beforeEach(() => { 37 | info = Info(); 38 | }); 39 | 40 | it ('should add object as key when no objects exist for global yet', () => { 41 | getMetadataStub 42 | .onFirstCall().returns(undefined); 43 | 44 | info(mockTarget); 45 | 46 | sinon.assert.calledOnce(getMetadataStub); 47 | sinon.assert.calledWith(getMetadataStub, 'fabric:info', global); 48 | sinon.assert.calledOnce(defineMetadataStub); 49 | sinon.assert.calledWith(defineMetadataStub, 'fabric:info', 50 | {steve: {name: 'steve', version: ''}} 51 | ); 52 | }); 53 | 54 | it ('should add object as key when objects exist for global', () => { 55 | getMetadataStub 56 | .onFirstCall().returns({'object1': {}}); 57 | 58 | info(mockTarget); 59 | 60 | sinon.assert.calledOnce(getMetadataStub); 61 | sinon.assert.calledWith(getMetadataStub, 'fabric:info', global); 62 | sinon.assert.calledOnce(defineMetadataStub); 63 | sinon.assert.calledWith(defineMetadataStub, 'fabric:info', { 64 | 'object1': {}, 65 | 'steve': {name: 'steve', version: ''} 66 | }); 67 | }); 68 | }); 69 | describe('Info with data', () => { 70 | 71 | let info; 72 | 73 | beforeEach(() => { 74 | info = Info({name: 'bill', version: '1.0.1'}); 75 | }); 76 | 77 | it ('should add object as key when no objects exist for global yet', () => { 78 | getMetadataStub 79 | .onFirstCall().returns(undefined); 80 | 81 | info(mockTarget); 82 | 83 | sinon.assert.calledOnce(getMetadataStub); 84 | sinon.assert.calledWith(getMetadataStub, 'fabric:info', global); 85 | sinon.assert.calledOnce(defineMetadataStub); 86 | sinon.assert.calledWith(defineMetadataStub, 'fabric:info', 87 | {steve: {name: 'bill', version: '1.0.1'}} 88 | ); 89 | }); 90 | 91 | it ('should add object as key when objects exist for global', () => { 92 | getMetadataStub 93 | .onFirstCall().returns({'object1': {}}); 94 | 95 | info(mockTarget); 96 | 97 | sinon.assert.calledOnce(getMetadataStub); 98 | sinon.assert.calledWith(getMetadataStub, 'fabric:info', global); 99 | sinon.assert.calledOnce(defineMetadataStub); 100 | sinon.assert.calledWith(defineMetadataStub, 'fabric:info', { 101 | 'object1': {}, 102 | 'steve': {name: 'bill', version: '1.0.1'} 103 | }); 104 | }); 105 | }); 106 | }); 107 | -------------------------------------------------------------------------------- /apis/fabric-contract-api/test/unit/context.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright IBM Corp. All Rights Reserved. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | /* global describe it beforeEach afterEach */ 8 | 'use strict'; 9 | 10 | const chai = require('chai'); 11 | chai.should(); 12 | 13 | chai.use(require('chai-as-promised')); 14 | chai.use(require('chai-things')); 15 | const sinon = require('sinon'); 16 | 17 | const path = require('path'); 18 | // class under test 19 | const pathToRoot = '../../..'; 20 | 21 | const Context = require(path.join(pathToRoot, 'fabric-contract-api/lib/context')); 22 | 23 | describe('contract.js', () => { 24 | 25 | let sandbox; 26 | 27 | beforeEach('Sandbox creation', () => { 28 | sandbox = sinon.createSandbox(); 29 | }); 30 | 31 | afterEach('Sandbox restoration', () => { 32 | sandbox.restore(); 33 | }); 34 | 35 | describe('#constructor', () => { 36 | 37 | it ('should create plain object ok', () => { 38 | const sc0 = new Context(); 39 | sc0.should.be.an.instanceOf(Context); 40 | }); 41 | 42 | it ('should have set* methods', () => { 43 | const sc0 = new Context(); 44 | sc0.setChaincodeStub('a stub'); 45 | sc0.stub.should.equal('a stub'); 46 | sc0.setClientIdentity('a client identity'); 47 | sc0.clientIdentity.should.equal('a client identity'); 48 | }); 49 | 50 | }); 51 | 52 | }); 53 | -------------------------------------------------------------------------------- /apis/fabric-contract-api/test/unit/data.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperledger/fabric-chaincode-node/96d934ee63fc7fc19de817dc5eb05f04b0306b55/apis/fabric-contract-api/test/unit/data.json -------------------------------------------------------------------------------- /apis/fabric-contract-api/test/unit/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright IBM Corp. All Rights Reserved. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | 'use strict'; 8 | 9 | require('../../index.js'); 10 | -------------------------------------------------------------------------------- /apis/fabric-contract-api/tsconfig.json: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 IBM All Rights Reserved. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | { 7 | "compilerOptions": { 8 | "types": ["./types/"], 9 | "alwaysStrict": true, 10 | "module": "commonjs", 11 | "declaration": true, 12 | "sourceMap": true, 13 | "strict": true, 14 | "target": "es2017", 15 | "lib": [ 16 | "esnext", 17 | ] 18 | }, 19 | "include": [ 20 | "lib/**/*", 21 | "test/**/*" 22 | ], 23 | "exclude": [ 24 | "node_modules/**/*" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /apis/fabric-contract-api/types/index.d.ts: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 IBM All Rights Reserved. 3 | 4 | SPDX-License-Identifier: Apache-2.0 5 | 6 | */ 7 | 8 | declare module 'fabric-contract-api' { 9 | import {Logger} from 'winston'; 10 | import {ChaincodeStub, ClientIdentity} from 'fabric-shim-api'; 11 | 12 | export class Context { 13 | stub: ChaincodeStub; 14 | clientIdentity: ClientIdentity; 15 | logging: { 16 | setLevel: (level: string) => void, 17 | getLogger: (name?: string) => Logger 18 | } 19 | } 20 | 21 | export class Contract { 22 | constructor(name?: string); 23 | 24 | static _isContract(): boolean; 25 | 26 | beforeTransaction(ctx : Context): Promise; 27 | afterTransaction(ctx : Context, result: any): Promise; 28 | aroundTransaction(ctx : Context, fn : Function, parameters: any): Promise; 29 | 30 | unknownTransaction(ctx : Context): Promise; 31 | 32 | createContext(): Context; 33 | getName(): string; 34 | 35 | } 36 | 37 | 38 | export class JSONSerializer { 39 | toBuffer(result: any, schema:any, loggerPrefix?:string): Buffer; 40 | fromBuffer(data: Buffer, schema:any, loggerPrefix?:string): any; 41 | } 42 | 43 | export function Transaction(commit?: boolean): (target: any, propertyKey: string | symbol) => void; 44 | export function Param(paramName: string, paramType: string, description?: string): (target: any, propertyKey: string | symbol) => void; 45 | export function Returns(returnType?: string): (target: any, propertyKey: string | symbol) => void; 46 | export function Object(opts?: object): (target: any) => void; 47 | export function Info(info?: object): (target: any) => void; 48 | export function Property(name?: string, type?: string): (target: any, propertyKey: string | symbol) => void; 49 | export function Default(): (target: any) => void; 50 | } 51 | -------------------------------------------------------------------------------- /apis/fabric-shim-api/README.md: -------------------------------------------------------------------------------- 1 | [![NPM](https://nodei.co/npm/fabric-shim-api.svg?downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/fabric-shim-api/) 2 | 3 | 4 | [![Version](https://badge.fury.io/js/fabric-shim-api.svg)](http://badge.fury.io/js/fabric-shim-api) 5 | 6 | This `fabric-shim-api` library provides type definitions for the `fabric-shim` module. It is also a dependency of the `fabric-contract-api` As this is a pure interface module it allows the `fabric-contract-api` annotations to be used in client application without the need to pull in unneeded required dependencies. 7 | 8 | Detailed explanation on the concepts and programming model can be found here: [https://hyperledger-fabric.readthedocs.io/en/latest/smartcontract/smartcontract.html](https://hyperledger-fabric.readthedocs.io/en/latest/smartcontract/smartcontract.html). 9 | 10 | 11 | ## License 12 | 13 | This package is distributed under the 14 | [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0), 15 | see LICENSE for more information. 16 | -------------------------------------------------------------------------------- /apis/fabric-shim-api/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | # Copyright IBM Corp. All Rights Reserved. 3 | # 4 | # SPDX-License-Identifier: Apache-2.0 5 | */ -------------------------------------------------------------------------------- /apis/fabric-shim-api/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fabric-shim-api", 3 | "version": "2.5.9", 4 | "tag": "latest", 5 | "description": "A node.js API of Hyperledger Fabric chaincode shim, to allow endorsing peers and user-provided chaincodes to communicate with each other", 6 | "main": "index.js", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/hyperledger/fabric-chaincode-node" 10 | }, 11 | "scripts": { 12 | "lint": "eslint ./types/ --ext .ts", 13 | "build": "echo No Build needed" 14 | }, 15 | "keywords": [ 16 | "fabric-shim", 17 | "Hyperledger Fabric", 18 | "Fabric Shim" 19 | ], 20 | "engines": { 21 | "node": ">=18", 22 | "eslint": "^6.6.0" 23 | }, 24 | "types": "./types/index.d.ts", 25 | "license": "Apache-2.0", 26 | "devDependencies": { 27 | "@types/long": "^4.0.1", 28 | "eslint": "^6.6.0" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /apis/fabric-shim-api/tsconfig.json: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 IBM All Rights Reserved. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | { 7 | "compilerOptions": { 8 | "types": ["./types/"], 9 | "alwaysStrict": true, 10 | "module": "commonjs", 11 | "declaration": true, 12 | "sourceMap": true, 13 | "strict": true, 14 | "target": "es2017", 15 | "lib": [ 16 | "esnext", 17 | ] 18 | }, 19 | "files": [ 20 | "types/index.d.ts" 21 | ], 22 | "exclude": [ 23 | "node_modules/**/*" 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /common/scripts/install-run-rush-pnpm.js: -------------------------------------------------------------------------------- 1 | // THIS FILE WAS GENERATED BY A TOOL. ANY MANUAL MODIFICATIONS WILL GET OVERWRITTEN WHENEVER RUSH IS UPGRADED. 2 | // 3 | // This script is intended for usage in an automated build environment where the Rush command may not have 4 | // been preinstalled, or may have an unpredictable version. This script will automatically install the version of Rush 5 | // specified in the rush.json configuration file (if not already installed), and then pass a command-line to the 6 | // rush-pnpm command. 7 | // 8 | // An example usage would be: 9 | // 10 | // node common/scripts/install-run-rush-pnpm.js pnpm-command 11 | // 12 | // For more information, see: https://rushjs.io/pages/maintainer/setup_new_repo/ 13 | 14 | /******/ (() => { // webpackBootstrap 15 | /******/ "use strict"; 16 | var __webpack_exports__ = {}; 17 | /*!*****************************************************!*\ 18 | !*** ./lib-esnext/scripts/install-run-rush-pnpm.js ***! 19 | \*****************************************************/ 20 | 21 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. 22 | // See LICENSE in the project root for license information. 23 | require('./install-run-rush'); 24 | //# sourceMappingURL=install-run-rush-pnpm.js.map 25 | module.exports = __webpack_exports__; 26 | /******/ })() 27 | ; 28 | //# sourceMappingURL=install-run-rush-pnpm.js.map -------------------------------------------------------------------------------- /common/scripts/install-run-rushx.js: -------------------------------------------------------------------------------- 1 | // THIS FILE WAS GENERATED BY A TOOL. ANY MANUAL MODIFICATIONS WILL GET OVERWRITTEN WHENEVER RUSH IS UPGRADED. 2 | // 3 | // This script is intended for usage in an automated build environment where the Rush command may not have 4 | // been preinstalled, or may have an unpredictable version. This script will automatically install the version of Rush 5 | // specified in the rush.json configuration file (if not already installed), and then pass a command-line to the 6 | // rushx command. 7 | // 8 | // An example usage would be: 9 | // 10 | // node common/scripts/install-run-rushx.js custom-command 11 | // 12 | // For more information, see: https://rushjs.io/pages/maintainer/setup_new_repo/ 13 | 14 | /******/ (() => { // webpackBootstrap 15 | /******/ "use strict"; 16 | var __webpack_exports__ = {}; 17 | /*!*************************************************!*\ 18 | !*** ./lib-esnext/scripts/install-run-rushx.js ***! 19 | \*************************************************/ 20 | 21 | // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. 22 | // See LICENSE in the project root for license information. 23 | require('./install-run-rush'); 24 | //# sourceMappingURL=install-run-rushx.js.map 25 | module.exports = __webpack_exports__; 26 | /******/ })() 27 | ; 28 | //# sourceMappingURL=install-run-rushx.js.map -------------------------------------------------------------------------------- /docker/fabric-nodeenv/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright IBM Corp. All Rights Reserved. 2 | # 3 | # SPDX-License-Identifier: Apache-2.0 4 | # 5 | ARG NODE_IMAGE_TAG=22-alpine 6 | FROM node:${NODE_IMAGE_TAG} 7 | RUN apk add --no-cache \ 8 | make \ 9 | python3 \ 10 | g++ 11 | RUN mkdir -p /chaincode/input \ 12 | && mkdir -p /chaincode/output \ 13 | && mkdir -p /usr/local/src 14 | ADD build.sh start.sh /chaincode/ 15 | -------------------------------------------------------------------------------- /docker/fabric-nodeenv/README.md: -------------------------------------------------------------------------------- 1 | # Quick reference 2 | 3 | - **Maintained by**: 4 | [The Fabric Node chaincode maintainers](https://github.com/hyperledger/fabric-chaincode-node) 5 | 6 | # Overview 7 | 8 | This image is used by the default [Hyperledger Fabric](https://hyperledger-fabric.readthedocs.io/) chaincode builder when deploying Node (TypeScript or JavaScript) smart contracts. It is not intended for use independently of Hyperledger Fabric. 9 | 10 | # Image variants 11 | 12 | Detailed information on image tags, interoperability, and supported Node versions can be found in the [compatibility](https://github.com/hyperledger/fabric-chaincode-node/blob/main/COMPATIBILITY.md) documentation. 13 | 14 | # License 15 | 16 | This image is provided under the [Apache-2.0](https://github.com/hyperledger/fabric-chaincode-node/blob/main/LICENSE) license. 17 | -------------------------------------------------------------------------------- /docker/fabric-nodeenv/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # SPDX-License-Identifier: Apache-2.0 4 | # 5 | set -ex 6 | INPUT_DIR=/chaincode/input 7 | OUTPUT_DIR=/chaincode/output 8 | cp -R ${INPUT_DIR}/src/. ${OUTPUT_DIR} 9 | cd ${OUTPUT_DIR} 10 | if [ -f package-lock.json ] || [ -f npm-shrinkwrap.json ]; then 11 | npm ci --omit=dev 12 | else 13 | npm install --omit=dev 14 | fi 15 | -------------------------------------------------------------------------------- /docker/fabric-nodeenv/docker.js: -------------------------------------------------------------------------------- 1 | /* 2 | # Copyright IBM Corp. All Rights Reserved. 3 | # 4 | # SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | /* eslint-disable no-console*/ 8 | 'use strict'; 9 | 10 | const fs = require('node:fs'); 11 | const git = require('git-rev-sync'); 12 | const path = require('node:path'); 13 | const { execSync } = require('node:child_process'); 14 | const process = require('node:process'); 15 | 16 | const version = JSON.parse(fs.readFileSync(path.join(__dirname,'package.json'))).version; 17 | const build_dir = path.join(__dirname); 18 | const tag = version + '-' + git.short(); 19 | const imageName = 'hyperledger/fabric-nodeenv' 20 | 21 | // reg exp the sort tag versions 22 | const regex = /^(\d+\.\d+)/ 23 | const shortVersion = version.match(regex); 24 | 25 | function runCmd(command) { 26 | console.log(command); 27 | execSync(command, { 28 | stdio: 'inherit', 29 | }); 30 | } 31 | 32 | // build and tag the fabric-nodeenv image 33 | function imageBuild() { 34 | runCmd(`docker build -t ${imageName}:${tag} -f ${path.join(build_dir, 'Dockerfile')} ${build_dir} 2>&1`); 35 | runCmd(`docker tag ${imageName}:${tag} ${imageName}:${version}`); 36 | runCmd(`docker tag ${imageName}:${tag} ${imageName}:${shortVersion[shortVersion.index]}`); 37 | runCmd(`docker tag ${imageName}:${tag} ${imageName}:latest`); 38 | }; 39 | 40 | // remove fabric-nodeenv images 41 | function imageClean() { 42 | runCmd(`docker images -q --filter=reference="${imageName}:${version}*" | uniq | xargs -r docker rmi -f`); 43 | }; 44 | 45 | try { 46 | imageClean(); 47 | imageBuild(); 48 | } catch (e) { 49 | console.error(e); 50 | process.exitCode = 1; 51 | } 52 | -------------------------------------------------------------------------------- /docker/fabric-nodeenv/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fabric-nodeenv", 3 | "version": "2.5.9", 4 | "description": "", 5 | "main": "docker.js", 6 | "scripts": { 7 | "build": "node docker.js" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "Apache-2.0", 12 | "dependencies": { 13 | "git-rev-sync": "3.0.2" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /docker/fabric-nodeenv/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # SPDX-License-Identifier: Apache-2.0 4 | # 5 | set -ex 6 | CHAINCODE_DIR=/usr/local/src 7 | cd ${CHAINCODE_DIR} 8 | npm start -- "$@" -------------------------------------------------------------------------------- /docs/404.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "404 - Page Not Found" 3 | permalink: /404.html 4 | --- 5 | 6 | ## The page you wanted does not exist 7 | 8 | If you were looking for JSDoc, try one of the releases below: 9 | 10 | {% include apidocs.html %} 11 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | [You probably want to look here](https://hyperledger.github.io/fabric-chaincode-node/) 2 | -------------------------------------------------------------------------------- /docs/_config.yml: -------------------------------------------------------------------------------- 1 | theme: minima 2 | title: "fabric-chaincode-node" 3 | releases: 4 | - main 5 | - release-1.4 6 | - release-2.2 7 | -------------------------------------------------------------------------------- /docs/_includes/apidocs.html: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /docs/_includes/footer.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperledger/fabric-chaincode-node/96d934ee63fc7fc19de817dc5eb05f04b0306b55/docs/_includes/footer.html -------------------------------------------------------------------------------- /docs/_includes/header.html: -------------------------------------------------------------------------------- 1 | 22 | -------------------------------------------------------------------------------- /docs/_jsdoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "source": { 3 | "include": [ 4 | "./_jsdoc/index.md", 5 | "../libraries/fabric-shim/lib/chaincode.js", 6 | "../libraries/fabric-shim/lib/stub.js", 7 | "../libraries/fabric-shim/lib/iterators.js", 8 | "../apis/fabric-contract-api/lib" 9 | ] 10 | }, 11 | "sourceType": "module", 12 | "opts": { 13 | "destination": "./gen", 14 | "recurse": true, 15 | "template": "./node_modules/ink-docstrap/template", 16 | "tutorials": "./_jsdoc/tutorials" 17 | }, 18 | "templates": { 19 | "systemName": "Hyperledger Fabric Contract API", 20 | "theme": "cosmo", 21 | "default": { 22 | "staticFiles": { 23 | "include": [ 24 | "./_jsdoc/static" 25 | ] 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /docs/_jsdoc/tutorials/data-types-and-contracts.md: -------------------------------------------------------------------------------- 1 | # How are data types handling with Contracts? 2 | This document deals with JavaScript and TypeScript contracts 3 | 4 | ## Function parameters 5 | 6 | ### JavaScript - no metadata 7 | 8 | This is the lowest common denominator; all data that is sent to the transaction function from the client is represented as strings. 9 | Therefore the conversion that takes place in the lack of any metadata is 10 | 11 | ``` 12 | json = JSON.parse(data.toString()); 13 | ``` 14 | 15 | If the json has a property of 'type' and that equals 'Buffer' then a byte buffer is constructed. The standard JSON.stringify() form of a byte buffer is to add the type field. 16 | 17 | It is then left to JavaScript to be able to coerce the data as per standard language rules 18 | 19 | ### JavaScript - with metadata 20 | 21 | If the metadata for the property specifies a String or a Number, then conversion to a String or Number takes place. 22 | Otherwise, the same conversion takes place as with 'no-metadata' 23 | 24 | 25 | ### Typescript 26 | Typescript needs to have no annotations for types, (other than arrays). The metadata is inferred with sufficient detail. 27 | For arrays, the `@Param(,,[])` needs to be used to mark the type that is in the array. 28 | 29 | 30 | ## Return types 31 | 32 | A transaction function is free to return anything it wishes. (Strictly speaking it must return a promise, and that can be resolved or rejected with anything). 33 | 34 | With the Node.js runtime, either JavaScript or TypeScript can be used. For both languages you can supply additional metadata, either as annotations, or as a JSON file. 35 | 36 | ### JavaScript - no metadata 37 | 38 | This is the lowest common denominator; if no metadata is either provided by annotations, file, or inferred by introspection this is behaviour. 39 | All return values will be processed as follows: 40 | 41 | ```javascript 42 | Buffer.from(JSON.stringify(functionsReturnValue)) 43 | ``` 44 | 45 | The data will be stringified, then converted to a buffer to be returned. The buffer conversion is required by the shim api to communicate with the peer. This will be 'reversed' in the client SDK so that clients are given a string. 46 | 47 | ### JavaScript with metadata 48 | 49 | It is beneficial to supply metadata; specifically in the case of JavaScript to identify strings and numbers from objects. 50 | 51 | By doing this means that the transaction functions can 52 | 53 | - Return strings and numbers directly. Numbers are converted to their textual form eg 42 becomes "42" 54 | - Anything else is returned by being stringified first 55 | 56 | ## Typescript 57 | 58 | Without the '@return' annotations and/or metadata Typescript introspection can not provide enough details about the return type. Primarily as this is a Promise that resolves a type introspection only indicates the promise aspect. 59 | 60 | Metadata can be explicitly provided or the `@Returns()` can be used to indicate the type. The annotation needs to have the type name specified as a string value. 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /docs/_jsdoc/tutorials/tutorials.json: -------------------------------------------------------------------------------- 1 | { 2 | "using-chaincodeinterface":{ 3 | "title":"Using the Chaincode Interface" 4 | }, 5 | "using-contractinterface":{ 6 | "title":"Using the Contract Interface" 7 | }, 8 | "annotated-contract-metadata":{ 9 | "title":"Walkthrough of annotated metadata.json" 10 | }, 11 | "deep-dive-contract-interface":{ 12 | "title":"Deep dive on Contract Interface" 13 | }, 14 | "using-typescript-decorators":{ 15 | "title":"Using TypeScript Decorators" 16 | }, 17 | "data-types-and-contracts":{ 18 | "title":"Details of type handling" 19 | }, 20 | "using-iterators": { 21 | "title":"Working with apis that return iterators" 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /docs/_jsdoc/tutorials/using-typescript-decorators.md: -------------------------------------------------------------------------------- 1 | # Summary of the Typescript Decorators 2 | 3 | When using Typescript to code the Contract implementations, Typescript Decorators can be used to provide additional metadata; together with the type information that can be introspected, a very detailed set of metadata can be put within the source code directly. 4 | 5 | ## Decorators available 6 | 7 | - @Info 8 | - Supplies information about the following contract such as license terms or author. 9 | - This takes as a parameter an object that has the key-value pairs as defined on the OpenAPI v3 [Info object spec](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#infoObject) 10 | - @Transaction 11 | - Defines the following function to be a callable transaction function 12 | - Takes a boolean parameter; true indicates that this function is intended to be called with the 'submit' semantics, false indicates that this is intended to be called with the evaluate semantics. (Submit means submit to the orderer to be recorded on the ledger) 13 | - Default is true 14 | - @Returns 15 | - Takes a string that is the name of the type that is being returned by this function 16 | - This is present as required as Typescript does not give back the complete return type 17 | - @Object 18 | - Defines the class that represents one of the complex types that can be returned or passed to the transaction functions 19 | - @Property 20 | - Defines a property of the a class (identified by @Object) that should be passed within the object 21 | - @Param 22 | - Permits additional information such as a type and description to provided for parameters. (Note type is only useful in weakly typed languages) 23 | 24 | **Note that emitDecoratorMetadata property in *tsconfig.json* file is mandatory.** 25 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: home 3 | --- 4 | 5 | Hyperledger Fabric offers a number of SDKs to support developing smart contracts (chaincode) 6 | in various programming languages. There are two other smart contract SDKs available for Java, and Go, in addition to this Node.js SDK: 7 | 8 | * [Java SDK documentation](https://hyperledger.github.io/fabric-chaincode-java/) 9 | * [Go SDK documentation](https://godoc.org/github.com/hyperledger/fabric-chaincode-go) 10 | 11 | ## Documentation 12 | 13 | Detailed explanation on the concepts and programming model for smart contracts can be found in the [Smart Contracts and Chaincode section in the Hyperledger Fabric documentation](https://hyperledger-fabric.readthedocs.io/en/latest/smartcontract/smartcontract.html). 14 | 15 | API documentation is available for each release: 16 | 17 | {% include apidocs.html %} 18 | 19 | ## Download 20 | 21 | The following packages are available from the npm Registry: 22 | 23 | - [fabric-contract-api](https://www.npmjs.com/package/fabric-contract-api) 24 | - [fabric-shim](https://www.npmjs.com/package/fabric-shim) 25 | - [fabric-shim-api](https://www.npmjs.com/package/fabric-shim-api) 26 | 27 | Check the [release notes](https://github.com/hyperledger/fabric-chaincode-node/releases) for the changes in each version. 28 | 29 | ## Samples 30 | 31 | Node.js chaincode samples for commercial paper and fabcar can be found in the [fabric-samples repository](https://github.com/hyperledger/fabric-samples) 32 | -------------------------------------------------------------------------------- /docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fabric-shim-docs", 3 | "version": "2.5.9", 4 | "description": "", 5 | "private": true, 6 | "scripts": { 7 | "build": "npm run docs", 8 | "docs": "rimraf ./gen && jsdoc -c ./_jsdoc.json" 9 | }, 10 | "dependencies": { 11 | "fabric-ledger": "2.5.9" 12 | }, 13 | "devDependencies": { 14 | "ink-docstrap": "^1.3.2", 15 | "jsdoc": "^3.6.3", 16 | "rimraf": "^3.0.2" 17 | }, 18 | "keywords": [], 19 | "author": "", 20 | "license": "Apache-2.0" 21 | } 22 | -------------------------------------------------------------------------------- /libraries/fabric-ledger/.eslintignore: -------------------------------------------------------------------------------- 1 | # don't ever lint node_modules 2 | node_modules 3 | 4 | # don't lint build output (make sure it's set to your correct build folder name) 5 | dist 6 | 7 | # don't lint nyc coverage output 8 | coverage 9 | -------------------------------------------------------------------------------- /libraries/fabric-ledger/.eslintrc.js: -------------------------------------------------------------------------------- 1 | // This is a workaround for https://github.com/eslint/eslint/issues/3458 2 | require("@rushstack/eslint-config/patch-eslint6"); 3 | 4 | module.exports = { 5 | extends: [ "@rushstack/eslint-config" ], 6 | parserOptions: { tsconfigRootDir: __dirname } 7 | }; 8 | -------------------------------------------------------------------------------- /libraries/fabric-ledger/.npmignore: -------------------------------------------------------------------------------- 1 | # Copyright IBM Corp. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | # OS generated files # 5 | .DS_Store 6 | 7 | # Node Files # 8 | /node_modules 9 | npm-debug.log 10 | 11 | # Coverage # 12 | /coverage 13 | 14 | # Test Files # 15 | /test 16 | 17 | # Source files # 18 | /src 19 | -------------------------------------------------------------------------------- /libraries/fabric-ledger/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fabric-ledger", 3 | "version": "2.5.9", 4 | "tag": "latest", 5 | "description": "A node.js implementation of Hyperledger Fabric ledger api, to allow access to ledger data from smart contracts", 6 | "main": "lib/index.js", 7 | "types": "lib/index.d.ts", 8 | "scripts": { 9 | "build": "npm run test", 10 | "compile": "tsc", 11 | "precompile": "npm run eslint", 12 | "pretest": "npm run compile", 13 | "test": "nyc mocha --require ts-node/register --recursive 'test/unit/**/*.spec.ts' --reporter spec-junit-splitter-mocha-reporter", 14 | "eslint": "eslint src --ext .ts" 15 | }, 16 | "repository": { 17 | "type": "git", 18 | "url": "https://github.com/hyperledger/fabric-chaincode-node" 19 | }, 20 | "keywords": [ 21 | "fabric-ledger", 22 | "Hyperledger Fabric", 23 | "Fabric Ledger" 24 | ], 25 | "engines": { 26 | "node": ">=18" 27 | }, 28 | "license": "Apache-2.0", 29 | "nyc": { 30 | "exclude": [ 31 | "coverage/**", 32 | "test/**", 33 | ".eslintrc.js" 34 | ], 35 | "extension": [ 36 | ".ts" 37 | ], 38 | "reporter": [ 39 | "text-summary", 40 | "cobertura", 41 | "html" 42 | ], 43 | "all": true, 44 | "check-coverage": true, 45 | "statements": 100, 46 | "branches": 100, 47 | "functions": 100, 48 | "lines": 100 49 | }, 50 | "dependencies": { 51 | "fabric-contract-api": "2.5.9", 52 | "winston": "^3.7.2" 53 | }, 54 | "devDependencies": { 55 | "@types/chai": "^4.2.22", 56 | "@types/chai-as-promised": "^7.1.4", 57 | "@types/mocha": "^9.0.0", 58 | "@rushstack/eslint-config": "^0.5.1", 59 | "chai": "^4.3.4", 60 | "chai-as-promised": "^7.1.1", 61 | "cpx": "^1.5.0", 62 | "eslint": "^6.6.0", 63 | "mocha": "9.1.3", 64 | "mockery": "^2.1.0", 65 | "nyc": "15.1.0", 66 | "rewire": "6.0.0", 67 | "rimraf": "^3.0.2", 68 | "sinon": "13.0.1", 69 | "ts-node": "^10.2.1", 70 | "ts-mockito": "^2.6.1", 71 | "typescript": "4.4.4", 72 | "spec-junit-splitter-mocha-reporter": "1.0.1" 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /libraries/fabric-ledger/src/Collection.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2020 IBM All Rights Reserved. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | export enum CollectionNames { 8 | WORLD = 'worldstate' 9 | } 10 | 11 | /** 12 | * Collection placeholder. 13 | * 14 | * @memberof module:fabric-ledger 15 | */ 16 | export class Collection { } 17 | -------------------------------------------------------------------------------- /libraries/fabric-ledger/src/Ledger.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2020 IBM All Rights Reserved. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | import {Collection, CollectionNames} from './Collection'; 8 | 9 | import {Context} from 'fabric-contract-api'; 10 | 11 | /** 12 | * Entrypoint for the Ledger API. 13 | * 14 | * @memberof module:fabric-ledger 15 | */ 16 | export class Ledger { 17 | 18 | private readonly _ctx: Context; 19 | 20 | private constructor (ctx: Context) { 21 | this._ctx = ctx; 22 | } 23 | 24 | /** 25 | * Get a Ledger instance which represents the current ledger state. 26 | * 27 | * @param {Context} ctx The transaction context 28 | * @returns {Promise} A new Ledger instance 29 | */ 30 | public static async getLedger (ctx: Context): Promise { 31 | return new Ledger(ctx); 32 | } 33 | 34 | /** 35 | * Get a Collection instance for the named collection. 36 | * 37 | * @param {string} collectionName The name of the collection 38 | * @returns {Promise} A new Collection instance 39 | */ 40 | public async getCollection (collectionName: string): Promise { 41 | return new Collection(); 42 | } 43 | 44 | /** 45 | * Get a Collection instance representing the default world state. 46 | * 47 | * @returns {Promise} A new Collection instance 48 | */ 49 | public async getDefaultCollection (): Promise { 50 | return this.getCollection(CollectionNames.WORLD); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /libraries/fabric-ledger/src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2020 IBM All Rights Reserved. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | export {Collection} from './Collection'; 8 | export {Ledger} from './Ledger'; 9 | -------------------------------------------------------------------------------- /libraries/fabric-ledger/test/unit/Ledger.spec.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 IBM All Rights Reserved. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | import {Context} from 'fabric-contract-api'; 8 | import {mock} from 'ts-mockito'; 9 | 10 | import {Collection} from '../../src/Collection'; 11 | import {Ledger} from '../../src/Ledger'; 12 | 13 | import chai = require('chai'); 14 | import chaiAsPromised = require('chai-as-promised'); 15 | chai.use(chaiAsPromised); 16 | const expect = chai.expect; 17 | 18 | 19 | describe('Ledger', () => { 20 | 21 | describe('getLedger()', () => { 22 | it('should return a Ledger instance', async () => { 23 | const ctxMock: Context = mock(Context); 24 | const ledger = await Ledger.getLedger(ctxMock); 25 | expect(ledger).to.exist; 26 | expect(ledger).to.be.instanceOf(Ledger); 27 | }); 28 | 29 | it('should always return a new instance', async () => { 30 | const ctxMock: Context = mock(Context); 31 | const ledger1 = await Ledger.getLedger(ctxMock); 32 | const ledger2 = await Ledger.getLedger(ctxMock); 33 | expect(ledger1).to.not.equal(ledger2); 34 | }); 35 | }); 36 | 37 | describe('getCollection()', () => { 38 | it('should return a Collection instance', async () => { 39 | const ctxMock: Context = mock(Context); 40 | const ledger = await Ledger.getLedger(ctxMock); 41 | const collection = await ledger.getCollection('mycollection'); 42 | expect(collection).to.exist; 43 | expect(collection).to.be.instanceOf(Collection); 44 | }); 45 | 46 | it('should always return a new instance', async () => { 47 | const ctxMock: Context = mock(Context); 48 | const ledger = await Ledger.getLedger(ctxMock); 49 | const collection1 = await ledger.getCollection('mycollection'); 50 | const collection2 = await ledger.getCollection('mycollection'); 51 | expect(collection1).to.not.equal(collection2); 52 | }); 53 | }); 54 | 55 | describe('getDefaultCollection()', () => { 56 | it('should return a Collection instance', async () => { 57 | const ctxMock: Context = mock(Context); 58 | const ledger = await Ledger.getLedger(ctxMock); 59 | const collection = await ledger.getDefaultCollection(); 60 | expect(collection).to.exist; 61 | expect(collection).to.be.instanceOf(Collection); 62 | }); 63 | 64 | it('should always return a new instance', async () => { 65 | const ctxMock: Context = mock(Context); 66 | const ledger = await Ledger.getLedger(ctxMock); 67 | const collection1 = await ledger.getDefaultCollection(); 68 | const collection2 = await ledger.getDefaultCollection(); 69 | expect(collection1).to.not.equal(collection2); 70 | }); 71 | }); 72 | }); 73 | -------------------------------------------------------------------------------- /libraries/fabric-ledger/tsconfig.json: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 IBM All Rights Reserved. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | { 7 | "compilerOptions": { 8 | "alwaysStrict": true, 9 | "module": "commonjs", 10 | "declaration": true, 11 | "outDir": "lib", 12 | "rootDir": "src", 13 | "sourceMap": true, 14 | "strict": true, 15 | "target": "es2017", 16 | "lib": [ 17 | "esnext", 18 | "esnext.asynciterable" 19 | ] 20 | }, 21 | "include": [ 22 | "src/**/*" 23 | ], 24 | "exclude": [ 25 | "node_modules/**/*" 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /libraries/fabric-shim/.npmignore: -------------------------------------------------------------------------------- 1 | test 2 | fabric-shim*.tgz -------------------------------------------------------------------------------- /libraries/fabric-shim/README.md: -------------------------------------------------------------------------------- 1 | [![NPM](https://nodei.co/npm/fabric-shim.svg?downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/fabric-contract-api/) 2 | 3 | 4 | 5 | [![Version](https://badge.fury.io/js/fabric-shim.svg)](http://badge.fury.io/js/fabric-shim) 6 | 7 | 8 | The `fabric-shim` provides the *chaincode interface*, a lower level API for implementing "Smart Contracts". To confirm that this is the same as the `fabric-shim` in previous versions of Hyperledger Fabric. 9 | 10 | Detailed explanation on the concept and programming model can be found here: [https://hyperledger-fabric.readthedocs.io/en/latest/smartcontract/smartcontract.html](https://hyperledger-fabric.readthedocs.io/en/latest/smartcontract/smartcontract.html). 11 | 12 | 13 | ## Chaincode Interface 14 | 15 | ### Installation 16 | ```sh 17 | npm install --save fabric-shim 18 | ``` 19 | 20 | ### Usage 21 | The [chaincode interface](https://hyperledger.github.io/fabric-chaincode-node/main/api/fabric-shim.ChaincodeInterface.html) contains two methods to be implemented: 22 | ```javascript 23 | const shim = require('fabric-shim'); 24 | 25 | const Chaincode = class { 26 | async Init(stub) { 27 | // use the instantiate input arguments to decide initial chaincode state values 28 | 29 | // save the initial states 30 | await stub.putState(key, Buffer.from(aStringValue)); 31 | 32 | return shim.success(Buffer.from('Initialized Successfully!')); 33 | } 34 | 35 | async Invoke(stub) { 36 | // use the invoke input arguments to decide intended changes 37 | 38 | // retrieve existing chaincode states 39 | let oldValue = await stub.getState(key); 40 | 41 | // calculate new state values and saves them 42 | let newValue = oldValue + delta; 43 | await stub.putState(key, Buffer.from(newValue)); 44 | 45 | return shim.success(Buffer.from(newValue.toString())); 46 | } 47 | }; 48 | ``` 49 | 50 | Start the chaincode process and listen for incoming endorsement requests: 51 | ```javascript 52 | shim.start(new Chaincode()); 53 | ``` 54 | 55 | ### API Reference 56 | Visit [API Reference](https://hyperledger.github.io/fabric-chaincode-node/main/api/) and click on "Classes" link in the navigation bar on the top to view the list of class APIs. 57 | 58 | ## Support 59 | Tested with node.js 8.9.0 (LTS). 60 | 61 | ## License 62 | 63 | This package is distributed under the 64 | [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0), 65 | see LICENSE.txt for more information. 66 | -------------------------------------------------------------------------------- /libraries/fabric-shim/cli.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | /* 3 | * Copyright IBM Corp. All Rights Reserved. 4 | * 5 | * SPDX-License-Identifier: Apache-2.0 6 | */ 7 | 8 | const version = 'v' + require('./package.json').version; 9 | const Logger = require('./lib/logger'); 10 | 11 | const logger = Logger.getLogger('fabric-shim/cli'); 12 | 13 | 14 | const main = async () => { 15 | const results = await require('yargs') 16 | .parserConfiguration({ 'dot-notation': false }) 17 | .commandDir('./lib/cmds') 18 | .demandCommand() 19 | .help() 20 | .wrap(null) 21 | .alias('v', 'version') 22 | .version(version) 23 | .describe('v', 'show version information') 24 | .env('CORE') 25 | .argv; 26 | 27 | logger.info("Bootstrap process completed") 28 | } 29 | 30 | main().catch( (e)=> { 31 | console.error("Major failure to start fabic-chaincode-node"); 32 | console.error(e); 33 | process.exitCode = 1; 34 | }); 35 | -------------------------------------------------------------------------------- /libraries/fabric-shim/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | # Copyright IBM Corp. All Rights Reserved. 3 | # 4 | # SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | module.exports = require('./lib/chaincode.js'); 8 | -------------------------------------------------------------------------------- /libraries/fabric-shim/lib/cmds/metadata.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed under the Apache License, Version 2.0 (the "License"); 3 | * you may not use this file except in compliance with the License. 4 | /* 5 | # Copyright IBM Corp. All Rights Reserved. 6 | # 7 | # SPDX-License-Identifier: Apache-2.0 8 | */ 9 | 10 | 'use strict'; 11 | 12 | exports.command = 'metadata '; 13 | exports.desc = 'Command for handling metadata'; 14 | exports.builder = function (yargs) { 15 | // apply commands in subdirectories, throws an error if an incorrect command is entered 16 | return yargs.demandCommand(1, 'Incorrect command. Please see the list of commands above.') 17 | .commandDir('metadata'); 18 | }; 19 | exports.handler = async (argv) => {}; 20 | 21 | module.exports.Generate = require('./metadata/lib/generate'); 22 | 23 | -------------------------------------------------------------------------------- /libraries/fabric-shim/lib/cmds/metadata/generateCommand.js: -------------------------------------------------------------------------------- 1 | /* 2 | # Copyright IBM Corp. All Rights Reserved. 3 | # 4 | # SPDX-License-Identifier: Apache-2.0 5 | */ 6 | const Generate = require ('./lib/generate.js'); 7 | 8 | 'use strict'; 9 | 10 | module.exports.command = 'generate [options]'; 11 | module.exports.desc = 'Generate a file containing the metadata from the deployed contract'; 12 | module.exports.builder = (yargs) => { 13 | yargs.options({ 14 | 'file': {alias: 'f', required: false, describe: 'The file name/path to save the generated metadata file, if no file is specified, it will print to stdout', type: 'string'}, 15 | 'module-path': {alias: 'p', required: false, describe: 'The path to the directory of your smart contract project which contains your chaincode, default is your current working directory', type: 'string', default: process.cwd()} 16 | }); 17 | yargs.usage('fabric-chaincode-node metadata generate --file "fileName"'); 18 | 19 | return yargs; 20 | }; 21 | 22 | module.exports.handler = async (argv) => { 23 | await Generate.handler(argv); 24 | }; 25 | -------------------------------------------------------------------------------- /libraries/fabric-shim/lib/cmds/metadata/lib/generate.js: -------------------------------------------------------------------------------- 1 | /* 2 | # Copyright IBM Corp. All Rights Reserved. 3 | # 4 | # SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 'use strict'; 7 | const path = require('node:path'); 8 | const {promises: fs} = require('node:fs'); 9 | const ChaincodeFromContract = require('../../../contract-spi/chaincodefromcontract.js'); 10 | const Bootstrap = require('../../../contract-spi/bootstrap.js'); 11 | const Logger = require('../../../logger'); 12 | const logger = Logger.getLogger('../../../cmds/metadata/lib/generate'); 13 | 14 | /** 15 | * fabric-chaincode-node "metadata generate" command 16 | * @private 17 | */ 18 | class Generate { 19 | /** 20 | * This is the main entry point for starting the user's chaincode 21 | * @ignore 22 | */ 23 | static async handler(opts) { 24 | // load up the meta data that the user may have specified 25 | // this will need to passed in and rationalized with the code as implemented 26 | const fileMetadata = await Bootstrap.getMetadata(opts['module-path']); 27 | const {contracts, serializers, title, version} = Bootstrap.getInfoFromContract(opts['module-path']); 28 | const chaincode = new ChaincodeFromContract(contracts, serializers, fileMetadata, title, version); 29 | if (opts.file) { 30 | const fileName = path.extname(opts.file) === '' ? opts.file + '.json' : opts.file; 31 | const filePath = path.resolve(process.cwd(), fileName); 32 | await fs.writeFile(filePath, JSON.stringify(chaincode.metadata, null, 4)); 33 | logger.info(`File containing metadata has been saved to ${filePath}`); 34 | } else { 35 | logger.info(JSON.stringify(chaincode.metadata, null, 4)); 36 | } 37 | } 38 | } 39 | module.exports = Generate; 40 | -------------------------------------------------------------------------------- /libraries/fabric-shim/lib/cmds/startCommand.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright contributors to Hyperledger Fabric. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | 'use strict'; 8 | 9 | const YargsParser = require('yargs-parser'); 10 | 11 | const validOptions = { 12 | 'peer.address': {type: 'string', required: true}, 13 | 'grpc.max_send_message_length': {type: 'number', default: -1}, 14 | 'grpc.max_receive_message_length': {type: 'number', default: -1}, 15 | 'grpc.keepalive_time_ms': {type: 'number', default: 110000}, 16 | 'grpc.http2.min_time_between_pings_ms': {type: 'number', default: 110000}, 17 | 'grpc.keepalive_timeout_ms': {type: 'number', default: 20000}, 18 | 'grpc.http2.max_pings_without_data': {type: 'number', default: 0}, 19 | 'grpc.keepalive_permit_without_calls': {type: 'number', default: 1}, 20 | 'ssl-target-name-override': {type: 'string'}, 21 | 'chaincode-id-name': {type: 'string', required: true}, 22 | 'module-path': {type: 'string', default: process.cwd()} 23 | }; 24 | 25 | module.exports.validOptions = validOptions; 26 | 27 | exports.command = 'start [options]'; 28 | exports.desc = 'Start an empty chaincode'; 29 | exports.builder = (yargs) => { 30 | yargs.options(validOptions); 31 | 32 | yargs.usage('fabric-chaincode-node start --peer.address localhost:7051 --chaincode-id-name mycc'); 33 | 34 | return yargs; 35 | }; 36 | exports.handler = async function (argv) { 37 | const Bootstrap = require('../contract-spi/bootstrap'); 38 | await Bootstrap.bootstrap(); 39 | }; 40 | 41 | exports.getArgs = function (yargs) { 42 | let argv = yargs.argv; 43 | 44 | if (argv.$0 !== 'fabric-chaincode-node') { 45 | 46 | const defaults = {}; 47 | 48 | const required = []; 49 | 50 | for (const key in validOptions) { 51 | if (validOptions[key].hasOwnProperty('default')) { // eslint-disable-line no-prototype-builtins 52 | defaults[key] = validOptions[key].default; 53 | } 54 | 55 | if (validOptions[key].hasOwnProperty('required') && validOptions[key].required) { // eslint-disable-line no-prototype-builtins 56 | required.push(key); 57 | } 58 | } 59 | 60 | argv = YargsParser(process.argv.slice(2), { 61 | default: defaults, 62 | configuration: { 63 | 'dot-notation': false 64 | }, 65 | envPrefix: 'CORE' 66 | }); 67 | 68 | argv['chaincode-id-name'] = argv.chaincodeIdName; 69 | argv['module-path'] = argv.modulePath; 70 | 71 | // eslint-disable-next-line eqeqeq 72 | if (argv.CORE_PEER_ADDRESS != null) { 73 | argv['peer.address'] = argv.CORE_PEER_ADDRESS; 74 | } 75 | 76 | required.forEach((argName) => { 77 | if (!argv.hasOwnProperty(argName) || typeof(argv[argName]) === 'undefined') { // eslint-disable-line no-prototype-builtins 78 | throw new Error('Missing required argument ' + argName); 79 | } 80 | }); 81 | } 82 | 83 | return argv; 84 | }; 85 | -------------------------------------------------------------------------------- /libraries/fabric-shim/lib/contract-spi/systemcontract.js: -------------------------------------------------------------------------------- 1 | /* 2 | # Copyright IBM Corp. All Rights Reserved. 3 | # 4 | # SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 'use strict'; 7 | 8 | const Contract = require('fabric-contract-api').Contract; 9 | 10 | /** 11 | * This is a contract that determines functions that can be invoked to provide general information 12 | * 13 | * @class 14 | * @memberof fabric-contract-api 15 | */ 16 | class SystemContract extends Contract { 17 | 18 | constructor() { 19 | super('org.hyperledger.fabric'); 20 | } 21 | 22 | /** 23 | * 24 | * @param {Object} chaincode 25 | */ 26 | _setMetadata(metadata) { 27 | this.metadata = metadata; 28 | } 29 | 30 | /** 31 | * Gets meta data associated with this Chaincode deployment 32 | */ 33 | async GetMetadata() { 34 | return this.metadata; 35 | } 36 | 37 | } 38 | 39 | module.exports = SystemContract; 40 | -------------------------------------------------------------------------------- /libraries/fabric-shim/lib/utils/utils.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright IBM Corp. All Rights Reserved. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | module.exports.generateLoggingPrefix = (channelId, txId) => { 8 | return `[${channelId}-${shortTxID(txId)}]`; 9 | }; 10 | 11 | function shortTxID (txId) { 12 | return txId.substring(0, 8); 13 | } 14 | -------------------------------------------------------------------------------- /libraries/fabric-shim/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fabric-shim", 3 | "version": "2.5.9", 4 | "tag": "latest", 5 | "description": "A node.js implementation of Hyperledger Fabric chaincode shim, to allow endorsing peers and user-provided chaincodes to communicate with each other", 6 | "main": "index.js", 7 | "bin": { 8 | "fabric-chaincode-node": "cli.js" 9 | }, 10 | "scripts": { 11 | "start": "./startup.sh", 12 | "compile": "tsc --project test/typescript", 13 | "test": "nyc mocha --recursive 'test/unit/**/*.js' --reporter spec-junit-splitter-mocha-reporter", 14 | "update:clean": "rimraf bundle.js bundle.d.ts protos && mkdirp protos", 15 | "update:copy": "cpx \"${GOPATH}/src/github.com/hyperledger/fabric-protos/**/*.proto\" protos --verbose", 16 | "update:pbjs": "pbjs -t static-module -p google-protos -p protos $(find google-protos protos -name \"*.proto\" -type f) -o bundle.js", 17 | "update:pbts": "pbts -o bundle.d.ts bundle.js", 18 | "update": "npm run update:clean && npm run update:copy && npm run update:pbjs && npm run update:pbts", 19 | "lint": "eslint ./lib ./types ./test/typescript/*.ts --ext .js --ext .ts", 20 | "build": "npm run lint & npm test 2>&1" 21 | }, 22 | "repository": { 23 | "type": "git", 24 | "url": "https://github.com/hyperledger/fabric-chaincode-node" 25 | }, 26 | "keywords": [ 27 | "fabric-shim", 28 | "Hyperledger Fabric", 29 | "Fabric Shim" 30 | ], 31 | "engines": { 32 | "node": ">=18" 33 | }, 34 | "types": "./types/index.d.ts", 35 | "license": "Apache-2.0", 36 | "nyc": { 37 | "exclude": [ 38 | "coverage/**", 39 | "test/**", 40 | "gulpfile.js", 41 | "bundle.js" 42 | ], 43 | "reporter": [ 44 | "text-summary", 45 | "cobertura", 46 | "html" 47 | ], 48 | "all": true, 49 | "check-coverage": true, 50 | "statements": 100, 51 | "branches": 100, 52 | "functions": 100, 53 | "lines": 100 54 | }, 55 | "dependencies": { 56 | "@fidm/x509": "^1.2.1", 57 | "@grpc/grpc-js": "^1.11.0", 58 | "@hyperledger/fabric-protos": "^0.2.2", 59 | "@types/node": "^16.11.1", 60 | "ajv": "^6.12.2", 61 | "fabric-contract-api": "2.5.9", 62 | "fabric-shim-api": "2.5.9", 63 | "fast-safe-stringify": "^2.1.1", 64 | "long": "^5.2.3", 65 | "reflect-metadata": "^0.1.13", 66 | "winston": "^3.7.2", 67 | "yargs": "^17.4.0", 68 | "yargs-parser": "^21.0.1" 69 | }, 70 | "devDependencies": { 71 | "chai": "^4.3.4", 72 | "chai-as-promised": "^7.1.1", 73 | "chai-things": "^0.2.0", 74 | "cpx": "^1.5.0", 75 | "eslint": "^6.6.0", 76 | "mocha": "9.1.3", 77 | "mockery": "^2.1.0", 78 | "nyc": "15.1.0", 79 | "rewire": "6.0.0", 80 | "rimraf": "^3.0.2", 81 | "sinon": "13.0.1", 82 | "spec-junit-splitter-mocha-reporter": "1.0.1", 83 | "caniuse-lite": "~1.0.30001325" 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /libraries/fabric-shim/startup.sh: -------------------------------------------------------------------------------- 1 | DIR=$(pwd) 2 | 3 | # MAKE IT GO THROUGH THE ARGS ONE BY ONE AND IF IT IS THE LABEL --module-path THEN GET THE NEXT ARG AND USE THAT AS THE CD OVER THE ENV VAR 4 | GRAB_NEXT=false 5 | for var in "$@"; do 6 | if [ $var = "--module-path" ]; then 7 | GRAB_NEXT=true 8 | elif [ $GRAB_NEXT = true ]; then 9 | CORE_MODULE_PATH="$var" 10 | fi 11 | done 12 | cd $CORE_MODULE_PATH 13 | 14 | if grep -q "fabric-contract-api" package.json; then 15 | cd $DIR 16 | node cli.js start "$@" 17 | else 18 | npm start -- "$@" 19 | fi -------------------------------------------------------------------------------- /libraries/fabric-shim/test/unit/cli.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright IBM Corp. All Rights Reserved. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | /* global describe it beforeEach afterEach */ 8 | 9 | 'use strict'; 10 | 11 | const sinon = require('sinon'); 12 | 13 | const yargs = require('yargs'); 14 | 15 | const {execSync} = require('child_process'); 16 | 17 | describe('fabric-chaincode-node cli', () => { 18 | let sandbox; 19 | 20 | beforeEach(() => { 21 | 22 | sandbox = sinon.createSandbox(); 23 | sandbox.stub(yargs, 'parserConfiguration').returns(yargs); 24 | sandbox.stub(yargs, 'commandDir').returns(yargs); 25 | sandbox.stub(yargs, 'demandCommand').returns(yargs); 26 | 27 | sandbox.stub(yargs, 'help').returns(yargs); 28 | sandbox.stub(yargs, 'wrap').returns(yargs); 29 | sandbox.stub(yargs, 'alias').returns(yargs); 30 | sandbox.stub(yargs, 'version').returns(yargs); 31 | 32 | sandbox.stub(process, 'exit'); 33 | execSync('cp ./cli.js ./cli2.js', () => {}); 34 | execSync('sed 1d ./cli2.js > ./cli.js', () => {}); 35 | }); 36 | 37 | afterEach(() => { 38 | sandbox.restore(); 39 | delete require.cache[require.resolve('../../cli.js')]; 40 | execSync('rm ./cli.js', () => {}); 41 | execSync('mv ./cli2.js ./cli.js', () => {}); 42 | }); 43 | 44 | describe('Main test', () => { 45 | it('should setup yargs correctly', () => { 46 | sandbox.stub(yargs, 'describe').returns(yargs); 47 | sandbox.stub(yargs, 'env').returns(yargs); 48 | 49 | require('../../cli.js'); 50 | 51 | sinon.assert.calledOnce(yargs.commandDir); 52 | sinon.assert.calledWith(yargs.commandDir, './lib/cmds'); 53 | sinon.assert.calledOnce(yargs.demandCommand); 54 | sinon.assert.calledOnce(yargs.help); 55 | sinon.assert.calledOnce(yargs.wrap); 56 | sinon.assert.calledOnce(yargs.alias); 57 | sinon.assert.calledOnce(yargs.version); 58 | sinon.assert.calledOnce(yargs.describe); 59 | sinon.assert.calledOnce(yargs.env); 60 | sinon.assert.calledWith(yargs.env, 'CORE'); 61 | }); 62 | 63 | it('should handle resolved promise correctly', () => { 64 | sandbox.stub(yargs, 'describe').returns(yargs); 65 | sandbox.stub(yargs, 'env').resolves(""); 66 | require('../../cli.js'); 67 | }); 68 | 69 | it('should handle rejected promise correctly', () => { 70 | sandbox.stub(yargs, 'describe').returns(yargs); 71 | sandbox.stub(yargs, 'env').throws("Test Failure") 72 | 73 | require('../../cli.js'); 74 | }); 75 | }); 76 | }); 77 | -------------------------------------------------------------------------------- /libraries/fabric-shim/test/unit/cmds/metadata.js: -------------------------------------------------------------------------------- 1 | /* 2 | # Copyright IBM Corp. All Rights Reserved. 3 | # 4 | # SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | 'use strict'; 8 | 9 | const MetadataCommand = require('../../../lib/cmds/metadata'); 10 | const yargs = require('yargs'); 11 | require('chai').should(); 12 | const chai = require('chai'); 13 | const sinon = require('sinon'); 14 | chai.should(); 15 | chai.use(require('chai-things')); 16 | chai.use(require('chai-as-promised')); 17 | const mockery = require('mockery'); 18 | 19 | describe('fabric-chaincode-node metadata cmd launcher', function () { 20 | let sandbox; 21 | 22 | beforeEach(() => { 23 | 24 | sandbox = sinon.createSandbox(); 25 | sandbox.stub(yargs, 'usage').returns(yargs); 26 | sandbox.stub(yargs, 'options').returns(yargs); 27 | sandbox.stub(yargs, 'requiresArg').returns(yargs); 28 | sandbox.stub(yargs, 'demandCommand').returns(yargs); 29 | sandbox.stub(yargs, 'commandDir'); 30 | }); 31 | 32 | afterEach(() => { 33 | mockery.deregisterAll(); 34 | sandbox.restore(); 35 | }); 36 | 37 | describe('cmd method tests', () => { 38 | 39 | it ('should have the correct command and description', function () { 40 | MetadataCommand.command.should.include('metadata'); 41 | MetadataCommand.desc.should.include('metadata'); 42 | }); 43 | 44 | it ('should call yargs correctly', () => { 45 | MetadataCommand.builder(yargs); 46 | sinon.assert.calledOnce(yargs.commandDir); 47 | sinon.assert.calledWith(yargs.commandDir, 'metadata'); 48 | MetadataCommand.handler(); 49 | }); 50 | 51 | }); 52 | 53 | 54 | }); 55 | -------------------------------------------------------------------------------- /libraries/fabric-shim/test/unit/cmds/metadata/generateCommand.js: -------------------------------------------------------------------------------- 1 | /* 2 | # Copyright IBM Corp. All Rights Reserved. 3 | # 4 | # SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | /* eslint-disable no-console */ 8 | 'use strict'; 9 | 10 | const yargs = require('yargs'); 11 | require('chai').should(); 12 | const chai = require('chai'); 13 | const sinon = require('sinon'); 14 | chai.should(); 15 | chai.use(require('chai-as-promised')); 16 | chai.use(require('chai-things')); 17 | 18 | const rewire = require('rewire'); 19 | // class under test 20 | const GenerateCommand = rewire('../../../../lib/cmds/metadata/generateCommand.js'); 21 | 22 | 23 | describe('GenerateCommand', () => { 24 | 25 | let sandbox; 26 | 27 | beforeEach('Sandbox creation', () => { 28 | sandbox = sinon.createSandbox(); 29 | }); 30 | 31 | afterEach('Sandbox restoration', () => { 32 | sandbox.restore(); 33 | }); 34 | 35 | describe('#builder function', () => { 36 | 37 | beforeEach(() => { 38 | sandbox.stub(yargs, 'usage').returns(yargs); 39 | sandbox.stub(yargs, 'options').returns(yargs); 40 | sandbox.stub(yargs, 'strict').returns(yargs); 41 | sandbox.stub(yargs, 'requiresArg').returns(yargs); 42 | sandbox.stub(yargs, 'demandCommand').returns(yargs); 43 | sandbox.stub(yargs, 'commandDir'); 44 | }); 45 | 46 | it ('should have the correct command and description', function () { 47 | GenerateCommand.command.should.include('generate'); 48 | GenerateCommand.desc.should.include('Generate'); 49 | }); 50 | 51 | it ('should call yargs correctly', () => { 52 | GenerateCommand.builder(yargs); 53 | sinon.assert.calledOnce(yargs.options); 54 | sinon.assert.calledWith(yargs.options, { 55 | 'file': {alias: 'f', required: false, describe: 'The file name/path to save the generated metadata file, if no file is specified, it will print to stdout', type: 'string'}, 56 | 'module-path': {alias: 'p', required: false, describe: 'The path to the directory of your smart contract project which contains your chaincode, default is your current working directory', type: 'string', default: process.cwd()} 57 | }); 58 | sinon.assert.calledOnce(yargs.usage); 59 | sinon.assert.calledWith(yargs.usage, 'fabric-chaincode-node metadata generate --file "fileName"'); 60 | }); 61 | }); 62 | 63 | describe('#handler function', () => { 64 | let handlerStub; 65 | class FakeGenerate { 66 | static handler() { 67 | } 68 | } 69 | beforeEach(() => { 70 | handlerStub = sandbox.stub(FakeGenerate, 'handler'); 71 | GenerateCommand.__set__('Generate', FakeGenerate); 72 | }); 73 | 74 | afterEach(() => { 75 | sandbox.restore(); 76 | }); 77 | 78 | it ('should call the handler function correctly', () => { 79 | const argv = {random: 'something'}; 80 | GenerateCommand.handler(argv); 81 | sinon.assert.calledOnce(handlerStub); 82 | sinon.assert.calledWithExactly(handlerStub, argv); 83 | }); 84 | }); 85 | }); 86 | -------------------------------------------------------------------------------- /libraries/fabric-shim/test/unit/contract-spi/systemcontract.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright IBM Corp. All Rights Reserved. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | /* global describe it beforeEach afterEach */ 8 | 'use strict'; 9 | 10 | // test specific libraries 11 | const chai = require('chai'); 12 | chai.should(); 13 | const expect = chai.expect; 14 | const rewire = require('rewire'); 15 | chai.use(require('chai-as-promised')); 16 | chai.use(require('chai-things')); 17 | const sinon = require('sinon'); 18 | 19 | const path = require('path'); 20 | 21 | // class under test 22 | const pathToRoot = '../../../..'; 23 | const SystemContract = rewire(path.join(pathToRoot, 'fabric-shim/lib/contract-spi/systemcontract')); 24 | 25 | describe('SystemContract', () => { 26 | 27 | let sandbox; 28 | 29 | beforeEach('Sandbox creation', () => { 30 | sandbox = sinon.createSandbox(); 31 | 32 | }); 33 | 34 | afterEach('Sandbox restoration', () => { 35 | sandbox.restore(); 36 | }); 37 | 38 | describe('#constructor', () => { 39 | 40 | it ('should create correctly', () => { 41 | const meta = new SystemContract(); 42 | expect(meta.getName()).to.equal('org.hyperledger.fabric'); 43 | }); 44 | 45 | }); 46 | 47 | describe('#GetMetadata', () => { 48 | 49 | it ('should get the buffer', async () => { 50 | const meta = new SystemContract(); 51 | meta._setMetadata({wibble:'good'}); 52 | const md = await meta.GetMetadata(); 53 | expect(md).to.deep.equal({wibble:'good'}); 54 | 55 | }); 56 | 57 | 58 | }); 59 | 60 | 61 | }); 62 | -------------------------------------------------------------------------------- /libraries/fabric-shim/test/unit/module.js: -------------------------------------------------------------------------------- 1 | /* 2 | # Copyright IBM Corp. All Rights Reserved. 3 | # 4 | # SPDX-License-Identifier: Apache-2.0 5 | */ 6 | /* global describe it */ 7 | 8 | 'use strict'; 9 | 10 | const chai = require('chai'); 11 | const expect = chai.expect; 12 | 13 | const theModule = require('../../../fabric-shim'); 14 | 15 | describe('Exports', () => { 16 | it ('should export the start function', () => { 17 | expect(typeof theModule.start).to.deep.equal('function'); 18 | }); 19 | 20 | it ('should export the success function', () => { 21 | expect(typeof theModule.success).to.deep.equal('function'); 22 | }); 23 | 24 | it ('should export the error function', () => { 25 | expect(typeof theModule.error).to.deep.equal('function'); 26 | }); 27 | 28 | it ('should export the Shim class', () => { 29 | expect(typeof theModule.Shim).to.deep.equal('function'); 30 | }); 31 | 32 | it ('should export the Stub class', () => { 33 | expect(typeof theModule.Stub).to.deep.equal('function'); 34 | }); 35 | 36 | it ('should export the ChaincodeInterface class', () => { 37 | expect(typeof theModule.ChaincodeInterface).to.deep.equal('function'); 38 | }); 39 | 40 | it ('should export the ClientIdentity class', () => { 41 | expect(typeof theModule.ClientIdentity).to.deep.equal('function'); 42 | }); 43 | 44 | it ('should export the Iterators.HistoryQueryIterator class', () => { 45 | expect(typeof theModule.Iterators.HistoryQueryIterator).to.deep.equal('function'); 46 | }); 47 | 48 | it ('should export the HistoryQueryIterator class', () => { 49 | expect(typeof theModule.HistoryQueryIterator).to.deep.equal('function'); 50 | }); 51 | 52 | it ('should export the Iterators.StateQueryIterator class', () => { 53 | expect(typeof theModule.Iterators.StateQueryIterator).to.deep.equal('function'); 54 | }); 55 | 56 | it ('should export the StateQueryIterator class', () => { 57 | expect(typeof theModule.StateQueryIterator).to.deep.equal('function'); 58 | }); 59 | }); 60 | -------------------------------------------------------------------------------- /libraries/fabric-shim/test/unit/test-ca.base64: -------------------------------------------------------------------------------- 1 | LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJrekNCOVFJSkFKMFo4akZpUFBpOU1Bb0dD 2 | Q3FHU000OUJBTUNNQTR4RERBS0JnTlZCQU1NQTNSc2N6QWUKRncweU1EQTFNRGN4TmpNME1qRmFG 3 | dzB6TURBMU1EVXhOak0wTWpGYU1BNHhEREFLQmdOVkJBTU1BM1JzY3pDQgptekFRQmdjcWhrak9Q 4 | UUlCQmdVcmdRUUFJd09CaGdBRUFDb1VTM3pnOVFqNUNnUWVOQ1krOXNQTTJZV1lIVVVRClNCRS9v 5 | WXBncldWOEU4VHF0V2tXY2h3WFA0T29aQXE3Yk1KMmJOUUU1U3E2SVkrYlpyWXBPS2pmQVNweVM0 6 | cVIKNHhKZkN1bjdCSVpBallIdlZxbWN1RjhhSmFmaDhGOTNHQmprSUxIZ0hUcnRMTHNBcTZzQnB6 7 | RXVWSmxzdWYxaApMaEtuQ0FxdmZFdEMxSUJWTUFvR0NDcUdTTTQ5QkFNQ0E0R01BRENCaUFKQ0FO 8 | R1VwNDU5UDNhTWh0VFpkWEZxCm1jOFFWTTdySFIzWmxpOWttV3NHVmRKdmJVYnVIY1g2KzBBVTFT 9 | OFIyRGhQQThvZUJ1UVQ3ZGJvdllmd2V1VmIKUWZSM0FrSUFwYUtlc2lOOUxOeTlhclNCR1hURktK 10 | cXVCVDYzdjRiaTRmeUNOaGhkQzN3eEtldHNKMURDcElkcgpCbDhabmNKeFVNakNyZDdCTmxrQk5Q 11 | N2pDR2RLcFBrPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0t 12 | -------------------------------------------------------------------------------- /libraries/fabric-shim/test/unit/test-ca.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIBkzCB9QIJAJ0Z8jFiPPi9MAoGCCqGSM49BAMCMA4xDDAKBgNVBAMMA3RsczAe 3 | Fw0yMDA1MDcxNjM0MjFaFw0zMDA1MDUxNjM0MjFaMA4xDDAKBgNVBAMMA3RsczCB 4 | mzAQBgcqhkjOPQIBBgUrgQQAIwOBhgAEACoUS3zg9Qj5CgQeNCY+9sPM2YWYHUUQ 5 | SBE/oYpgrWV8E8TqtWkWchwXP4OoZAq7bMJ2bNQE5Sq6IY+bZrYpOKjfASpyS4qR 6 | 4xJfCun7BIZAjYHvVqmcuF8aJafh8F93GBjkILHgHTrtLLsAq6sBpzEuVJlsuf1h 7 | LhKnCAqvfEtC1IBVMAoGCCqGSM49BAMCA4GMADCBiAJCANGUp459P3aMhtTZdXFq 8 | mc8QVM7rHR3Zli9kmWsGVdJvbUbuHcX6+0AU1S8R2DhPA8oeBuQT7dbovYfweuVb 9 | QfR3AkIApaKesiN9LNy9arSBGXTFKJquBT63v4bi4fyCNhhdC3wxKetsJ1DCpIdr 10 | Bl8ZncJxUMjCrd7BNlkBNP7jCGdKpPk= 11 | -----END CERTIFICATE----- -------------------------------------------------------------------------------- /libraries/fabric-shim/test/unit/test-cert.base64: -------------------------------------------------------------------------------- 1 | LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJrakNCOVFJSkFPZTRqL3NqV3ltRE1Bb0dDQ3FHU000OUJBTUNNQTR4RERBS0JnTlZCQU1NQTNSc2N6QWUKRncweU1EQTFNRGN4TmpNek5UUmFGdzB6TURBMU1EVXhOak16TlRSYU1BNHhEREFLQmdOVkJBTU1BM1JzY3pDQgptekFRQmdjcWhrak9QUUlCQmdVcmdRUUFJd09CaGdBRUFPcllIem5BZmVXZ3pVM3dVZ1Q1Ylk5NkUvT2ZMb3p4CitlUUFIL2Y5cDV3TUxuUzliMTJZczBHWitTNEdjSEYva1FBNlpoMVZBcFdKYnJ6MjFYVWhSbU5QQVRibDd3K2cKbytyazJ2cVZ5Y0E3dU1tUERlL0J2MVlldEh1WXZCd05vajVLVm9vVnVpUnJPOUlkU2N3ZUxkai9WOXoyQUkvQgpmUC9iN01aYWFwbUdUQjVFTUFvR0NDcUdTTTQ5QkFNQ0E0R0xBRENCaHdKQmVZQ1ZPclFWR3dmb1Q3OWRqRWpqCm1YVkVIL3hWcGk4b1ZhWkxVRm0yN2RldkYwb1ViZHowZSt2MzhZdkx6aERnWWh2MUtMQzhnYWxxaFdleTI2MmkKVVcwQ1FnRWRrUHFOYUZlbjF0WEQ5RWJoTjhSdVRyQWE3RGphNzZ3SWVMZUZSdFloZ0hCZlMvZmM0VWR3N1hWbgpQcG9nQ0xhM0ZMNkNDSUZIQWEyTU9kc3VMeld4V2c9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0t -------------------------------------------------------------------------------- /libraries/fabric-shim/test/unit/test-cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIBkjCB9QIJAOe4j/sjWymDMAoGCCqGSM49BAMCMA4xDDAKBgNVBAMMA3RsczAe 3 | Fw0yMDA1MDcxNjMzNTRaFw0zMDA1MDUxNjMzNTRaMA4xDDAKBgNVBAMMA3RsczCB 4 | mzAQBgcqhkjOPQIBBgUrgQQAIwOBhgAEAOrYHznAfeWgzU3wUgT5bY96E/OfLozx 5 | +eQAH/f9p5wMLnS9b12Ys0GZ+S4GcHF/kQA6Zh1VApWJbrz21XUhRmNPATbl7w+g 6 | o+rk2vqVycA7uMmPDe/Bv1YetHuYvBwNoj5KVooVuiRrO9IdScweLdj/V9z2AI/B 7 | fP/b7MZaapmGTB5EMAoGCCqGSM49BAMCA4GLADCBhwJBeYCVOrQVGwfoT79djEjj 8 | mXVEH/xVpi8oVaZLUFm27devF0oUbdz0e+v38YvLzhDgYhv1KLC8galqhWey262i 9 | UW0CQgEdkPqNaFen1tXD9EbhN8RuTrAa7Dja76wIeLeFRtYhgHBfS/fc4Udw7XVn 10 | PpogCLa3FL6CCIFHAa2MOdsuLzWxWg== 11 | -----END CERTIFICATE----- -------------------------------------------------------------------------------- /libraries/fabric-shim/test/unit/test-key.base64: -------------------------------------------------------------------------------- 1 | LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1JSGNBZ0VCQkVJQmZXcmJQam9pdHcwd3AwUjA3dHdKeDhxaDZGenhpVFArekpFNEZHZ3EvTXh6Sy9kdUhIN2YKRjNzOWtmM1dkcWxYNlkwTnM2K3VRR2hmK2laODZtd01zaU9nQndZRks0RUVBQ09oZ1lrRGdZWUFCQURxMkI4NQp3SDNsb00xTjhGSUUrVzJQZWhQem55Nk04Zm5rQUIvMy9hZWNEQzUwdlc5ZG1MTkJtZmt1Qm5CeGY1RUFPbVlkClZRS1ZpVzY4OXRWMUlVWmpUd0UyNWU4UG9LUHE1TnI2bGNuQU83akpqdzN2d2I5V0hyUjdtTHdjRGFJK1NsYUsKRmJva2F6dlNIVW5NSGkzWS8xZmM5Z0NQd1h6LzIrekdXbXFaaGt3ZVJBPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQ== -------------------------------------------------------------------------------- /libraries/fabric-shim/test/unit/test-key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN EC PRIVATE KEY----- 2 | MIHcAgEBBEIBfWrbPjoitw0wp0R07twJx8qh6FzxiTP+zJE4FGgq/MxzK/duHH7f 3 | F3s9kf3WdqlX6Y0Ns6+uQGhf+iZ86mwMsiOgBwYFK4EEACOhgYkDgYYABADq2B85 4 | wH3loM1N8FIE+W2PehPzny6M8fnkAB/3/aecDC50vW9dmLNBmfkuBnBxf5EAOmYd 5 | VQKViW689tV1IUZjTwE25e8PoKPq5Nr6lcnAO7jJjw3vwb9WHrR7mLwcDaI+SlaK 6 | FbokazvSHUnMHi3Y/1fc9gCPwXz/2+zGWmqZhkweRA== 7 | -----END EC PRIVATE KEY----- -------------------------------------------------------------------------------- /libraries/fabric-shim/test/unit/utils/utils.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright IBM Corp. All Rights Reserved. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | const chai = require('chai'); 8 | const expect = chai.expect; 9 | 10 | const utils = require('../../../lib/utils/utils'); 11 | 12 | describe('utils', () => { 13 | describe('generateLoggingPrefix', () => { 14 | it ('should shorten txids over 8 letters', () => { 15 | expect(utils.generateLoggingPrefix('myc', '123456789')).to.deep.equal('[myc-12345678]'); 16 | }); 17 | 18 | it ('should leave txids shorter than 8 as was', () => { 19 | expect(utils.generateLoggingPrefix('myc', '1234567')).to.deep.equal('[myc-1234567]'); 20 | }); 21 | 22 | it ('should leave txids exactly 8 letters as was', () => { 23 | expect(utils.generateLoggingPrefix('myc', '12345678')).to.deep.equal('[myc-12345678]'); 24 | }); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /libraries/fabric-shim/tsconfig.json: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 IBM All Rights Reserved. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | { 7 | "compilerOptions": { 8 | "types": ["./types/"], 9 | "alwaysStrict": true, 10 | "module": "commonjs", 11 | "declaration": true, 12 | "sourceMap": true, 13 | "strict": true, 14 | "target": "es2017", 15 | "lib": [ 16 | "esnext", 17 | ] 18 | }, 19 | "include": [ 20 | "lib/**/*", 21 | "test/**/*" 22 | ], 23 | "exclude": [ 24 | "node_modules/**/*" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /release_notes/v1.1.0-alpha.txt: -------------------------------------------------------------------------------- 1 | v1.1.0-alpha January 25, 2018 2 | ----------------------------- 3 | 4 | Release Notes 5 | ------------- 6 | No changes since v1.1.0-preview release 7 | 8 | Known Vulnerabilities 9 | --------------------- 10 | none 11 | 12 | Resolved Vulnerabilities 13 | ------------------------ 14 | none 15 | 16 | Known Issues & Workarounds 17 | -------------------------- 18 | none 19 | 20 | Change Log 21 | ---------- 22 | https://github.com/hyperledger/fabric-ca/blob/master/CHANGELOG.md#v110-alpha 23 | -------------------------------------------------------------------------------- /release_notes/v1.1.0-preview.txt: -------------------------------------------------------------------------------- 1 | v1.1.0-preview November 1, 2017 2 | ------------------------------- 3 | 4 | Release Notes 5 | ------------- 6 | Initial release of Node.js chaincode support 7 | https://jira.hyperledger.org/browse/FAB-5371 8 | 9 | Known Vulnerabilities 10 | --------------------- 11 | none 12 | 13 | Resolved Vulnerabilities 14 | ------------------------ 15 | none 16 | 17 | Known Issues & Workarounds 18 | -------------------------- 19 | none 20 | 21 | Change Log 22 | ---------- 23 | https://github.com/hyperledger/fabric-ca/blob/master/CHANGELOG.md#v110-preview 24 | -------------------------------------------------------------------------------- /release_notes/v1.1.0.txt: -------------------------------------------------------------------------------- 1 | v1.1.0 March, 2018 2 | ----------------------------- 3 | 4 | Release Notes 5 | ------------- 6 | Initial GA release of Node.js chaincode support. 7 | Includes bug fixes since v1.1.0-alpha release. 8 | 9 | Known Vulnerabilities 10 | --------------------- 11 | none 12 | 13 | Resolved Vulnerabilities 14 | ------------------------ 15 | none 16 | 17 | Known Issues & Workarounds 18 | -------------------------- 19 | none 20 | 21 | Change Log 22 | ---------- 23 | https://github.com/hyperledger/fabric-chaincode-node/blob/release-1.1/CHANGELOG.md#v110 24 | -------------------------------------------------------------------------------- /release_notes/v1.2.0.txt: -------------------------------------------------------------------------------- 1 | v1.2.0 July 6, 2018 2 | ----------------------------- 3 | 4 | Release Notes 5 | ------------- 6 | Add support for private data APIs. 7 | Bug fixes. 8 | 9 | 10 | Known Vulnerabilities 11 | --------------------- 12 | none 13 | 14 | Resolved Vulnerabilities 15 | ------------------------ 16 | none 17 | 18 | Known Issues & Workarounds 19 | -------------------------- 20 | none 21 | 22 | Change Log 23 | ---------- 24 | https://github.com/hyperledger/fabric-chaincode-node/blob/release-1.2/CHANGELOG.md#v120 25 | -------------------------------------------------------------------------------- /release_notes/v1.3.0.txt: -------------------------------------------------------------------------------- 1 | v1.3.0 October 10, 2018 2 | ----------------------------- 3 | 4 | Release Notes 5 | ------------- 6 | Bug fixes. 7 | Paging support for query. 8 | Typescript definitions are now included. 9 | 10 | 11 | Known Vulnerabilities 12 | --------------------- 13 | none 14 | 15 | Resolved Vulnerabilities 16 | ------------------------ 17 | none 18 | 19 | Known Issues & Workarounds 20 | -------------------------- 21 | none 22 | 23 | Change Log 24 | ---------- 25 | https://github.com/hyperledger/fabric-chaincode-node/blob/release-1.3/CHANGELOG.md#v130 26 | -------------------------------------------------------------------------------- /release_notes/v1.4.0-beta.txt: -------------------------------------------------------------------------------- 1 | v1.4.0-beta November 1, 2018 2 | ----------------------------- 3 | 4 | Release Notes 5 | ------------- 6 | Bug fixes. 7 | Added the fabric contract API 8 | 9 | 10 | Known Vulnerabilities 11 | --------------------- 12 | none 13 | 14 | Resolved Vulnerabilities 15 | ------------------------ 16 | none 17 | 18 | Known Issues & Workarounds 19 | -------------------------- 20 | none 21 | 22 | Change Log 23 | ---------- 24 | https://github.com/hyperledger/fabric-chaincode-node/blob/master/CHANGELOG.md#v140-beta 25 | -------------------------------------------------------------------------------- /release_notes/v1.4.0.txt: -------------------------------------------------------------------------------- 1 | v1.4.0-beta November 1, 2018 2 | ----------------------------- 3 | 4 | Release Notes 5 | ------------- 6 | Fabric 1.4.0 introduces a new programming model designed to improve developer productivity and ease of use. 7 | A new NPM package `fabric-contract-api` is added that lets the developer focus on the functions they want to invoke 8 | within the chaincode. They can also modularize their applications into 'Contracts' by extending a Contract class. 9 | 10 | See https://hyperledger-fabric.readthedocs.io/en/developapps/developing_applications.html 11 | 12 | To help client applications, and tooling and to make working with the transaction functions easier, a defined 13 | schema of Contract Metadata has been introduced. Depending on language a large part of this can be automatically created. 14 | Typescript Annotations are provided that are very useful in creating this data. 15 | 16 | See https://fabric-shim.github.io/contract-schema.json 17 | 18 | 19 | On the client application side, a new NPM package `fabric-network` is added which contains the classes and methods for writing 20 | blockchain enabled applications in node.js using javascript or typescript. 21 | 22 | See https://fabric-sdk-node.github.io/module-fabric-network.html 23 | 24 | 25 | Bug fixes and documentation improvements. 26 | 27 | Known Vulnerabilities 28 | --------------------- 29 | none 30 | 31 | Resolved Vulnerabilities 32 | ------------------------ 33 | none 34 | 35 | Known Issues & Workarounds 36 | -------------------------- 37 | none 38 | 39 | Change Log 40 | ---------- 41 | https://github.com/hyperledger/fabric-chaincode-node/blob/master/CHANGELOG.md#v140 42 | -------------------------------------------------------------------------------- /release_notes/v2.0.0-alpha.txt: -------------------------------------------------------------------------------- 1 | v2.0.0-alpha April 5th, 2019 2 | ----------------------------- 3 | 4 | Release Notes 5 | ------------- 6 | The main change in the v2.0.0 alpha over v1.4.1 is the level of NodeJS runtime has moved up to version 10 7 | v2.0.0 has v1.4.1 level of base functionality 8 | 9 | Migration Notes 10 | --------------- 11 | Note that a change needed to be made to the metadata schema as it was in error; it had diverged from the JSONSchema standard 12 | so that it was not possible to validate complex objects. 13 | 14 | If you have custom metadata defined in the contract, then for the complex objects defined in the 'components' section 15 | the properties of this object where previously held as array; they now need to be held as a map with the key as the name 16 | of the property 17 | 18 | Return types on functions where returned as an array of schema objects. this has been modified to be a single object. i.e. 19 | the single value array is now just a single value. 20 | 21 | There is also a new nodeenv docker image that is used for hosting the chaincode rather than use the baseos image. 22 | 23 | Summary of the programming model 24 | ------------------------------- 25 | 26 | This is designed to improve developer productivity and ease of use. 27 | For more information see https://hyperledger-fabric.readthedocs.io/en/developapps/developing_applications.html 28 | 29 | Known Vulnerabilities 30 | --------------------- 31 | none 32 | 33 | Resolved Vulnerabilities 34 | ------------------------ 35 | none 36 | 37 | Known Issues & Workarounds 38 | -------------------------- 39 | none 40 | 41 | Change Log 42 | ---------- 43 | https://github.com/hyperledger/fabric-chaincode-node/blob/release-1.4/CHANGELOG.md#v141 44 | -------------------------------------------------------------------------------- /release_notes/v2.0.0-beta.txt: -------------------------------------------------------------------------------- 1 | v2.0.0-beta, 12 December 2019 2 | ----------------------------- 3 | 4 | Release Notes 5 | ------------- 6 | The main change in the v2.0.0 beta is the level of NodeJS runtime has moved up to the latest LTS version of v12.13.0 7 | v2.0.0 beta has the fixes from v1.4.4 level. 8 | 9 | Migration Notes 10 | --------------- 11 | Note that a change needed to be made to the metadata schema as it was in error; it had diverged from the JSONSchema standard 12 | so that it was not possible to validate complex objects. 13 | 14 | If you have custom metadata defined in the contract, then for the complex objects defined in the 'components' section 15 | the properties of this object where previously held as array; they now need to be held as a map with the key as the name 16 | of the property 17 | 18 | Return types on functions where returned as an array of schema objects. this has been modified to be a single object. i.e. 19 | the single value array is now just a single value. 20 | 21 | There is also a new nodeenv docker image that is used for hosting the chaincode rather than use the baseos image as in V1.4 22 | 23 | In v1.4, the fabric-contract-api had a dependency on the fabric-shim. This has changed in this version to have a dependency 24 | on the new fabric-shim-api module. This allows the fabric-contract-api to be used client side for annotations. 25 | 26 | For contributors, the v2.0.0 repo is built using rush and is organized as a full mono-repo. 27 | 28 | The @Object annotation has been deprecated in favour of the @DataType annotation 29 | 30 | The x509 library used for parsing has changed; this should be parse the X509 certificates exactly the same way; this is a note that 31 | differences are observed in the parsed certificates please raise an issue. 32 | 33 | Summary of the programming model 34 | ------------------------------- 35 | 36 | This is designed to improve developer productivity and ease of use. 37 | For more information see https://hyperledger-fabric.readthedocs.io/en/developapps/developing_applications.html 38 | 39 | Known Vulnerabilities 40 | --------------------- 41 | none 42 | 43 | Resolved Vulnerabilities 44 | ------------------------ 45 | none 46 | 47 | Known Issues & Workarounds 48 | -------------------------- 49 | none 50 | 51 | Change Log 52 | ---------- 53 | https://github.com/hyperledger/fabric-chaincode-node/blob/release-1.4/CHANGELOG.md#v2.0.0-beta 54 | -------------------------------------------------------------------------------- /release_notes/v2.0.0.txt: -------------------------------------------------------------------------------- 1 | v2.0.0, 22 January 2020 2 | ----------------------- 3 | 4 | Release Notes 5 | ------------- 6 | The main change in the v2.0.0 is the level of NodeJS runtime has moved up to the latest LTS version of v12.13.0 7 | v2.0.0 has the fixes from v1.4.4 level. 8 | 9 | Migration Notes 10 | --------------- 11 | Note that a change needed to be made to the metadata schema as it was in error; it had diverged from the JSONSchema standard 12 | so that it was not possible to validate complex objects. 13 | 14 | If you have custom metadata defined in the contract, then for the complex objects defined in the 'components' section 15 | the properties of this object where previously held as array; they now need to be held as a map with the key as the name 16 | of the property 17 | 18 | Return types on functions where returned as an array of schema objects. this has been modified to be a single object. i.e. 19 | the single value array is now just a single value. 20 | 21 | There is also a new nodeenv docker image that is used for hosting the chaincode rather than use the baseos image as in V1.4 22 | 23 | In v1.4, the fabric-contract-api had a dependency on the fabric-shim. This has changed in this version to have a dependency 24 | on the new fabric-shim-api module. This allows the fabric-contract-api to be used client side for annotations. 25 | 26 | For contributors, the v2.0.0 repo is built using rush and is organized as a full mono-repo. 27 | 28 | The @Object annotation has been deprecated in favour of the @DataType annotation 29 | 30 | The x509 library used for parsing has changed; this should be parse the X509 certificates exactly the same way; this is a note that 31 | differences are observed in the parsed certificates please raise an issue. 32 | 33 | Summary of the programming model 34 | ------------------------------- 35 | 36 | This is designed to improve developer productivity and ease of use. 37 | For more information see https://hyperledger-fabric.readthedocs.io/en/developapps/developing_applications.html 38 | 39 | Known Vulnerabilities 40 | --------------------- 41 | none 42 | 43 | Resolved Vulnerabilities 44 | ------------------------ 45 | none 46 | 47 | Known Issues & Workarounds 48 | -------------------------- 49 | none 50 | 51 | Change Log 52 | ---------- 53 | https://github.com/hyperledger/fabric-chaincode-node/blob/release-2.x/CHANGELOG.md#v2.0.0 54 | -------------------------------------------------------------------------------- /release_notes/v2.1.0.txt: -------------------------------------------------------------------------------- 1 | v2.1.0 2 | ------ 3 | 4 | Release Notes 5 | ------------- 6 | There are minimal changes between v2.0.0 and v2.1.0, please see the change log for a full list of updates. 7 | 8 | The release-2.0 branch has been renamed to release-2.x; the v2.1.0 release supercedes v2.0.0. 9 | The release-1.4 branch is currently LTS, please see the proposed Fabric LTS strategy for more information: 10 | https://github.com/hyperledger/fabric-rfcs/pull/23 11 | 12 | - FABCN-373 Added a compatibility.md file, explaining support for node and fabric versions 13 | - FABCN-381 Exposes a new shim function for returning the CORE_PEER_LOCALMSPID peer environment variable 14 | 15 | Change Log 16 | ---------- 17 | https://github.com/hyperledger/fabric-chaincode-node/blob/release-2.x/CHANGELOG.md#v2.1.0 18 | -------------------------------------------------------------------------------- /release_notes/v2.1.1.txt: -------------------------------------------------------------------------------- 1 | v2.1.1 2 | ------ 3 | 4 | Release Notes 5 | ------------- 6 | There are minimal changes between v2.1.0 and v2.1.1, please see the change log for a full list of updates. 7 | 8 | The release-2.0 branch has been renamed to release-2.x; the v2.1.0 release supercedes v2.0.0. 9 | The release-1.4 branch is currently LTS, please see the proposed Fabric LTS strategy for more information: 10 | https://github.com/hyperledger/fabric-rfcs/pull/23 11 | 12 | - FABCN-394 fabric-shim incorrectly implements interface ChaincodeStub from fabric-shim-api 13 | 14 | Change Log 15 | ---------- 16 | https://github.com/hyperledger/fabric-chaincode-node/blob/release-2.x/CHANGELOG.md#v2.1.1 17 | -------------------------------------------------------------------------------- /release_notes/v2.1.2.txt: -------------------------------------------------------------------------------- 1 | v2.1.2 2 | ------ 3 | 4 | Release Notes 5 | ------------- 6 | 7 | This release fixs a bug when querying more than 100 assets. 8 | 9 | The release-2.0 branch has been renamed to release-2.x; the v2.1.0 release supercedes v2.0.0. 10 | The release-1.4 branch is currently LTS, please see the proposed Fabric LTS strategy for more information: 11 | https://github.com/hyperledger/fabric-rfcs/pull/23 12 | 13 | Change Log 14 | ---------- 15 | https://github.com/hyperledger/fabric-chaincode-node/blob/release-2.x/CHANGELOG.md#v2.1.2 16 | -------------------------------------------------------------------------------- /release_notes/v2.1.3.txt: -------------------------------------------------------------------------------- 1 | v2.1.3 2 | ------ 3 | 4 | Release Notes 5 | ------------- 6 | 7 | Locks the version of the @grpc/grpc-js library to 1.0.3 8 | The updated grpc lirbary of 1.1.0 prevents the chaincode from contacting the peer. 9 | 10 | The release-2.0 branch has been renamed to release-2.x; the v2.1.0 release supercedes v2.0.0. 11 | The release-1.4 branch is currently LTS, please see the proposed Fabric LTS strategy for more information: 12 | https://github.com/hyperledger/fabric-rfcs/pull/23 13 | 14 | Change Log 15 | ---------- 16 | https://github.com/hyperledger/fabric-chaincode-node/blob/release-2.x/CHANGELOG.md#v2.1.3 17 | -------------------------------------------------------------------------------- /release_notes/v2.1.4.txt: -------------------------------------------------------------------------------- 1 | v2.1.4 2 | ------ 3 | 4 | Release Notes 5 | ------------- 6 | 7 | - FABCN-418 Dependency unable to use git 8 | 9 | Locks the version of the winston library to 3.2.1 10 | The updated winston library after 3.3.0 prevents chaincode installing due to 11 | a new requirement for git which is not available in the 12 | hyperledger/fabric-nodeenv docker image. 13 | 14 | The release-2.0 branch has been renamed to release-2.x; the v2.1.0 release supercedes v2.0.0. 15 | The release-1.4 branch is currently LTS, please see the proposed Fabric LTS strategy for more information: 16 | https://github.com/hyperledger/fabric-rfcs/pull/23 17 | 18 | Change Log 19 | ---------- 20 | https://github.com/hyperledger/fabric-chaincode-node/blob/release-2.x/CHANGELOG.md#v2.1.4 21 | -------------------------------------------------------------------------------- /release_notes/v2.2.0.txt: -------------------------------------------------------------------------------- 1 | v2.2.0 2 | ------ 3 | 4 | Release Notes 5 | ------------- 6 | 7 | The v2.2.0 release is the LTS version of the fabric-chaincode-node 8 | 9 | 10 | Change Log 11 | ---------- 12 | https://github.com/hyperledger/fabric-chaincode-node/blob/release-2.x/CHANGELOG.md#v2.2.0 13 | -------------------------------------------------------------------------------- /release_notes/v2.3.0.txt: -------------------------------------------------------------------------------- 1 | v2.3.0 2 | ------ 3 | 4 | Release Notes 5 | ------------- 6 | 7 | - Updated class transformer dependency 8 | - Fixed type for timestamp.second 9 | - OOM on Large Arg Size 10 | - Removed to.be.ok 11 | - Updated typescript and @types/node 12 | - Added release guide 13 | 14 | 15 | Change Log 16 | ---------- 17 | https://github.com/hyperledger/fabric-chaincode-node/blob/release-2.x/CHANGELOG.md#v2.3.0 18 | -------------------------------------------------------------------------------- /release_notes/v2.4.0-beta.txt: -------------------------------------------------------------------------------- 1 | v2.4.0-beta 2 | ------ 3 | 4 | Release Notes 5 | ------------- 6 | This v2.4.0-beta Release is a bug fix release of the main branch. 7 | 8 | Change Log 9 | ---------- 10 | https://github.com/hyperledger/fabric-chaincode-node/blob/release-2.x/CHANGELOG.md#v2.4.0-beta 11 | -------------------------------------------------------------------------------- /release_notes/v2.4.0.txt: -------------------------------------------------------------------------------- 1 | v2.4.0 2 | ------ 3 | 4 | Release Notes 5 | ------------- 6 | This v2.4.0 Release is a bug fix release of the main branch. 7 | 8 | Note that version of Node.js is updated to 16.4.0. See the COMPATIBILITY.md file in the main branch for information. 9 | 10 | Change Log 11 | ---------- 12 | https://github.com/hyperledger/fabric-chaincode-node/blob/release-2.x/CHANGELOG.md#v2.4.0-beta 13 | -------------------------------------------------------------------------------- /release_notes/v2.4.1.txt: -------------------------------------------------------------------------------- 1 | v2.4.1 2 | ------ 3 | 4 | Release Notes 5 | ------------- 6 | This v2.4.1 is a release for fix the CI pipeline to properly release docker images. 7 | 8 | Note that version of Node.js is updated to 16.4.0. See the COMPATIBILITY.md file in the main branch for information. 9 | 10 | Change Log 11 | ---------- 12 | https://github.com/hyperledger/fabric-chaincode-node/blob/release-2.x/CHANGELOG.md#v2.4.1 13 | -------------------------------------------------------------------------------- /release_notes/v2.4.2.txt: -------------------------------------------------------------------------------- 1 | v2.4.2 2 | ------ 3 | 4 | Release Notes 5 | ------------- 6 | 7 | This release corrects the 2.4 nodeenv docker image to be Node 16, and removes the fabric-shim-crypto package. 8 | 9 | Note that version of Node.js is updated to 16.4.0. See the COMPATIBILITY.md file in the main branch for information. 10 | 11 | See the change log for a full list of updates. 12 | 13 | Change Log 14 | ---------- 15 | https://github.com/hyperledger/fabric-chaincode-node/blob/main/CHANGELOG.md#v2.4.2 16 | -------------------------------------------------------------------------------- /release_notes/v2.5.0.txt: -------------------------------------------------------------------------------- 1 | v2.5.0 2 | ------ 3 | 4 | Release Notes 5 | ------------- 6 | This is the LTS Release of of the v2.5 Fabric Chaincode Node. It replaces the previous v2.2 LTS. 7 | 8 | - the PurgePrivateData feature is exposed via a new `PurgePrivateData` API 9 | 10 | Change Log 11 | ---------- 12 | https://github.com/hyperledger/fabric-chaincode-node/blob/main/CHANGELOG.md#v2.5.0 13 | -------------------------------------------------------------------------------- /release_notes/v2.5.1.txt: -------------------------------------------------------------------------------- 1 | v2.5.1 2 | ------ 3 | 4 | Release Notes 5 | ------------- 6 | This is the LTS Release of of the v2.5 Fabric Chaincode Node. It replaces the previous v2.2 LTS. 7 | 8 | - the PurgePrivateData feature is exposed via a new `PurgePrivateData` API 9 | - the grpc-js dependency has been locked to 1.8.1 10 | - arm docker builds 11 | 12 | Change Log 13 | ---------- 14 | https://github.com/hyperledger/fabric-chaincode-node/blob/main/CHANGELOG.md#v2.5.0 15 | -------------------------------------------------------------------------------- /release_notes/v2.5.2.txt: -------------------------------------------------------------------------------- 1 | v2.5.2 2 | ------ 3 | 4 | Release Notes 5 | ------------- 6 | This is the LTS Release of of the v2.5 Fabric Chaincode Node. It replaces the previous v2.2 LTS. 7 | 8 | New in the version 2.5.2 9 | 10 | - Fixed the getHistory API returning a byte buffer rather than an JSON object 11 | - Setting a state endorsement policy functions correctly 12 | 13 | Other noteable 2.5 updates are 14 | 15 | - the PurgePrivateData feature is exposed via a new `PurgePrivateData` API 16 | - the grpc-js dependency has been locked to 1.8.1 17 | - arm docker builds 18 | 19 | Change Log 20 | ---------- 21 | https://github.com/hyperledger/fabric-chaincode-node/blob/main/CHANGELOG.md#v2.5.2 22 | -------------------------------------------------------------------------------- /test/chaincodes/annotations/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ts_chaincode", 3 | "description": "Chaincode testing typescript functionality and annotations", 4 | "engines": { 5 | "node": ">=18" 6 | }, 7 | "scripts": { 8 | "build": "tsc", 9 | "start": "fabric-chaincode-node start", 10 | "prestart": "tsc" 11 | }, 12 | "main": "dist/index.js", 13 | "typings": "dist/index.d.ts", 14 | "engine-strict": true, 15 | "engineStrict": true, 16 | "version": "2.5.9", 17 | "author": "", 18 | "license": "APACHE-2.0", 19 | "dependencies": { 20 | "@types/node": "^16.11.4", 21 | "fabric-contract-api": "2.5.9", 22 | "fabric-shim": "2.5.9", 23 | "ts-node": "^3.3.0", 24 | "tslint": "^5.6.0", 25 | "typescript": "^4.0.2" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /test/chaincodes/annotations/src/index.ts: -------------------------------------------------------------------------------- 1 | import TestContract from './test_contract/test_contract'; 2 | export const contracts: any[] = [ TestContract ]; -------------------------------------------------------------------------------- /test/chaincodes/annotations/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "dist", 4 | "target": "es2017", 5 | "moduleResolution": "node", 6 | "module": "commonjs", 7 | "declaration": true, 8 | "experimentalDecorators": true, 9 | "emitDecoratorMetadata": true, 10 | "lib": [ 11 | "esnext" 12 | ] 13 | } 14 | } -------------------------------------------------------------------------------- /test/chaincodes/clientidentity/chaincode.js: -------------------------------------------------------------------------------- 1 | /* 2 | # Copyright IBM Corp. All Rights Reserved. 3 | # 4 | # SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 'use strict'; 7 | 8 | const {Contract} = require('fabric-contract-api'); 9 | const shim = require('fabric-shim'); 10 | 11 | class ClientIdentityChaincode extends Contract { 12 | 13 | constructor() { 14 | super('org.mynamespace.clientidentity'); 15 | } 16 | 17 | async instantiate(ctx) { 18 | const stub = ctx.stub; 19 | 20 | await stub.putState('string', Buffer.from('string')); 21 | const names = ['ann', 'beth', 'cory']; 22 | const colors = ['black', 'red', 'yellow']; 23 | for (const n in names) { 24 | for (const c in colors) { 25 | const compositeKey = stub.createCompositeKey('name~color', [names[n], colors[c]]); 26 | await stub.putState(compositeKey, names[n] + colors[c]); 27 | } 28 | } 29 | for (let i = 0; i < 5; i++) { 30 | await stub.putState(`key${i}`, Buffer.from(`value${i}`)); 31 | await stub.putState(`jsonkey${i}`, Buffer.from(JSON.stringify({value: `value${i}`}))); 32 | } 33 | } 34 | 35 | async clientIdentityInstance({stub}) { 36 | const cid = new shim.ClientIdentity(stub); 37 | return {mspId: cid.mspId, id: cid.id}; 38 | } 39 | 40 | async localMspID({stub}) { 41 | const localMspID = stub.getMspID(); 42 | return {localMspID}; 43 | } 44 | 45 | } 46 | module.exports = ClientIdentityChaincode; -------------------------------------------------------------------------------- /test/chaincodes/clientidentity/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright IBM Corp. All Rights Reserved. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | 'use strict'; 8 | 9 | const Chaincode = require('./chaincode'); 10 | 11 | module.exports.contracts = [Chaincode]; 12 | -------------------------------------------------------------------------------- /test/chaincodes/clientidentity/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "chaincode", 3 | "description": "Chaincode testing ClientIdentity functionality", 4 | "engines": { 5 | "node": ">=18" 6 | }, 7 | "scripts": { 8 | "start": "fabric-chaincode-node start" 9 | }, 10 | "main": "index.js", 11 | "engine-strict": true, 12 | "engineStrict": true, 13 | "version": "2.5.9", 14 | "author": "", 15 | "license": "Apache-2.0", 16 | "dependencies": { 17 | "fabric-shim": "2.5.9", 18 | "fabric-contract-api": "2.5.9" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /test/chaincodes/crosschaincode/chaincode.js: -------------------------------------------------------------------------------- 1 | /* 2 | # Copyright IBM Corp. All Rights Reserved. 3 | # 4 | # SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 'use strict'; 7 | 8 | const {Contract} = require('fabric-contract-api'); 9 | 10 | class CrossChaincode extends Contract { 11 | 12 | constructor() { 13 | super('org.mynamespace.crosschaincode'); 14 | } 15 | 16 | async instantiate(ctx) { 17 | const stub = ctx.stub; 18 | 19 | await stub.putState('string', Buffer.from('string')); 20 | const names = ['ann', 'beth', 'cory']; 21 | const colors = ['black', 'red', 'yellow']; 22 | for (const n in names) { 23 | for (const c in colors) { 24 | const compositeKey = stub.createCompositeKey('name~color', [names[n], colors[c]]); 25 | await stub.putState(compositeKey, names[n] + colors[c]); 26 | } 27 | } 28 | for (let i = 0; i < 5; i++) { 29 | await stub.putState(`key${i}`, Buffer.from(`value${i}`)); 30 | await stub.putState(`jsonkey${i}`, Buffer.from(JSON.stringify({value: `value${i}`}))); 31 | } 32 | } 33 | 34 | async invokeChaincode({stub}) { 35 | const {params} = stub.getFunctionAndParameters(); 36 | const results = await stub.invokeChaincode('crosschaincode2', [params[0], params[1]]); 37 | return results.payload.toString(); 38 | } 39 | 40 | async invokeChaincodeError({stub}) { 41 | const {params} = stub.getFunctionAndParameters(); 42 | const results = await stub.invokeChaincode('crosschaincode2', [params[0]]); 43 | return results; 44 | } 45 | 46 | } 47 | module.exports = CrossChaincode; 48 | -------------------------------------------------------------------------------- /test/chaincodes/crosschaincode/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright IBM Corp. All Rights Reserved. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | 'use strict'; 8 | 9 | const Chaincode = require('./chaincode'); 10 | 11 | module.exports.contracts = [Chaincode]; 12 | -------------------------------------------------------------------------------- /test/chaincodes/crosschaincode/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "chaincode", 3 | "description": "Chaincode testing cross chaincode functionality", 4 | "engines": { 5 | "node": ">=18" 6 | }, 7 | "scripts": { 8 | "start": "set -x && CORE_CHAINCODE_LOGGING_LEVEL=debug fabric-chaincode-node start" 9 | }, 10 | "main": "index.js", 11 | "engine-strict": true, 12 | "engineStrict": true, 13 | "version": "2.5.9", 14 | "author": "", 15 | "license": "Apache-2.0", 16 | "dependencies": { 17 | "fabric-shim": "2.5.9", 18 | "fabric-contract-api": "2.5.9" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /test/chaincodes/crosschaincode2/chaincode.js: -------------------------------------------------------------------------------- 1 | /* 2 | # Copyright IBM Corp. All Rights Reserved. 3 | # 4 | # SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 'use strict'; 7 | 8 | const {Contract} = require('fabric-contract-api'); 9 | 10 | class CrossChaincode2 extends Contract { 11 | 12 | constructor() { 13 | super('org.mynamespace.crosschaincode2'); 14 | } 15 | 16 | async instantiate(ctx) { 17 | const stub = ctx.stub; 18 | await stub.putState('key1', Buffer.from('crosschaincode2')); 19 | } 20 | 21 | // useful helper transactions 22 | async getKey({stub}) { 23 | const {params} = stub.getFunctionAndParameters(); 24 | if (params.length !== 1) { 25 | throw new Error('Incorrect no. of parameters'); 26 | } 27 | const key = params[0]; 28 | return (await stub.getState(key)).toString(); 29 | } 30 | 31 | } 32 | module.exports = CrossChaincode2; -------------------------------------------------------------------------------- /test/chaincodes/crosschaincode2/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | # Copyright IBM Corp. All Rights Reserved. 3 | # 4 | # SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 'use strict'; 7 | 8 | const Chaincode = require('./chaincode'); 9 | 10 | module.exports.contracts = [Chaincode]; 11 | -------------------------------------------------------------------------------- /test/chaincodes/crosschaincode2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "chaincode", 3 | "description": "Chaincode testing cross chaincode functionality", 4 | "engines": { 5 | "node": ">=18" 6 | }, 7 | "scripts": { 8 | "start": "fabric-chaincode-node start" 9 | }, 10 | "main": "index.js", 11 | "engine-strict": true, 12 | "engineStrict": true, 13 | "version": "2.5.9", 14 | "author": "", 15 | "license": "Apache-2.0", 16 | "dependencies": { 17 | "fabric-shim": "2.5.9", 18 | "fabric-contract-api": "2.5.9" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /test/chaincodes/crud/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright IBM Corp. All Rights Reserved. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | 'use strict'; 8 | 9 | const Chaincode = require('./chaincode'); 10 | 11 | module.exports.contracts = [Chaincode]; 12 | -------------------------------------------------------------------------------- /test/chaincodes/crud/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "chaincode", 3 | "description": "Chaincode testing crud functionality", 4 | "engines": { 5 | "node": ">=18" 6 | }, 7 | "scripts": { 8 | "start": "set -x && CORE_CHAINCODE_LOGGING_LEVEL=debug fabric-chaincode-node start" 9 | }, 10 | "main": "index.js", 11 | "engine-strict": true, 12 | "engineStrict": true, 13 | "version": "2.5.9", 14 | "author": "", 15 | "license": "Apache-2.0", 16 | "dependencies": { 17 | "fabric-shim": "2.5.9", 18 | "fabric-contract-api": "2.5.9" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /test/chaincodes/events/chaincode.js: -------------------------------------------------------------------------------- 1 | /* 2 | # Copyright IBM Corp. All Rights Reserved. 3 | # 4 | # SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 'use strict'; 7 | 8 | const {Contract} = require('fabric-contract-api'); 9 | 10 | class EventsChaincode extends Contract { 11 | 12 | constructor() { 13 | super('org.mynamespace.events'); 14 | this.logBuffer = {output: []}; 15 | } 16 | 17 | async instantiate(ctx) { 18 | 19 | } 20 | 21 | async emit(ctx, value) { 22 | const buffer = Buffer.from(value); 23 | ctx.stub.setEvent('myevent', buffer); 24 | } 25 | 26 | } 27 | module.exports = EventsChaincode; 28 | -------------------------------------------------------------------------------- /test/chaincodes/events/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright IBM Corp. All Rights Reserved. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | 'use strict'; 8 | 9 | const Chaincode = require('./chaincode'); 10 | 11 | module.exports.contracts = [Chaincode]; 12 | -------------------------------------------------------------------------------- /test/chaincodes/events/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "chaincode", 3 | "description": "Chaincode testing events functionality", 4 | "engines": { 5 | "node": ">=18" 6 | }, 7 | "scripts": { 8 | "start": "set -x && CORE_CHAINCODE_LOGGING_LEVEL=debug fabric-chaincode-node start" 9 | }, 10 | "main": "index.js", 11 | "engine-strict": true, 12 | "engineStrict": true, 13 | "version": "2.5.9", 14 | "author": "", 15 | "license": "Apache-2.0", 16 | "dependencies": { 17 | "fabric-shim": "2.5.9", 18 | "fabric-contract-api": "2.5.9" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /test/chaincodes/ledger/chaincode.js: -------------------------------------------------------------------------------- 1 | /* 2 | # Copyright IBM Corp. All Rights Reserved. 3 | # 4 | # SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 'use strict'; 7 | 8 | const {Contract} = require('fabric-contract-api'); 9 | const {Ledger} = require('fabric-ledger'); 10 | 11 | class LedgerTestContract extends Contract { 12 | 13 | constructor() { 14 | super('org.example.ledger'); 15 | this.logBuffer = {output: []}; 16 | } 17 | 18 | async getLedger(ctx) { 19 | const ledger = Ledger.getLedger(ctx); 20 | 21 | return ledger?'success':'fail'; 22 | } 23 | } 24 | module.exports = LedgerTestContract; 25 | -------------------------------------------------------------------------------- /test/chaincodes/ledger/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright IBM Corp. All Rights Reserved. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | 'use strict'; 8 | 9 | const Chaincode = require('./chaincode'); 10 | 11 | module.exports.contracts = [Chaincode]; 12 | -------------------------------------------------------------------------------- /test/chaincodes/ledger/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "chaincode", 3 | "description": "Chaincode testing ledger functionality", 4 | "engines": { 5 | "node": ">=18" 6 | }, 7 | "scripts": { 8 | "start": "fabric-chaincode-node start" 9 | }, 10 | "main": "index.js", 11 | "engine-strict": true, 12 | "engineStrict": true, 13 | "version": "2.5.9", 14 | "author": "", 15 | "license": "Apache-2.0", 16 | "dependencies": { 17 | "fabric-shim": "2.5.9", 18 | "fabric-contract-api": "2.5.9", 19 | "fabric-ledger": "2.5.9" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /test/chaincodes/privateData/chaincode.js: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | */ 4 | 5 | 'use strict'; 6 | 7 | const { Contract } = require('fabric-contract-api'); 8 | const crypto = require('crypto'); 9 | 10 | class privateDataContract extends Contract { 11 | 12 | async assetExists(ctx, assetId) { 13 | const data = await ctx.stub.getPrivateDataHash("collection", assetId); 14 | return (!!data && data.length > 0); 15 | } 16 | 17 | async createAsset(ctx, assetId) { 18 | const exists = await this.assetExists(ctx, assetId); 19 | if (exists) { 20 | throw new Error(`The asset asset ${assetId} already exists`); 21 | } 22 | 23 | const privateAsset = {}; 24 | 25 | const transientData = ctx.stub.getTransient(); 26 | if (transientData.size === 0 || !transientData.has('privateValue')) { 27 | throw new Error('The privateValue key was not specified in transient data. Please try again.'); 28 | } 29 | privateAsset.privateValue = transientData.get('privateValue').toString(); 30 | 31 | await ctx.stub.putPrivateData("collection", assetId, Buffer.from(JSON.stringify(privateAsset))); 32 | } 33 | 34 | async readAsset(ctx, assetId) { 35 | const exists = await this.assetExists(ctx, assetId); 36 | if (!exists) { 37 | throw new Error(`The asset ${assetId} does not exist`); 38 | } 39 | let privateDataString; 40 | const privateData = await ctx.stub.getPrivateData("collection", assetId); 41 | privateDataString = JSON.parse(privateData.toString()); 42 | return privateDataString; 43 | } 44 | 45 | async updateAsset(ctx, assetId) { 46 | const exists = await this.assetExists(ctx, assetId); 47 | if (!exists) { 48 | throw new Error(`The asset asset ${assetId} does not exist`); 49 | } 50 | const privateAsset = {}; 51 | 52 | const transientData = ctx.stub.getTransient(); 53 | if (transientData.size === 0 || !transientData.has('privateValue')) { 54 | throw new Error('The privateValue key was not specified in transient data. Please try again.'); 55 | } 56 | privateAsset.privateValue = transientData.get('privateValue').toString(); 57 | 58 | await ctx.stub.putPrivateData("collection", assetId, Buffer.from(JSON.stringify(privateAsset))); 59 | } 60 | 61 | async deleteAsset(ctx, assetId) { 62 | const exists = await this.assetExists(ctx, assetId); 63 | if (!exists) { 64 | throw new Error(`The asset asset ${assetId} does not exist`); 65 | } 66 | await ctx.stub.deletePrivateData("collection", assetId); 67 | } 68 | 69 | async purgeAsset(ctx, assetId) { 70 | const exists = await this.assetExists(ctx, assetId); 71 | if (!exists) { 72 | throw new Error(`The asset asset ${assetId} does not exist`); 73 | } 74 | await ctx.stub.purgePrivateData("collection", assetId); 75 | } 76 | 77 | async verifyAsset(ctx, mspid, assetId, objectToVerify) { 78 | 79 | const hashToVerify = crypto.createHash('sha256').update(objectToVerify).digest('hex'); 80 | const pdHashBytes = await ctx.stub.getPrivateDataHash("collection", assetId); 81 | if (pdHashBytes.length === 0) { 82 | throw new Error('No private data hash with the key: ' + assetId); 83 | } 84 | 85 | const actualHash = Buffer.from(pdHashBytes).toString('hex'); 86 | 87 | if (hashToVerify === actualHash) { 88 | return true; 89 | } else { 90 | return false; 91 | } 92 | } 93 | } 94 | 95 | module.exports = privateDataContract; 96 | -------------------------------------------------------------------------------- /test/chaincodes/privateData/collection-config/collection.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "collection", 4 | "policy": "OR('Org1MSP.member', 'Org2MSP.member')", 5 | "requiredPeerCount": 1, 6 | "maxPeerCount": 1, 7 | "blockToLive":1000000, 8 | "memberOnlyRead": true, 9 | "memberOnlyWrite": true 10 | } 11 | ] 12 | -------------------------------------------------------------------------------- /test/chaincodes/privateData/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-License-Identifier: Apache-2.0 3 | */ 4 | 5 | 'use strict'; 6 | 7 | const Chaincode = require('./chaincode'); 8 | 9 | module.exports.contracts = [Chaincode]; 10 | 11 | -------------------------------------------------------------------------------- /test/chaincodes/privateData/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "chaincode", 3 | "description": "Chaincode testing private data functionality", 4 | "engines": { 5 | "node": ">=18" 6 | }, 7 | "scripts": { 8 | "start": "fabric-chaincode-node start" 9 | }, 10 | "main": "index.js", 11 | "engine-strict": true, 12 | "engineStrict": true, 13 | "version": "2.5.9", 14 | "author": "", 15 | "license": "Apache-2.0", 16 | "dependencies": { 17 | "fabric-shim": "2.5.9", 18 | "fabric-contract-api": "2.5.9" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /test/chaincodes/query/chaincode.js: -------------------------------------------------------------------------------- 1 | /* 2 | # Copyright IBM Corp. All Rights Reserved. 3 | # 4 | # SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 'use strict'; 7 | 8 | const {Contract} = require('fabric-contract-api'); 9 | 10 | async function getAllResults(iterator, getKeys) { 11 | const allResults = []; 12 | let loop = true; 13 | while (loop) { 14 | const res = await iterator.next(); 15 | if (!res.value && res.done) { 16 | await iterator.close(); 17 | return allResults; 18 | } else if (!res.value) { 19 | throw new Error('no value and not done (internal error?)'); 20 | } 21 | const theVal = (getKeys) ? res.value.key : res.value.value.toString('utf8'); 22 | allResults.push(JSON.parse(theVal)); 23 | if (res.done) { 24 | await iterator.close(); 25 | loop = false; 26 | return allResults; 27 | } 28 | } 29 | } 30 | 31 | class QueryChaincode extends Contract { 32 | 33 | async unknownTransaction({stub}) { 34 | throw new Error(`Could not find chaincode function: ${stub.getFunctionAndParameters()}`); 35 | } 36 | 37 | constructor() { 38 | super('org.mynamespace.query'); 39 | } 40 | 41 | async instantiate(ctx) { 42 | const stub = ctx.stub; 43 | 44 | await stub.putState('string', Buffer.from('string')); 45 | const names = ['ann', 'beth', 'cory']; 46 | const colors = ['black', 'red', 'yellow']; 47 | for (const n in names) { 48 | for (const c in colors) { 49 | const compositeKey = stub.createCompositeKey('name~color', [names[n], colors[c]]); 50 | await stub.putState(compositeKey, names[n] + colors[c]); 51 | } 52 | } 53 | for (let i = 0; i < 5; i++) { 54 | await stub.putState(`jsonkey${i}`, Buffer.from(JSON.stringify({value: `value${i}`}))); 55 | } 56 | } 57 | 58 | async query({stub}, query) { 59 | const iterator = await stub.getQueryResult(query); 60 | const results = await getAllResults(iterator); 61 | return JSON.stringify(results); 62 | } 63 | 64 | } 65 | module.exports = QueryChaincode; 66 | -------------------------------------------------------------------------------- /test/chaincodes/query/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright IBM Corp. All Rights Reserved. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | 'use strict'; 8 | 9 | const Chaincode = require('./chaincode'); 10 | 11 | module.exports.contracts = [Chaincode]; 12 | -------------------------------------------------------------------------------- /test/chaincodes/query/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "chaincode", 3 | "description": "Chaincode testing query functionality", 4 | "engines": { 5 | "node": ">=18" 6 | }, 7 | "scripts": { 8 | "start": "fabric-chaincode-node start" 9 | }, 10 | "main": "index.js", 11 | "engine-strict": true, 12 | "engineStrict": true, 13 | "version": "2.5.9", 14 | "author": "", 15 | "license": "Apache-2.0", 16 | "dependencies": { 17 | "fabric-shim": "2.5.9", 18 | "fabric-contract-api": "2.5.9" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /test/chaincodes/scenario/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright IBM Corp. All Rights Reserved. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | 'use strict'; 8 | 9 | const UpdateValues = require('./updatevalues'); 10 | const RemoveValues = require('./removevalues'); 11 | 12 | // export the smart contracts 13 | module.exports.contracts = [UpdateValues, RemoveValues]; 14 | -------------------------------------------------------------------------------- /test/chaincodes/scenario/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "chaincode", 3 | "description": "My first exciting chaincode implemented in node.js", 4 | "engines": { 5 | "node": ">=18" 6 | }, 7 | "scripts": { 8 | "start": "fabric-chaincode-node start" 9 | }, 10 | "main": "index.js", 11 | "engine-strict": true, 12 | "engineStrict": true, 13 | "version": "2.5.9", 14 | "author": "", 15 | "license": "Apache-2.0", 16 | "dependencies": { 17 | "fabric-shim": "2.5.9", 18 | "fabric-contract-api": "2.5.9" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /test/chaincodes/scenario/removevalues.js: -------------------------------------------------------------------------------- 1 | /* 2 | # Copyright IBM Corp. All Rights Reserved. 3 | # 4 | # SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 'use strict'; 7 | /* eslint-disable no-console */ 8 | const {Contract} = require('fabric-contract-api'); 9 | 10 | /** 11 | * Set of functions to support modifing the values 12 | */ 13 | class RemoveValues extends Contract { 14 | 15 | constructor() { 16 | super('RemoveValues'); 17 | // going to leave the default 'not known function' handling alone 18 | } 19 | 20 | /** 21 | * 22 | * @param {*} api 23 | */ 24 | async quarterAssetValue({stub}) { 25 | console.info('Transaction ID: ' + stub.getTxID()); 26 | 27 | const value = await stub.getState('dummyKey'); 28 | if (Number.isNan(value)) { 29 | const str = `'Need to have numerc value set to quarter it, ${value}`; 30 | console.error(str); 31 | throw new Error(str); 32 | } else { 33 | const v = value / 4; 34 | await stub.putState('dummyKey', v); 35 | return v; 36 | } 37 | } 38 | 39 | 40 | async getAssetValue({stub}) { 41 | console.info('Transaction ID: ' + stub.getTxID()); 42 | 43 | const value = await stub.getState('dummyKey'); 44 | return value; 45 | } 46 | 47 | } 48 | 49 | module.exports = RemoveValues; 50 | -------------------------------------------------------------------------------- /test/chaincodes/scenario/scenariocontext.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright IBM Corp. All Rights Reserved. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | 'use strict'; 8 | 9 | const {Context} = require('fabric-contract-api'); 10 | 11 | class ScenarioContext extends Context { 12 | 13 | constructor() { 14 | super(); 15 | } 16 | 17 | 18 | generateKey() { 19 | return this.stub.createCompositeKey('type', ['keyvalue']); 20 | } 21 | 22 | } 23 | 24 | module.exports = ScenarioContext; 25 | -------------------------------------------------------------------------------- /test/chaincodes/scenario/updatevalues.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright IBM Corp. All Rights Reserved. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | 'use strict'; 8 | 9 | const {Contract} = require('fabric-contract-api'); 10 | 11 | const ScenarioContext = require('./scenariocontext'); 12 | /** 13 | * Support the Updating of values within the SmartContract 14 | */ 15 | class UpdateValues extends Contract { 16 | 17 | _log(args) { 18 | this.logBuffer.output.push(`::[UpdateValues] ${args}`); 19 | } 20 | /** 21 | * Sets a name so that the functions in this particular class can 22 | * be separated from others. 23 | */ 24 | constructor() { 25 | super('UpdateValues'); 26 | this.logBuffer = {output: []}; 27 | } 28 | 29 | /** The function to invoke if something unkown comes in. 30 | * 31 | */ 32 | async unknownTransaction(ctx) { 33 | throw new Error('Big Friendly letters ->>> DON\'T PANIC'); 34 | } 35 | 36 | async beforeTransaction(ctx) { 37 | this._log(`Transaction ID: ${ctx.stub.getTxID()}`); 38 | } 39 | 40 | /** 41 | * Custom context for use within this contract 42 | */ 43 | createContext() { 44 | return new ScenarioContext(); 45 | } 46 | 47 | /** 48 | * A function that will setup a starting value 49 | * Note that this is not expliclity called from init. IF you want it called from init, then 50 | * specifiy it in the fn name when init is invoked. 51 | */ 52 | async setup(ctx) { 53 | await ctx.stub.putState(ctx.generateKey(), Buffer.from('Starting Value')); 54 | 55 | this._log('Put state success'); 56 | return Buffer.from(JSON.stringify(this.logBuffer)); 57 | } 58 | 59 | /** 60 | * @param {int|string} newAssetValue new asset value to set 61 | */ 62 | async setNewAssetValue(ctx, newAssetValue) { 63 | this._log(`New Asset value will be ${newAssetValue}`); 64 | await ctx.stub.putState(ctx.generateKey(), Buffer.from(newAssetValue)); 65 | 66 | return Buffer.from(JSON.stringify(this.logBuffer)); 67 | } 68 | 69 | /** 70 | * Doubles the api if it is a number fail otherwise 71 | */ 72 | async doubleAssetValue(ctx) { 73 | const value = await ctx.stub.getState(ctx.generateKey()); 74 | if (isNaN(value)) { 75 | const str = `'Need to have numerc value set to double it, ${value}`; 76 | this._log(str); 77 | throw new Error(str); 78 | } else { 79 | const v = value * 2; 80 | await ctx.stub.putState(ctx.generateKey(), v); 81 | this.logBuffer.result = v; 82 | } 83 | return Buffer.from(JSON.stringify(this.logBuffer)); 84 | } 85 | 86 | } 87 | 88 | module.exports = UpdateValues; 89 | -------------------------------------------------------------------------------- /test/chaincodes/server/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | package.lock.json 3 | package 4 | -------------------------------------------------------------------------------- /test/chaincodes/server/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM hyperledger/fabric-nodeenv:latest 2 | 3 | ADD . /opt/chaincode 4 | RUN cd /opt/chaincode; npm install 5 | 6 | WORKDIR /opt/chaincode 7 | ENTRYPOINT ["npm", "start"] 8 | -------------------------------------------------------------------------------- /test/chaincodes/server/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | # Copyright Hitachi America, Ltd. All Rights Reserved. 3 | # 4 | # SPDX-License-Identifier: Apache-2.0 5 | */ 6 | "use strict"; 7 | 8 | const { Contract } = require('fabric-contract-api'); 9 | 10 | class ServerTestChaincode extends Contract { 11 | async unknownTransaction({stub}) { 12 | const {fcn, params} = stub.getFunctionAndParameters(); 13 | throw new Error(`Could not find chaincode function: ${fcn}`); 14 | } 15 | 16 | constructor() { 17 | super('org.mynamespace.server'); 18 | } 19 | 20 | async putValue(ctx, value) { 21 | await ctx.stub.putState('state1', Buffer.from(JSON.stringify(value))); 22 | } 23 | 24 | async getValue(ctx) { 25 | const value = await ctx.stub.getState('state1'); 26 | return JSON.parse(value.toString()); 27 | } 28 | } 29 | 30 | exports.contracts = [ ServerTestChaincode ]; 31 | -------------------------------------------------------------------------------- /test/chaincodes/server/package/connection.json: -------------------------------------------------------------------------------- 1 | { 2 | "address": "cc-server:9999", 3 | "dial_timeout": "10s", 4 | "tls_required": false 5 | } 6 | -------------------------------------------------------------------------------- /test/chaincodes/server/package/metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "path": "", 3 | "type": "external", 4 | "label": "server_v0" 5 | } 6 | -------------------------------------------------------------------------------- /test/constants.js: -------------------------------------------------------------------------------- 1 | /* 2 | # Copyright IBM Corp. All Rights Reserved. 3 | # 4 | # SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 'use strict'; 7 | 8 | const peerAddress = 'peer0.org1.example.com:7052'; 9 | 10 | module.exports.peerAddress = peerAddress; 11 | -------------------------------------------------------------------------------- /test/e2e/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fabric-e2e-tests", 3 | "version": "2.5.9", 4 | "description": "", 5 | "main": "docker.js", 6 | "scripts": { 7 | "build": "", 8 | "test:e2e": "gulp -f ./scenario.js --reporter spec-junit-splitter-mocha-reporter 2>&1" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "Apache-2.0", 13 | "devDependencies": { 14 | "git-rev-sync": "3.0.1", 15 | "gulp": "^4.0.2", 16 | "toolchain": "1.0.0-dev", 17 | "delay": "5.0.0", 18 | "ip": "^1.1.5", 19 | "ajv": "^6.12.2", 20 | "ajv-cli": "^3.2.1", 21 | "spec-junit-splitter-mocha-reporter": "1.0.1" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /test/fixtures/channel-init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright London Stock Exchange Group All Rights Reserved. 3 | # 4 | # SPDX-License-Identifier: Apache-2.0 5 | # 6 | CHANNEL_NAME="$1" 7 | : ${CHANNEL_NAME:="mychannel"} 8 | : ${TIMEOUT:="60"} 9 | COUNTER=1 10 | MAX_RETRY=5 11 | GENESIS_LOCATION=/etc/hyperledger/config 12 | ORDERER_CA=/etc/hyperledger/config/crypto-config/ordererOrganizations/example.com/tlsca/tlsca.example.com-cert.pem 13 | 14 | echo "Channel name : "$CHANNEL_NAME 15 | 16 | verifyResult () { 17 | if [ $1 -ne 0 ] ; then 18 | echo "!!!!!!!!!!!!!!! "$2" !!!!!!!!!!!!!!!!" 19 | echo "================== ERROR !!! FAILED to execute Test Init ==================" 20 | echo 21 | exit 1 22 | fi 23 | } 24 | 25 | ## Sometimes Join takes time hence RETRY atleast for 5 times 26 | joinWithRetry () { 27 | peer channel join -b $GENESIS_LOCATION/$CHANNEL_NAME.block >&log.txt 28 | res=$? 29 | cat log.txt 30 | if [ $res -ne 0 -a $COUNTER -lt $MAX_RETRY ]; then 31 | COUNTER=` expr $COUNTER + 1` 32 | echo "PEER0 failed to join the channel, Retry after 2 seconds" 33 | sleep 2 34 | joinWithRetry 35 | else 36 | COUNTER=1 37 | fi 38 | verifyResult $res "After $MAX_RETRY attempts, PEER0 has failed to Join the Channel" 39 | } 40 | 41 | joinChannel () { 42 | joinWithRetry 43 | echo "===================== PEER0 joined on the channel \"$CHANNEL_NAME\" ===================== " 44 | sleep 2 45 | echo 46 | } 47 | 48 | ## Join all the peers to the channel 49 | echo "Having all peers join the channel..." 50 | joinChannel 51 | 52 | exit 0 53 | -------------------------------------------------------------------------------- /test/fixtures/kill-chaincode-node.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # SPDX-License-Identifier: Apache-2.0 4 | # 5 | 6 | kill $(ps aux | awk '/--peer.address/ {print $1}') 7 | kill $(ps aux | awk '/--peer.address/ {print $2}') -------------------------------------------------------------------------------- /test/fv/annotations.js: -------------------------------------------------------------------------------- 1 | /* 2 | # Copyright IBM Corp. All Rights Reserved. 3 | # 4 | # SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 'use-strict'; 7 | 8 | const fs = require('fs'); 9 | const path = require('path'); 10 | const Ajv = require('ajv'); 11 | const chai = require('chai'); 12 | chai.use(require('chai-as-promised')); 13 | const expect = chai.expect; 14 | const utils = require('./utils'); 15 | const {SHORT_STEP, LONG_STEP} = utils.TIMEOUTS; 16 | 17 | describe('Typescript chaincode', () => { 18 | const suite = 'annotations'; 19 | utils.registerAndEnroll(); 20 | 21 | before(async function () { 22 | this.timeout(LONG_STEP); 23 | return utils.installAndInstantiate(suite); 24 | }); 25 | 26 | 27 | describe('Scenario', () => { 28 | 29 | it('should write an asset', async function () { 30 | this.timeout(LONG_STEP); 31 | await utils.invoke(suite, 'TestContract:createAsset', ['GLD', 'GOLD_BAR', '100', 'EXTRA_ID', '50']); 32 | const payload = JSON.parse(await utils.query(suite, 'TestContract:getAsset', ['GLD'])); 33 | expect(payload).to.eql({id: 'GLD', name: 'GOLD_BAR', value: 100, extra: {id: 'EXTRA_ID', value: 50}}); 34 | }); 35 | 36 | it('should update an asset', async function() { 37 | this.timeout(SHORT_STEP); 38 | await utils.invoke(suite, 'TestContract:updateAsset', [JSON.stringify({id: 'GLD', name: 'GOLD_BAR', value: 200, extra: {id: 'EXTRA_ID', value: 100}})]); 39 | const payload = JSON.parse(await utils.query(suite, 'TestContract:getAsset', ['GLD'])); 40 | expect(payload).to.eql({id: 'GLD', name: 'GOLD_BAR', value: 200, extra: {id: 'EXTRA_ID', value: 100}}); 41 | }); 42 | 43 | it('should handle the getMetadata', async function () { 44 | this.timeout(SHORT_STEP); 45 | const payload = JSON.parse(await utils.query(suite, 'org.hyperledger.fabric:GetMetadata')); 46 | 47 | const schema = fs.readFileSync(path.join(__dirname, '../../apis/fabric-contract-api/schema/contract-schema.json')); 48 | 49 | const ajv = new Ajv({schemaId: 'id'}); 50 | ajv.addMetaSchema(require('ajv/lib/refs/json-schema-draft-04.json')); 51 | 52 | if (!ajv.validate(JSON.parse(schema), payload)) { 53 | throw new Error('Expected generated metadata to match the schema'); 54 | } 55 | 56 | const expectedMetadata = fs.readFileSync(path.join(__dirname, '../chaincodes/annotations/src/test_contract/expected-metadata.json')); 57 | expect(payload).to.eql(JSON.parse(expectedMetadata)); 58 | }); 59 | 60 | }); 61 | 62 | }); 63 | -------------------------------------------------------------------------------- /test/fv/clientidentity.js: -------------------------------------------------------------------------------- 1 | /* 2 | # Copyright IBM Corp. All Rights Reserved. 3 | # 4 | # SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 'use strict'; 7 | 8 | const chai = require('chai'); 9 | chai.use(require('chai-as-promised')); 10 | const expect = chai.expect; 11 | const utils = require('./utils'); 12 | const {MED_STEP, LONG_STEP} = utils.TIMEOUTS; 13 | 14 | describe('Chaincode clientidentity', () => { 15 | const suite = 'clientidentity'; 16 | 17 | before(async function () { 18 | this.timeout(LONG_STEP); 19 | 20 | return utils.installAndInstantiate(suite, 'org.mynamespace.clientidentity:instantiate'); 21 | }); 22 | 23 | it('should create an instance of the client identity class', async function () { 24 | this.timeout(MED_STEP); 25 | 26 | const payload = JSON.parse(await utils.query(suite, 'org.mynamespace.clientidentity:clientIdentityInstance', [])); 27 | expect(payload.mspId).to.equal('Org2MSP', 'Test mspId value'); 28 | expect(payload.id).to.equal('x509::/C=US/ST=North Carolina/O=Hyperledger/OU=client/CN=buyer::/C=UK/ST=Hampshire/L=Hursley/O=org2.example.com/CN=ca.org2.example.com', 'Test getID()'); 29 | }); 30 | 31 | it('should be able to check the peer MSPID', async function () { 32 | this.timeout(MED_STEP); 33 | 34 | const payload = JSON.parse(await utils.query(suite, 'org.mynamespace.clientidentity:localMspID', [])); 35 | expect(payload.localMspID).to.equal('Org2MSP', 'Test stub.getMspID()'); 36 | }); 37 | 38 | }); -------------------------------------------------------------------------------- /test/fv/crosschaincode.js: -------------------------------------------------------------------------------- 1 | /* 2 | # Copyright IBM Corp. All Rights Reserved. 3 | # 4 | # SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 'use strict'; 7 | 8 | const chai = require('chai'); 9 | chai.use(require('chai-as-promised')); 10 | const expect = chai.expect; 11 | const utils = require('./utils'); 12 | const {LONG_STEP, LONGEST_STEP} = utils.TIMEOUTS; 13 | 14 | describe('Chaincode crosschaincode', () => { 15 | const suite = 'crosschaincode'; 16 | const suite2 = 'crosschaincode2'; 17 | 18 | before(async function () { 19 | this.timeout(LONG_STEP); 20 | 21 | await utils.installAndInstantiate(suite, 'org.mynamespace.crosschaincode:instantiate'); 22 | await utils.installAndInstantiate(suite2, 'org.mynamespace.crosschaincode2:instantiate'); 23 | 24 | // kick crosschaincode2 on org2 - shouldn't need this! 25 | await utils.query(suite2, 'org.mynamespace.crosschaincode2:getKey', ['key1']); 26 | }); 27 | 28 | describe('Invoke', () => { 29 | 30 | it('should invoke chaincode', async function () { 31 | this.timeout(LONGEST_STEP); 32 | 33 | const payload = await utils.query(suite, 'org.mynamespace.crosschaincode:invokeChaincode', ['getKey', 'key1']); 34 | expect(payload).to.equal('crosschaincode2'); 35 | }); 36 | 37 | it('should throw an error when invoking chaincode', async function () { 38 | this.timeout(LONGEST_STEP); 39 | 40 | const payload = await utils.query(suite, 'org.mynamespace.crosschaincode:invokeChaincodeError', ['getKey']); 41 | expect(payload).to.match(/Incorrect no. of parameters/); 42 | }); 43 | 44 | }); 45 | 46 | }); 47 | -------------------------------------------------------------------------------- /test/fv/crosschaincode2.js: -------------------------------------------------------------------------------- 1 | /* 2 | # Copyright IBM Corp. All Rights Reserved. 3 | # 4 | # SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | 8 | /* 9 | * Mock mocha file to allow for the packed modules to be copied correctly over. 10 | */ -------------------------------------------------------------------------------- /test/fv/events.js: -------------------------------------------------------------------------------- 1 | /* 2 | # Copyright IBM Corp. All Rights Reserved. 3 | # 4 | # SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 'use strict'; 7 | 8 | const chai = require('chai'); 9 | chai.use(require('chai-as-promised')); 10 | const expect = chai.expect; 11 | const utils = require('./utils'); 12 | const {LONG_STEP} = utils.TIMEOUTS; 13 | 14 | describe('Chaincode events', async function () { 15 | const suite = 'events'; 16 | 17 | before(async function () { 18 | this.timeout(LONG_STEP); 19 | 20 | return utils.installAndInstantiate(suite, 'org.mynamespace.events:instantiate'); 21 | }); 22 | 23 | it('should publish an event', async function () { 24 | this.timeout(LONG_STEP); 25 | 26 | const date = new Date().toISOString(); 27 | await utils.invoke(suite, 'org.mynamespace.events:emit', [`my event data @ ${date}`]); 28 | const block = await utils.getLastBlock(); 29 | expect(block.data.data.length).to.equal(1); // only one transaction 30 | const transaction = block.data.data[0]; 31 | const actions = transaction.payload.data.actions; 32 | expect(actions.length).to.equal(1); // only one action 33 | const action = actions[0]; 34 | const proposalResponsePayload = action.payload.action.proposal_response_payload; 35 | const events = proposalResponsePayload.extension.events; 36 | expect(events.chaincode_id).to.equal('events'); 37 | expect(events.event_name).to.equal('myevent'); 38 | const payload = Buffer.from(events.payload, 'base64').toString(); 39 | expect(payload).to.equal(`my event data @ ${date}`); 40 | }); 41 | 42 | }); 43 | -------------------------------------------------------------------------------- /test/fv/ledger.js: -------------------------------------------------------------------------------- 1 | /* 2 | # Copyright IBM Corp. All Rights Reserved. 3 | # 4 | # SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 'use strict'; 7 | 8 | const chai = require('chai'); 9 | chai.use(require('chai-as-promised')); 10 | const expect = chai.expect; 11 | const utils = require('./utils'); 12 | const {SHORT_STEP, MED_STEP, LONG_STEP} = utils.TIMEOUTS; 13 | 14 | describe('Chaincode ledger', () => { 15 | const suite = 'ledger'; 16 | 17 | before(async function () { 18 | this.timeout(LONG_STEP); 19 | 20 | return utils.installAndInstantiate(suite); 21 | }); 22 | 23 | it('should be able to use the ledger API', async function () { 24 | this.timeout(LONG_STEP); 25 | 26 | const payload = await utils.query(suite, 'org.example.ledger:getLedger', ['']); 27 | expect(payload).to.equal('success'); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /test/fv/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fvtests", 3 | "version": "2.5.9", 4 | "description": "fv tests", 5 | "testFabricVersion": "main", 6 | "testFabricThirdParty": "0.4.15", 7 | "docsLatestVersion": "release-1.4", 8 | "engines": { 9 | "node": ">=18" 10 | }, 11 | "engineStrict": true, 12 | "license": "Apache-2.0", 13 | "scripts": { 14 | "hello": "echo test fv project", 15 | "test:fv": "mocha *.js --reporter spec-junit-splitter-mocha-reporter 2>&1", 16 | "build": "" 17 | }, 18 | "dependencies": { 19 | "@sinonjs/referee-sinon": "~5.0.0", 20 | "ajv": "^6.12.2", 21 | "ajv-cli": "^3.2.1", 22 | "chai": "^4.3.4", 23 | "chai-as-promised": "^7.1.1", 24 | "chai-things": "^0.2.0", 25 | "del": "^3.0.0", 26 | "delay": "5.0.0", 27 | "eslint": "^6.6.0", 28 | "fabric-contract-api": "2.5.9", 29 | "fabric-shim": "2.5.9", 30 | "fabric-shim-api": "2.5.9", 31 | "git-rev-sync": "3.0.1", 32 | "gulp": "^4.0.2", 33 | "ip": "^1.1.5", 34 | "istanbul-api": "^1.1.13", 35 | "jsverify": "~0.8.4", 36 | "mocha": "9.1.3", 37 | "mockery": "^2.1.0", 38 | "rewire": "6.0.0", 39 | "sinon": "13.0.1", 40 | "sinon-test": "^2.2.0", 41 | "spec-junit-splitter-mocha-reporter": "1.0.1" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /test/fv/privateData.js: -------------------------------------------------------------------------------- 1 | /* 2 | # Copyright IBM Corp. All Rights Reserved. 3 | # 4 | # SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 'use strict'; 7 | 8 | const chai = require('chai'); 9 | chai.use(require('chai-as-promised')); 10 | const expect = chai.expect; 11 | const utils = require('./utils'); 12 | const {MED_STEP, LONG_STEP} = utils.TIMEOUTS; 13 | 14 | describe('Chaincode privateData', () => { 15 | const suite = 'privateData'; 16 | 17 | before(async function () { 18 | this.timeout(LONG_STEP); 19 | return utils.installAndInstantiate(suite, null, null, true); 20 | }); 21 | 22 | it('should write and read an asset with private data', async function () { 23 | this.timeout(MED_STEP); 24 | const privateData = Buffer.from('privateData').toString('base64'); 25 | await utils.invoke(suite, 'privateDataContract:createAsset', ['1'], `{"privateValue":"${privateData}"}`); 26 | const payload = await utils.query(suite, 'privateDataContract:readAsset', ['1']); 27 | expect(payload).to.eql('{"privateValue":"privateData"}'); 28 | }); 29 | 30 | it('should update an asset with private data', async function () { 31 | this.timeout(MED_STEP); 32 | let privateData = Buffer.from('privateData').toString('base64'); 33 | await utils.invoke(suite, 'privateDataContract:createAsset', ['2'], `{"privateValue":"${privateData}"}`); 34 | privateData = Buffer.from('updatedPrivateData').toString('base64'); 35 | await utils.invoke(suite, 'privateDataContract:updateAsset', ['2'], `{"privateValue":"${privateData}"}`); 36 | const payload = await utils.query(suite, 'privateDataContract:readAsset', ['2']); 37 | expect(payload).to.eql('{"privateValue":"updatedPrivateData"}'); 38 | }); 39 | 40 | it('should delete an asset with private data', async function () { 41 | this.timeout(MED_STEP); 42 | const privateData = Buffer.from('privateData').toString('base64'); 43 | await utils.invoke(suite, 'privateDataContract:createAsset', ['3'], `{"privateValue":"${privateData}"}`); 44 | let payload = await utils.query(suite, 'privateDataContract:readAsset', ['3']); 45 | expect(payload).to.eql('{"privateValue":"privateData"}'); 46 | await utils.invoke(suite, 'privateDataContract:deleteAsset', ['3']); 47 | payload = await utils.query(suite, 'privateDataContract:assetExists', ['3']); 48 | expect(payload).to.eql('false'); 49 | }); 50 | 51 | it('should call purge private data without failing', async function () { 52 | this.timeout(MED_STEP); 53 | const privateData = Buffer.from('privateData').toString('base64'); 54 | await utils.invoke(suite, 'privateDataContract:createAsset', ['4'], `{"privateValue":"${privateData}"}`); 55 | let payload = await utils.query(suite, 'privateDataContract:readAsset', ['4']); 56 | expect(payload).to.eql('{"privateValue":"privateData"}'); 57 | console.log(await utils.invoke(suite, 'privateDataContract:purgeAsset', ['4'])); 58 | payload = await utils.query(suite, 'privateDataContract:assetExists', ['4']); 59 | expect(payload).to.eql('false'); 60 | }); 61 | 62 | }); -------------------------------------------------------------------------------- /test/fv/query.js: -------------------------------------------------------------------------------- 1 | /* 2 | # Copyright IBM Corp. All Rights Reserved. 3 | # 4 | # SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 'use strict'; 7 | 8 | const chai = require('chai'); 9 | chai.use(require('chai-as-promised')); 10 | const expect = chai.expect; 11 | const utils = require('./utils'); 12 | const {MED_INC, LONG_STEP} = utils.TIMEOUTS; 13 | 14 | 15 | describe('Chaincode query', () => { 16 | const suite = 'query'; 17 | before(async function () { 18 | this.timeout(LONG_STEP); 19 | return utils.installAndInstantiate(suite, 'org.mynamespace.query:instantiate'); 20 | }); 21 | 22 | it('should perform an equals query', async function () { 23 | this.timeout(MED_INC); 24 | const query = JSON.stringify({ 25 | selector: { 26 | value: 'value0' 27 | } 28 | }); 29 | const payload = await utils.query(suite, 'org.mynamespace.query:query', [query]); 30 | expect(payload).to.deep.equal(JSON.stringify([{value: 'value0'}])); 31 | }); 32 | 33 | it('should perform an regex query', async function () { 34 | this.timeout(MED_INC); 35 | const query = JSON.stringify({ 36 | selector: { 37 | value: { 38 | $regex: 'value[0-2]' 39 | } 40 | } 41 | }); 42 | const payload = await utils.query(suite, 'org.mynamespace.query:query', [query]); 43 | expect(payload).to.deep.equal(JSON.stringify([ 44 | {value: 'value0'}, 45 | {value: 'value1'}, 46 | {value: 'value2'} 47 | ])); 48 | }); 49 | }); 50 | -------------------------------------------------------------------------------- /tools/getEdgeDocker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Copyright IBM Corp. All Rights Reserved. 4 | # 5 | # SPDX-License-Identifier: Apache-2.0 6 | # 7 | set -euo pipefail 8 | 9 | version=${FABRIC_VERSION:-2.5} 10 | docker_registry=docker.io 11 | 12 | for image in peer orderer baseos ccenv tools; do 13 | image_name="hyperledger/fabric-${image}" 14 | image_pull="${docker_registry}/${image_name}:${version}" 15 | docker pull -q "${image_pull}" 16 | docker tag "${image_pull}" "${image_name}" 17 | done 18 | 19 | docker pull -q couchdb:latest 20 | docker pull -q "${docker_registry}/hyperledger/fabric-ca:1.5" 21 | docker tag "${docker_registry}/hyperledger/fabric-ca:1.5" hyperledger/fabric-ca 22 | -------------------------------------------------------------------------------- /tools/logfiles.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | # Grab the current directory 5 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )"/.. && pwd )" 6 | esc=$(printf '\033') 7 | 8 | files=$(find ${DIR} -name "*.build*.log") 9 | for LOG in ${files}; do 10 | realpath -q --relative-to="$(pwd)" ${LOG} | sed "s,.*error.*,${esc}[91m&${esc}[0m," 11 | done 12 | 13 | -------------------------------------------------------------------------------- /tools/monitordocker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This script uses the logspout and http stream tools to let you watch the docker containers 4 | # in action. 5 | # 6 | # More information at https://github.com/gliderlabs/logspout/tree/master/httpstream 7 | 8 | if [ -z "$1" ]; then 9 | DOCKER_NETWORK=basicnetwork_basic 10 | else 11 | DOCKER_NETWORK="$1" 12 | fi 13 | 14 | echo Starting monitoring on all containers on the network ${DOCKER_NETWORK} 15 | 16 | docker kill logspout 2> /dev/null 1>&2 || true 17 | docker rm logspout 2> /dev/null 1>&2 || true 18 | 19 | docker run -d --name="logspout" \ 20 | --volume=/var/run/docker.sock:/var/run/docker.sock \ 21 | --publish=127.0.0.1:8000:80 \ 22 | --network ${DOCKER_NETWORK} \ 23 | gliderlabs/logspout 24 | sleep 3 25 | curl http://127.0.0.1:8000/logs 26 | -------------------------------------------------------------------------------- /tools/scripts/changelog.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright IBM Corp. All Rights Reserved. 4 | # 5 | # SPDX-License-Identifier: Apache-2.0 6 | # 7 | set -ev 8 | 9 | PREVIOUS_TAG=$1 10 | NEW_VERSION=$2 11 | 12 | : ${PREVIOUS_TAG:?} 13 | : ${NEW_VERSION:?} 14 | 15 | echo "## ${NEW_VERSION}\n$(date)" >> CHANGELOG.new 16 | echo "" >> CHANGELOG.new 17 | git log ${PREVIOUS_TAG}..HEAD --oneline | grep -v Merge | sed -e "s/\[\{0,1\}\(FAB[^0-9]*-[0-9]*\)\]\{0,1\}/\[\1\](https:\/\/jira.hyperledger.org\/browse\/\1\)/" -e "s/\([0-9|a-z]*\)/* \[\1\](https:\/\/github.com\/hyperledger\/fabric-chaincode-node\/commit\/\1)/" >> CHANGELOG.new 18 | echo "" >> CHANGELOG.new 19 | cat CHANGELOG.md >> CHANGELOG.new 20 | mv -f CHANGELOG.new CHANGELOG.md 21 | -------------------------------------------------------------------------------- /tools/scripts/gittag.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Exit on first error, print all commands. 4 | set -e 5 | set -o pipefail 6 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )" 7 | 8 | # set to echo to do processing but not the git commands 9 | #DRYRUN=echo 10 | 11 | # release name 12 | RELEASE=release-1.4 13 | 14 | function abort { 15 | echo "!! Exiting shell script" 16 | echo "!!" "$1" 17 | exit -1 18 | } 19 | 20 | VERSION=$(jq '.version' ${DIR}/package.json | sed -r "s/\"([0-9]?[0-9]\.[0-9]?[0-9]\.[0-9]?[0-9]).*/\1/") 21 | 22 | echo New version string will be v${VERSION} 23 | 24 | # do the release notes for this new version exist? 25 | if [[ -f "${DIR}/release_notes/v${VERSION}.txt" ]]; then 26 | echo "Release notes exist, hope they make sense!" 27 | else 28 | abort "No releases notes under the file ${DIR}/release_notes/v${NEW_VERSION}.txt exist"; 29 | fi 30 | 31 | 32 | 33 | 34 | ${DRYRUN} git checkout "${RELEASE}" 35 | ${DRYRUN} git pull 36 | ${DRYRUN} git tag -a "v${VERSION}" `git log -n 1 --pretty=oneline | head -c7` -F release_notes/"v${VERSION}".txt 37 | ${DRYRUN} git push origin v${VERSION} HEAD:refs/heads/${RELEASE} -------------------------------------------------------------------------------- /tools/scripts/multiarch.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright IBM Corp. All Rights Reserved. 4 | # 5 | # SPDX-License-Identifier: Apache-2.0 6 | # 7 | 8 | usage() { 9 | echo "Usage: $0 " 10 | echo " and credentials for the repository" 11 | echo "ENV:" 12 | echo " NS=$NS" 13 | echo " VERSION=$VERSION" 14 | echo " TWO_DIGIT_VERSION=$TWO_DIGIT_VERSION" 15 | exit 1 16 | } 17 | 18 | missing() { 19 | echo "Error: some image(s) missing from registry" 20 | echo "ENV:" 21 | echo " NS=$NS" 22 | echo " VERSION=$VERSION" 23 | echo " TWO_DIGIT_VERSION=$TWO_DIGIT_VERSION" 24 | exit 1 25 | } 26 | 27 | failed() { 28 | echo "Error: multiarch manifest push failed" 29 | echo "ENV:" 30 | echo " NS=$NS" 31 | echo " VERSION=$VERSION" 32 | echo " TWO_DIGIT_VERSION=$TWO_DIGIT_VERSION" 33 | exit 1 34 | } 35 | 36 | USER=${1:-nobody} 37 | PASSWORD=${2:-nohow} 38 | NS=${NS:-hyperledger} 39 | VERSION=${BASE_VERSION:-1.3.0} 40 | TWO_DIGIT_VERSION=${TWO_DIGIT_VERSION:-1.3} 41 | 42 | if [ "$#" -ne 2 ]; then 43 | usage 44 | fi 45 | 46 | # verify that manifest-tool is installed and found on PATH 47 | which manifest-tool 48 | if [ "$?" -ne 0 ]; then 49 | echo "manifest-tool not installed or not found on PATH" 50 | exit 1 51 | fi 52 | 53 | IMAGES="fabric-nodeenv" 54 | 55 | # check that all images have been published 56 | for image in ${IMAGES}; do 57 | docker pull ${NS}/${image}:amd64-${VERSION} || missing 58 | docker pull ${NS}/${image}:s390x-${VERSION} || missing 59 | done 60 | 61 | # push the multiarch manifest and tag with just $VERSION and 'latest' 62 | for image in ${IMAGES}; do 63 | manifest-tool --username ${USER} --password ${PASSWORD} push from-args\ 64 | --platforms linux/amd64,linux/s390x --template "${NS}/${image}:ARCH-${VERSION}"\ 65 | --target "${NS}/${image}:${VERSION}" 66 | # manifest-tool --username ${USER} --password ${PASSWORD} push from-args\ 67 | # --platforms linux/amd64,linux/s390x --template "${NS}/${image}:ARCH-${VERSION}"\ 68 | # --target "${NS}/${image}:latest" 69 | manifest-tool --username ${USER} --password ${PASSWORD} push from-args\ 70 | --platforms linux/amd64,linux/s390x --template "${NS}/${image}:ARCH-${VERSION}"\ 71 | --target "${NS}/${image}:${TWO_DIGIT_VERSION}" 72 | done 73 | 74 | # test that manifest is working as expected 75 | for image in ${IMAGES}; do 76 | docker pull ${NS}/${image}:${VERSION} || failed 77 | docker pull ${NS}/${image}:${TWO_DIGIT_VERSION} || failed 78 | # docker pull ${NS}/${image}:latest || failed 79 | done 80 | 81 | echo "Successfully pushed multiarch manifest" 82 | exit 0 83 | -------------------------------------------------------------------------------- /tools/scripts/startFabric.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This starts up a Fabric Network for use by the integration tests 4 | # PLEASE NOTE - this pulls the latest 'edge' version of the binaries 5 | # Plans in place to update this a better version and to use the LTS 2.5 binaries once released 6 | 7 | # Exit on first error, print all commands. 8 | set -xeo pipefail 9 | 10 | ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/../.." && pwd )" 11 | 12 | pushd "${ROOT_DIR}" 13 | rm -rf "${ROOT_DIR}/fabric-samples" 14 | 15 | curl -sSLO https://raw.githubusercontent.com/hyperledger/fabric/main/scripts/install-fabric.sh \ 16 | && chmod +x install-fabric.sh \ 17 | && ./install-fabric.sh -f 2.5.0 samples 18 | 19 | pushd "${ROOT_DIR}/fabric-samples" 20 | 21 | find "${ROOT_DIR}/fabric-samples" -name configtx.yaml -exec yq -i '.Capabilities.Application.V2_5 = true | del(.Capabilities.Application.V2_0)' {} \; 22 | 23 | # get the edge binaries - these are the version 2.5 24 | # the latest docker images are pulled elsewhere 25 | curl -sSL https://hyperledger.jfrog.io/artifactory/fabric-binaries/hyperledger-fabric-ca-linux-amd64-2.5-stable.tar.gz | tar -xz 26 | curl -sSL https://hyperledger.jfrog.io/artifactory/fabric-binaries/hyperledger-fabric-linux-amd64-2.5-stable.tar.gz | tar -xz 27 | 28 | 29 | pushd "${ROOT_DIR}/fabric-samples/test-network" 30 | ./network.sh down 31 | ./network.sh up createChannel -ca -s couchdb 32 | 33 | # unwind the stack 34 | popd 35 | popd 36 | popd -------------------------------------------------------------------------------- /tools/scripts/updateversions.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -eo pipefail 4 | 5 | if [ -z "$1" ]; then 6 | echo "Need to have the first arg set to the new package.json version" 7 | exit 1 8 | fi 9 | 10 | NEW_VERSION="$1" 11 | echo "Setting new version to '${NEW_VERSION}'" 12 | 13 | DEPENDENCIES=( fabric-contract-api fabric-shim-api fabric-shim fabric-ledger ) 14 | 15 | updatePackageVersion() { 16 | npm --allow-same-version --no-git-tag-version version "$1" 17 | for dependency in "${DEPENDENCIES[@]}"; do 18 | updateDependencyVersion "${dependency}" "$1" 19 | done 20 | } 21 | 22 | updateDependencyVersion() { 23 | local packageJson 24 | packageJson=$(node -e "const pkg = require('./package.json'); if (pkg.dependencies?.['$1']) pkg.dependencies['$1'] = '$2'; console.log(JSON.stringify(pkg, undefined, 2))") 25 | echo "${packageJson}" > package.json 26 | } 27 | 28 | while read -r PACKAGE; do 29 | echo "Updating '${PACKAGE}'" 30 | ( cd "$(dirname "${PACKAGE}")" && updatePackageVersion "${NEW_VERSION}" ) 31 | done <<< "$(find . -type d \( -name node_modules -o -name common -o -name tools \) -prune -o -type f -name package.json -print)" 32 | 33 | MAJOR_MINOR=$(cut -d. -f-2 <<< "${NEW_VERSION}") 34 | 35 | echo "Please also check these files containing ${MAJOR_MINOR}.n" 36 | # NB - the grep regexp syntax is a little different 37 | MAJOR_MINOR_REGEX="${MAJOR_MINOR/./\.}\.\?[0-9]" 38 | find ./test \ 39 | -type d \( -name node_modules -o -name '.*' \) -prune \ 40 | -o -type f -name package.json -prune \ 41 | -o -type f \( -name '*.js' -o -name '*.json' \) -exec grep "${MAJOR_MINOR_REGEX}" {} + 42 | -------------------------------------------------------------------------------- /tools/toolchain/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright contributors to Hyperledger Fabric. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | const {shell} = require('./shell/cmd'); 8 | const {getTLSArgs, getPeerAddresses} = require('./utils'); 9 | 10 | module.exports.shell = shell; 11 | 12 | module.exports.getTLSArgs = getTLSArgs; 13 | module.exports.getPeerAddresses = getPeerAddresses; 14 | -------------------------------------------------------------------------------- /tools/toolchain/network/crypto-material/crypto-config.yaml: -------------------------------------------------------------------------------- 1 | # Copyright IBM Corp. All Rights Reserved. 2 | # 3 | # SPDX-License-Identifier: Apache-2.0 4 | # 5 | 6 | # --------------------------------------------------------------------------- 7 | # "OrdererOrgs" - Definition of organizations managing orderer nodes 8 | # --------------------------------------------------------------------------- 9 | OrdererOrgs: 10 | # --------------------------------------------------------------------------- 11 | # Orderer 12 | # --------------------------------------------------------------------------- 13 | - Name: Orderer 14 | Domain: example.com 15 | # --------------------------------------------------------------------------- 16 | # "Specs" - See PeerOrgs below for complete description 17 | # --------------------------------------------------------------------------- 18 | Specs: 19 | - Hostname: orderer 20 | # --------------------------------------------------------------------------- 21 | # "PeerOrgs" - Definition of organizations managing peer nodes 22 | # --------------------------------------------------------------------------- 23 | PeerOrgs: 24 | # --------------------------------------------------------------------------- 25 | # Org1 26 | # --------------------------------------------------------------------------- 27 | - Name: Org1 28 | Domain: org1.example.com 29 | Template: 30 | Count: 2 31 | Users: 32 | Count: 1 33 | # --------------------------------------------------------------------------- 34 | # Org2: See "Org1" for full specification 35 | # --------------------------------------------------------------------------- 36 | - Name: Org2 37 | Domain: org2.example.com 38 | Template: 39 | Count: 2 40 | Users: 41 | Count: 1 42 | -------------------------------------------------------------------------------- /tools/toolchain/network/crypto-material/rename_sk.sh: -------------------------------------------------------------------------------- 1 | # Rename the key files we use to be key.pem instead of a uuid 2 | BASEDIR=$(dirname "$0") 3 | 4 | chmod -R og+rx ${BASEDIR} 5 | 6 | for KEY in $(find ${BASEDIR}/crypto-config -type f -name "*_sk"); do 7 | KEY_DIR=$(dirname ${KEY}) 8 | mv ${KEY} ${KEY_DIR}/key.pem 9 | done -------------------------------------------------------------------------------- /tools/toolchain/network/docker-compose/docker-compose-cli.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # Licensed under the Apache License, Version 2.0 (the "License"); 3 | # you may not use this file except in compliance with the License. 4 | # You may obtain a copy of the License at 5 | # 6 | # http://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, 10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | # See the License for the specific language governing permissions and 12 | # limitations under the License. 13 | # 14 | 15 | services: 16 | clinopeer: 17 | container_name: cli 18 | image: hyperledger/fabric-tools 19 | tty: true 20 | environment: 21 | - GOPATH=/opt/gopath 22 | - FABRIC_CFG_PATH=/etc/hyperledger/config 23 | 24 | # LOGGING SETTINGS 25 | - FABRIC_LOGGING_SPEC=INFO 26 | 27 | working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer 28 | command: /bin/bash 29 | volumes: 30 | - /var/run/:/host/var/run/ 31 | - ../crypto-material:/etc/hyperledger/config/ 32 | - ../../../../test/chaincodes/privateData/collection-config:/collection-config 33 | -------------------------------------------------------------------------------- /tools/toolchain/network/external/build: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright Hitachi America, Ltd. All Rights Reserved. 4 | # 5 | # SPDX-License-Identifier: Apache-2.0 6 | 7 | set -e 8 | 9 | SOURCE="$1" 10 | OUTPUT="$3" 11 | 12 | if [ ! -f "${SOURCE}/connection.json" ]; then 13 | echo "Error: ${SOURCE}/connection.json not found" 1>&2 14 | exit 1 15 | fi 16 | 17 | cp "${SOURCE}/connection.json" "${OUTPUT}/connection.json" 18 | 19 | if [ -d "${SOURCE}/metadata" ]; then 20 | cp -a ${SOURCE}/metadata ${OUTPUT}/metadata 21 | fi 22 | 23 | exit 0 24 | -------------------------------------------------------------------------------- /tools/toolchain/network/external/detect: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright Hitachi America, Ltd. All Rights Reserved. 4 | # 5 | # SPDX-License-Identifier: Apache-2.0 6 | 7 | set -e 8 | 9 | METADIR="$2" 10 | 11 | if [ `jq -r .type "${METADIR}/metadata.json"` = "external" ]; then 12 | exit 0 13 | fi 14 | 15 | exit 1 16 | -------------------------------------------------------------------------------- /tools/toolchain/network/external/release: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright Hitachi America, Ltd. All Rights Reserved. 4 | # 5 | # SPDX-License-Identifier: Apache-2.0 6 | 7 | set -e 8 | 9 | BUILD="$1" 10 | RELEASE="$2" 11 | 12 | if [ -d "${BUILD}/metadata" ]; then 13 | cp -a "${BUILD}/metadata/*" "${RELEASE}/" 14 | fi 15 | 16 | if [ -f "${BUILD}/connection.json" ]; then 17 | mkdir -p "${RELEASE}/chaincode/server" 18 | cp "${BUILD}/connection.json" "${RELEASE}/chaincode/server" 19 | 20 | # TODO: TLS 21 | 22 | exit 0 23 | fi 24 | -------------------------------------------------------------------------------- /tools/toolchain/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "toolchain", 3 | "version": "1.0.0-dev", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "", 8 | "startfabric": "gulp startFabric", 9 | "stopfabric": "gulp stopFabric" 10 | }, 11 | "author": "", 12 | "license": "Apache-2.0", 13 | "dependencies": { 14 | "delay": "5.0.0", 15 | "git-rev-sync": "3.0.1", 16 | "gulp-debug": "~4.0.0", 17 | "gulp-eslint": "~6.0.0", 18 | "gulp-rename": "~2.0.0", 19 | "gulp-shell": "~0.7.1", 20 | "merge-stream": "~2.0.0", 21 | "npm-cli-login": "~0.1.1", 22 | "ip": "^1.1.5", 23 | "gulp-cli": "2.3.0" 24 | }, 25 | "devDependencies": { 26 | "gulp": "^4.0.2" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /tools/toolchain/shell/cmd.js: -------------------------------------------------------------------------------- 1 | /* 2 | # Copyright IBM Corp. All Rights Reserved. 3 | # 4 | # SPDX-License-Identifier: Apache-2.0 5 | */ 6 | const spawn = require('child_process').spawn; 7 | 8 | // A general purpose structure that can be used for any command. 9 | // This defines the important 'spawn' command. This executes the command 10 | // with the arguments that have been specified. 11 | // It is set to inherit the environment variables, uses the default sell, and inherits the 12 | // stdio/stderr streams. (Inheriting means that the formating colour, etc is maintained) 13 | // 14 | // spawn() MUST be the last item chained sequence 15 | // 16 | // It also blanks the arguments supplied, so the instance of the cmd can be reused 17 | // It returns a promise that is resolved when the exit code is 0, and rejected for any other code 18 | const _cmd = { 19 | cmd: '', 20 | args: [], 21 | stdoutstr: [], 22 | 23 | // can override the cwd 24 | spawn: function (cwd = process.cwd()) { 25 | const promise = new Promise((resolve, reject) => { 26 | const _name = this.toString(); 27 | // eslint-disable-next-line no-console 28 | console.log(`spawning:: ${_name} in ${cwd}`); 29 | const call = spawn(this.cmd, this.args, {env: process.env, shell: true, stdio: ['inherit', 'pipe', 'inherit'], cwd}); 30 | this.args = []; 31 | this.stdoutstr = []; 32 | call.on('exit', (code) => { 33 | // eslint-disable-next-line no-console 34 | console.log(`spawning:: ${_name} code::${code}`); 35 | if (code === 0) { 36 | resolve(0); 37 | } else { 38 | reject(code); 39 | } 40 | }); 41 | call.stdout.on('data', (data) => { 42 | const s = data.toString('utf8'); 43 | console.log(s.slice(0, s.length - 1)); 44 | this.stdoutstr.push(s); 45 | }); 46 | return call; 47 | }); 48 | 49 | return promise; 50 | }, 51 | toString: function () { 52 | return `${this.cmd} ${this.args.join(' ')}`; 53 | } 54 | }; 55 | 56 | 57 | const newCmd = (newcmd) => { 58 | // duplicate the generic cmd object 59 | const _new = Object.create(_cmd); 60 | _new.cmd = newcmd; 61 | _new.args = []; 62 | return _new; 63 | }; 64 | 65 | module.exports = _cmd; 66 | module.exports.newCmd = newCmd; 67 | module.exports.shell = async (cmds) => { 68 | const retvals = []; 69 | for (const c of cmds) { 70 | const cmd = newCmd(c); 71 | await cmd.spawn(); 72 | retvals.push(cmd.stdoutstr.join(' ')); 73 | } 74 | return retvals; 75 | 76 | }; -------------------------------------------------------------------------------- /tools/toolchain/shell/docker.js: -------------------------------------------------------------------------------- 1 | /* 2 | # Copyright IBM Corp. All Rights Reserved. 3 | # 4 | # SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | const _cmd = require('./cmd.js'); 8 | 9 | 10 | // Function to create a new instance of the npm command. 11 | // This sets up the run, test, and prefix options 12 | // If you wish to add 'scripts' eg build compile etc, the useScript() 13 | // function can be used. 14 | function docker () { 15 | 16 | // duplicate the generic cmd object 17 | const _docker = Object.create(_cmd); 18 | _docker.cmd = 'docker'; 19 | _docker.args = []; 20 | 21 | // function to use to add extra scripts 22 | // npm.useScript('compile','build') 23 | _docker.useScript = (...scripts) => { 24 | scripts.forEach((m) => { 25 | Object.defineProperty(_docker, m, { 26 | get: function () { 27 | this.args.push(m); 28 | return this; 29 | } 30 | }); 31 | }); 32 | return this; 33 | }; 34 | 35 | return _docker; 36 | } 37 | 38 | // default export is the npm function to create instances of the npm command 39 | module.exports = docker; 40 | -------------------------------------------------------------------------------- /tools/toolchain/shell/npm.js: -------------------------------------------------------------------------------- 1 | /* 2 | # Copyright IBM Corp. All Rights Reserved. 3 | # 4 | # SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | const _cmd = require('./cmd.js'); 8 | 9 | 10 | // Function to create a new instance of the npm command. 11 | // This sets up the run, test, and prefix options 12 | // If you wish to add 'scripts' eg build compile etc, the useScript() 13 | // function can be used. 14 | function npm () { 15 | 16 | // duplicate the generic cmd object 17 | const _npm = Object.create(_cmd); 18 | _npm.cmd = 'npm'; 19 | _npm.args = []; 20 | 21 | // no-args 22 | const noargs = ['run', 'test', 'build', 'start', 'install']; 23 | noargs.forEach((m) => { 24 | Object.defineProperty(_npm, m, { 25 | get: function () { 26 | this.args.push(m); 27 | return this; 28 | } 29 | }); 30 | }); 31 | 32 | // single-arg fn 33 | ['prefix'].forEach((m) => { 34 | Object.defineProperty(_npm, m, { 35 | value: function (p) { 36 | this.args.push(`--${m}`, p); 37 | return this; 38 | } 39 | }); 40 | 41 | }); 42 | 43 | // function to use to add extra scripts 44 | // npm.useScript('compile','build') 45 | _npm.useScript = (...scripts) => { 46 | scripts.forEach((m) => { 47 | Object.defineProperty(_npm, m, { 48 | get: function () { 49 | this.args.push(m); 50 | return this; 51 | } 52 | }); 53 | }); 54 | return this; 55 | }; 56 | 57 | return _npm; 58 | } 59 | 60 | // default export is the npm function to create instances of the npm command 61 | module.exports = npm; 62 | // singleton npm instance 63 | module.exports.npm = npm(); 64 | 65 | -------------------------------------------------------------------------------- /tools/toolchain/test/inversionOfControl.js: -------------------------------------------------------------------------------- 1 | /* 2 | # Copyright IBM Corp. All Rights Reserved. 3 | # 4 | # SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | // remove once inversion of control in fabric as other tests will cover this 8 | 9 | /* 10 | # Copyright IBM Corp. All Rights Reserved. 11 | # 12 | # SPDX-License-Identifier: Apache-2.0 13 | */ 14 | 'use strict'; 15 | /* eslint-disable no-console */ 16 | 17 | const gulp = require('gulp'); 18 | 19 | const util = require('util'); 20 | 21 | const childProcess = require('child_process'); 22 | const exec = childProcess.exec; 23 | 24 | const peerAddress = require('../../test/constants').peerAddress; 25 | 26 | require('./scenario'); 27 | 28 | gulp.task('inv-startup-chaincode', async (done) => { 29 | const script = util.format('docker exec org1_cli bash -c "cd %s; npm start -- --peer.address %s --chaincode-id-name %s --module-path %s"', 30 | // the /etc/hyperledger/config has been mapped to the 31 | // basic-network folder in the test setup for the CLI docker 32 | '/opt/gopath/src/github.com/chaincode/scenario/node_modules/fabric-shim', 33 | peerAddress, 34 | 'mysmartcontract:v0', 35 | '/opt/gopath/src/github.com/chaincode/scenario'); 36 | 37 | try { 38 | await new Promise((resolve, reject) => { 39 | const child = exec(script); 40 | 41 | child.stdout.on('data', (data) => { 42 | if (Buffer.isBuffer(data)) { 43 | data = data.toString(); 44 | } 45 | 46 | if (data.includes('Successfully established communication with peer node')) { 47 | resolve(child); 48 | } 49 | }); 50 | 51 | child.stderr.on('data', (data) => { 52 | console.log('[STR] stderr "%s"', String(data)); 53 | }); 54 | 55 | child.on('close', (code, signal) => { 56 | reject('Starting up chaincode via CLI failed'); 57 | }); 58 | }); 59 | } catch (err) { 60 | done(err); 61 | } 62 | }); 63 | 64 | /** 65 | * Invoke all the smart contract functions - steals some commands from scenario as uses same contract 66 | */ 67 | 68 | gulp.task('invokeAllFnsInvCtrl', gulp.series( 69 | [ 70 | 'cli-install-chaincode', 71 | 72 | // Start chaincode 73 | 'inv-startup-chaincode', 74 | 75 | // install 76 | 'st-install_chaincode', 77 | 78 | // instantiate 79 | 'st-instantiate_chaincode', 80 | 'delay', 81 | 82 | // Check it didnt make docker images 83 | 'check-docker', 84 | 85 | // invoke all functions 86 | 'invoke_functions', 87 | 88 | // query the functions 89 | 'query_functions', 90 | 91 | // stop chaincode 92 | 'stop-cli-running-chaincode', 93 | 94 | 'dm-clean-up-chaincode' 95 | ] 96 | )); 97 | 98 | gulp.task('test-scenario-invctrl', gulp.series('invokeAllFnsInvCtrl')); 99 | -------------------------------------------------------------------------------- /tools/toolchain/utils.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright contributors to Hyperledger Fabric. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | const path = require('path'); 8 | 9 | const ordererCA = '/test-network/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem'; 10 | const org1CA = '/etc/hyperledger/config/crypto-config/peerOrganizations/org1.example.com/tlsca/tlsca.org1.example.com-cert.pem'; 11 | const org2CA = '/etc/hyperledger/config/crypto-config/peerOrganizations/org2.example.com/tlsca/tlsca.org2.example.com-cert.pem'; 12 | const dir = path.join(__dirname, '..', '..', 'fabric-samples'); 13 | 14 | const tls = process.env.TLS && process.env.TLS.toLowerCase() === 'true' ? true : false; 15 | 16 | exports.tls = tls; 17 | 18 | exports.getTLSArgs = () => { 19 | return `--tls true --cafile ${dir}` + ordererCA; 20 | }; 21 | 22 | exports.getPeerAddresses = () => { 23 | if (tls) { 24 | return '--peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles ' + org1CA + 25 | ' --peerAddresses peer0.org2.example.com:8051 --tlsRootCertFiles ' + org2CA; 26 | } else { 27 | return '--peerAddresses peer0.org1.example.com:7051' + 28 | ' --peerAddresses peer0.org2.example.com:8051'; 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /tools/toolchain/verdaccio/config.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # This is the config file used for the docker images. 3 | # It allows all users to do anything, so don't use it on production systems. 4 | # 5 | # Do not configure host and port under `listen` in this file 6 | # as it will be ignored when using docker. 7 | # see https://verdaccio.org/docs/en/docker#docker-and-custom-port-configuration 8 | # 9 | # Look here for more config file examples: 10 | # https://github.com/verdaccio/verdaccio/tree/master/conf 11 | # 12 | 13 | # path to a directory with all packages 14 | storage: /verdaccio/storage/data 15 | # path to a directory with plugins to include 16 | plugins: /verdaccio/plugins 17 | 18 | web: 19 | # WebUI is enabled as default, if you want disable it, just uncomment this line 20 | #enable: false 21 | title: Verdaccio 22 | # comment out to disable gravatar support 23 | # gravatar: false 24 | # by default packages are ordercer ascendant (asc|desc) 25 | # sort_packages: asc 26 | 27 | auth: 28 | htpasswd: 29 | file: /verdaccio/storage/htpasswd 30 | # Maximum amount of users allowed to register, defaults to "+infinity". 31 | # You can set this to -1 to disable registration. 32 | # max_users: 1000 33 | 34 | security: 35 | api: 36 | jwt: 37 | sign: 38 | expiresIn: 60d 39 | notBefore: 1 40 | web: 41 | sign: 42 | expiresIn: 7d 43 | notBefore: 1 44 | 45 | # a list of other known repositories we can talk to 46 | uplinks: 47 | npmjs: 48 | url: https://registry.npmjs.org/ 49 | 50 | packages: 51 | '@*/*': 52 | # scoped packages 53 | access: $all 54 | publish: $all 55 | unpublish: $all 56 | proxy: npmjs 57 | 58 | 'fabric-*': 59 | access: $all 60 | publish: $all 61 | unpublish: $all 62 | 63 | '**': 64 | # allow all users (including non-authenticated users) to read and 65 | # publish all packages 66 | # 67 | # you can specify usernames/groupnames (depending on your auth plugin) 68 | # and three keywords: "$all", "$anonymous", "$authenticated" 69 | access: $all 70 | 71 | # allow all known users to publish/publish packages 72 | # (anyone can register by default, remember?) 73 | publish: $all 74 | unpublish: $all 75 | 76 | # if package is not available locally, proxy requests to 'npmjs' registry 77 | proxy: npmjs 78 | 79 | middlewares: 80 | audit: 81 | enabled: true 82 | 83 | # log settings 84 | logs: 85 | - { type: stdout, format: pretty, level: http } 86 | #- {type: file, path: verdaccio.log, level: info} 87 | -------------------------------------------------------------------------------- /tools/toolchain/verdaccio/index.js: -------------------------------------------------------------------------------- 1 | /* 2 | # Copyright IBM Corp. All Rights Reserved. 3 | # 4 | # SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | 'use strict'; 8 | 9 | const gulp = require('gulp'); 10 | const { shell: runcmds } = require('../shell/cmd'); 11 | const util = require('util'); 12 | const path = require('path'); 13 | const ip = require('ip'); 14 | 15 | // Install from the dirs for use within the development context 16 | const installDir = (commands) =>{ 17 | 18 | const npm_packages = [{ category: 'apis', name: 'fabric-contract-api' }, 19 | { category: 'apis', name: 'fabric-shim-api' }, 20 | { category: 'libraries', name: 'fabric-ledger' }, 21 | { category: 'libraries', name: 'fabric-shim' }]; 22 | 23 | 24 | for (const npm_package of npm_packages) { 25 | const packageJSON = require(`../../../${npm_package.category}/${npm_package.name}/package.json`); 26 | const npm_tag = packageJSON.tag; 27 | const modulepath = path.resolve(`../../../${npm_package.category}/${npm_package.name}/`); 28 | commands.push(util.format(`npm publish --registry http://${ip.address()}:4873 %s --tag %s`, modulepath, npm_tag)); 29 | commands.push(util.format(`npm view --registry http://${ip.address()}:4873 %s`, npm_package.name)); 30 | } 31 | 32 | return commands; 33 | } 34 | 35 | // Install from a set of prebuild tgz for use within the pipline 36 | const installTGZ = (commands) =>{ 37 | 38 | const npm_packages = [{ category: 'apis', name: 'fabric-contract-api' }, 39 | { category: 'apis', name: 'fabric-shim-api' }, 40 | { category: 'libraries', name: 'fabric-ledger' }, 41 | { category: 'libraries', name: 'fabric-shim' }]; 42 | 43 | 44 | for (const npm_package of npm_packages) { 45 | const packageJSON = require(`../../../${npm_package.category}/${npm_package.name}/package.json`); 46 | const npm_tag = packageJSON.tag; 47 | const name = `${npm_package.name}-${packageJSON.version}.tgz`; 48 | commands.push(util.format(`npm publish --registry http://${ip.address()}:4873 ../../../build/%s --tag %s`, name, npm_tag)); 49 | commands.push(util.format(`npm view --registry http://${ip.address()}:4873 %s`, npm_package.name)); 50 | } 51 | 52 | 53 | return commands; 54 | } 55 | 56 | 57 | const verdaccioStart = async () => { 58 | let commands = [ 59 | 'docker rm -f verdaccio || true', 60 | util.format('docker run -d -p 4873:4873 -v %s/config.yaml:/verdaccio/conf/config.yaml --name verdaccio verdaccio/verdaccio', __dirname), 61 | 'sleep 5', // verdaccio takes a while to start 62 | `npm config delete //${ip.address()}:4873/:_authToken`, 63 | `npm-cli-login -u testuser -p testpass -e testuser@example.org -r http://${ip.address()}:4873`, 64 | 'sleep 5' // avoid "jwt not active" error 65 | ]; 66 | 67 | 68 | let inPipeline = process.env.PIPELINE_WORKSPACE || false; 69 | 70 | if (inPipeline){ 71 | commands = installTGZ(commands); 72 | } else { 73 | commands = installDir(commands); 74 | } 75 | 76 | await runcmds(commands); 77 | }; 78 | 79 | const verdaccioStop = async () => { 80 | const commands = [ 81 | util.format('docker rm -f verdaccio || true') 82 | ]; 83 | await runcmds(commands); 84 | }; 85 | 86 | exports.start = verdaccioStart; 87 | exports.stop = verdaccioStop; --------------------------------------------------------------------------------