├── .eslintrc.yml ├── .gitignore ├── LICENSE ├── README.md ├── index.js ├── lib └── logic.js ├── models └── com.genxas.coin.cto ├── package.json ├── permissions.acl ├── queries.qry ├── start-api.sh └── test └── logic.js /.eslintrc.yml: -------------------------------------------------------------------------------- 1 | env: 2 | node: true 3 | mocha: true 4 | extends: 'eslint:recommended' 5 | parserOptions: 6 | sourceType: 7 | - script 8 | globals: 9 | getFactory: true 10 | getSerializer: true 11 | getAssetRegistry: true 12 | getParticipantRegistry: true 13 | getCurrentParticipant: true 14 | post: true 15 | emit: true 16 | rules: 17 | indent: 18 | - error 19 | - 4 20 | linebreak-style: 21 | - error 22 | - unix 23 | quotes: 24 | - error 25 | - single 26 | semi: 27 | - error 28 | - always 29 | no-unused-vars: 30 | - 0 31 | - args: none 32 | no-console: off 33 | curly: error 34 | eqeqeq: error 35 | no-throw-literal: error 36 | strict: error 37 | dot-notation: error 38 | no-tabs: error 39 | no-trailing-spaces: error 40 | no-useless-call: error 41 | no-with: error 42 | operator-linebreak: error 43 | require-jsdoc: 44 | - error 45 | - require: 46 | ClassDeclaration: true 47 | MethodDefinition: true 48 | FunctionDeclaration: true 49 | yoda: error 50 | no-confusing-arrow: 2 51 | no-constant-condition: 2 52 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | composer-logs/ 2 | 3 | *.card 4 | *.bna 5 | 6 | /node_modules 7 | package-lock.json -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Genxas 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Hyperledger Composer Coin Sample Network 2 | 3 | Coin sample network on Hyperledger Fabric 4 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Genxas/hyperledger-composer-coin-network/7e5990385ee91ce65436615ff2a423d137b4579a/index.js -------------------------------------------------------------------------------- /lib/logic.js: -------------------------------------------------------------------------------- 1 | function onDepositCoin(transaction) { 2 | validateAmount(transaction.amount) 3 | 4 | var vault = transaction.vault 5 | vault.amount += transaction.amount 6 | 7 | var newTransaction = getFactory().newConcept('com.genxas.coin.network', 'CoinTransaction') 8 | newTransaction.amount = transaction.amount 9 | newTransaction.type = "DEPOSIT" 10 | 11 | if (vault.transactions) { 12 | vault.transactions.push(newTransaction) 13 | } else { 14 | vault.transactions = [newTransaction] 15 | } 16 | 17 | return getAssetRegistry('com.genxas.coin.network.Vault') 18 | .then(function (assetRegistry) { 19 | return assetRegistry.update(vault) 20 | }) 21 | .then(function () { 22 | sendEvent("Transfer complete"); 23 | }) 24 | } 25 | 26 | function onWithdrawCoin(transaction) { 27 | validateAmount(transaction.amount) 28 | 29 | var vault = transaction.vault 30 | 31 | if (vault.amount < transaction.amount) { 32 | throw new Error('Insufficient fund') 33 | } 34 | 35 | vault.amount -= transaction.amount 36 | 37 | var newTransaction = getFactory().newConcept('com.genxas.coin.network', 'CoinTransaction') 38 | newTransaction.amount = transaction.amount 39 | newTransaction.type = "WITHDRAW" 40 | 41 | if (vault.transactions) { 42 | vault.transactions.push(newTransaction) 43 | } else { 44 | vault.transactions = [newTransaction] 45 | } 46 | 47 | return getAssetRegistry('com.genxas.coin.network.Vault') 48 | .then(function (assetRegistry) { 49 | return assetRegistry.update(vault) 50 | }) 51 | .then(function () { 52 | sendEvent("Transfer complete"); 53 | }) 54 | } 55 | 56 | function onTransferCoin(transaction) { 57 | validateAmount(transaction.amount) 58 | 59 | if (transaction.sender.amount < transaction.amount) { 60 | throw new Error('Insufficient fund') 61 | } 62 | 63 | transaction.sender.amount -= transaction.amount 64 | transaction.receiver.amount += transaction.amount 65 | 66 | var sendTransaction = getFactory().newConcept('com.genxas.coin.network', 'CoinTransaction') 67 | sendTransaction.amount = transaction.amount 68 | sendTransaction.type = "SEND" 69 | if (transaction.sender.transactions) { 70 | transaction.sender.transactions.push(sendTransaction) 71 | } else { 72 | transaction.sender.transactions = [sendTransaction] 73 | } 74 | var receiveTransaction = getFactory().newConcept('com.genxas.coin.network', 'CoinTransaction') 75 | receiveTransaction.amount = transaction.amount 76 | receiveTransaction.type = "RECEIVE" 77 | if (transaction.receiver.transactions) { 78 | transaction.receiver.transactions.push(receiveTransaction) 79 | } else { 80 | transaction.receiver.transactions = [receiveTransaction] 81 | } 82 | 83 | 84 | // Chain style 85 | // 86 | // return getAssetRegistry('com.genxas.coin.network.Vault') 87 | // .then(function (assetRegistry) { 88 | // return assetRegistry.update(transaction.sender) 89 | // }) 90 | // .then(function () { 91 | // return getAssetRegistry('com.genxas.coin.network.Vault') 92 | // }) 93 | // .then(function (assetRegistry) { 94 | // return assetRegistry.update(transaction.receiver) 95 | // }) 96 | 97 | return getAssetRegistry('com.genxas.coin.network.Vault') 98 | .then(function (assetRegistry) { 99 | return assetRegistry.updateAll([transaction.sender, transaction.receiver]) 100 | }) 101 | .then(function () { 102 | sendEvent("Transfer complete") 103 | }) 104 | } 105 | 106 | function validateAmount(amount) { 107 | if (amount < 0) { 108 | throw new Error('Invalid amount') 109 | } 110 | } 111 | 112 | function sendEvent(msg) { 113 | var coinEvent = getFactory().newEvent('com.genxas.coin.network', 'TransactionCompleted') 114 | coinEvent.msg = msg 115 | emit(coinEvent) 116 | } -------------------------------------------------------------------------------- /models/com.genxas.coin.cto: -------------------------------------------------------------------------------- 1 | namespace com.genxas.coin.network 2 | 3 | participant User identified by id { 4 | o String id 5 | o String name 6 | } 7 | 8 | asset Vault identified by id { 9 | o String id 10 | o Double amount 11 | --> User owner 12 | o CoinTransaction[] transactions optional 13 | } 14 | 15 | concept CoinTransaction { 16 | o Double amount 17 | o CoinTransactionType type 18 | } 19 | 20 | enum CoinTransactionType { 21 | o DEPOSIT 22 | o WITHDRAW 23 | o SEND 24 | o RECEIVE 25 | } 26 | 27 | transaction DepositCoin { 28 | --> Vault vault 29 | o Double amount 30 | } 31 | 32 | transaction WithdrawCoin { 33 | --> Vault vault 34 | o Double amount 35 | } 36 | 37 | transaction TransferCoin { 38 | --> Vault sender 39 | --> Vault receiver 40 | o Double amount 41 | } 42 | 43 | event TransactionCompleted { 44 | o String msg 45 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "genxas-coin-network", 3 | "version": "0.0.1", 4 | "description": "Genxas coin", 5 | "scripts": { 6 | "test": "mocha --recursive" 7 | }, 8 | "author": "BabeDev", 9 | "email": "babedroid@gmail.com", 10 | "license": "Apache-2.0", 11 | "devDependencies": { 12 | "composer-admin": "latest", 13 | "composer-client": "latest", 14 | "composer-connector-embedded": "latest", 15 | "browserfs": "latest", 16 | "chai": "latest", 17 | "eslint": "latest", 18 | "istanbul": "latest", 19 | "mkdirp": "latest", 20 | "mocha": "latest" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /permissions.acl: -------------------------------------------------------------------------------- 1 | rule NetworkAdminUser { 2 | description: "Grant business network administrators full access to user resources" 3 | participant: "org.hyperledger.composer.system.NetworkAdmin" 4 | operation: ALL 5 | resource: "**" 6 | action: ALLOW 7 | } 8 | 9 | rule NetworkAdminSystem { 10 | description: "Grant business network administrators full access to system resources" 11 | participant: "org.hyperledger.composer.system.NetworkAdmin" 12 | operation: ALL 13 | resource: "org.hyperledger.composer.system.**" 14 | action: ALLOW 15 | } 16 | 17 | rule NetworkUserSystem { 18 | description: "Grant business network administrators full access to system resources" 19 | participant: "com.genxas.coin.network.User" 20 | operation: READ 21 | resource: "org.hyperledger.composer.system.**" 22 | action: ALLOW 23 | } 24 | 25 | rule SeeYourUser { 26 | description: "See only your user" 27 | participant(p): "com.genxas.coin.network.User" 28 | operation: ALL 29 | resource(r): "com.genxas.coin.network.User" 30 | condition: (p.getIdentifier() == r.getIdentifier()) 31 | action: ALLOW 32 | } 33 | 34 | rule SeeYourVault { 35 | description: "See only your vault" 36 | participant(p): "com.genxas.coin.network.User" 37 | operation: ALL 38 | resource(r): "com.genxas.coin.network.Vault" 39 | condition: (p.getIdentifier() == r.owner.getIdentifier()) 40 | action: ALLOW 41 | } -------------------------------------------------------------------------------- /queries.qry: -------------------------------------------------------------------------------- 1 | query VaultHasAmountMoreThanThousand { 2 | description: "Select all vaults that has amount more than thoudsands coin" 3 | statement: 4 | SELECT com.genxas.coin.network.Vault 5 | WHERE (amount > 1000) 6 | } 7 | 8 | query VaultHasAmountMoreThanParam { 9 | description: "Select all vaults that has amount more than PARAM" 10 | statement: 11 | SELECT com.genxas.coin.network.Vault 12 | WHERE (amount > _$amountParam) 13 | } -------------------------------------------------------------------------------- /start-api.sh: -------------------------------------------------------------------------------- 1 | composer-rest-server -c admin@genxas-coin-network -n never -------------------------------------------------------------------------------- /test/logic.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /** 3 | * Write the unit tests for your transction processor functions here 4 | */ 5 | 6 | var AdminConnection = require('composer-admin').AdminConnection; 7 | var BrowserFS = require('browserfs/dist/node/index'); 8 | var BusinessNetworkConnection = require('composer-client').BusinessNetworkConnection; 9 | var BusinessNetworkDefinition = require('composer-common').BusinessNetworkDefinition; 10 | var path = require('path'); 11 | var fs = require('fs'); 12 | 13 | require('chai').should(); 14 | 15 | var bfs_fs = BrowserFS.BFSRequire('fs'); 16 | var NS = 'com.genxas.coin'; 17 | 18 | var assetType = 'SampleAsset'; 19 | 20 | describe('#'+NS, function() { 21 | 22 | var businessNetworkConnection; 23 | 24 | before(function() { 25 | BrowserFS.initialize(new BrowserFS.FileSystem.InMemory()); 26 | var adminConnection = new AdminConnection({ fs: bfs_fs }); 27 | return adminConnection.createProfile('defaultProfile', { 28 | type: 'embedded' 29 | }) 30 | .then(function() { 31 | return adminConnection.connect('defaultProfile', 'admin', 'Xurw3yU9zI0l'); 32 | }) 33 | .then(function() { 34 | return BusinessNetworkDefinition.fromDirectory(path.resolve(__dirname, '..')); 35 | }) 36 | .then(function(businessNetworkDefinition) { 37 | return adminConnection.deploy(businessNetworkDefinition); 38 | }) 39 | .then(function() { 40 | businessNetworkConnection = new BusinessNetworkConnection({ fs: bfs_fs }); 41 | return businessNetworkConnection.connect('defaultProfile', 'hyperledger-composer-coin-network', 'admin', 'Xurw3yU9zI0l'); 42 | }); 43 | }); 44 | 45 | describe('ChangeAssetValue()', function() { 46 | 47 | it('should change the value property of ' + assetType + ' to newValue', () => { 48 | 49 | var factory = businessNetworkConnection.getBusinessNetwork().getFactory(); 50 | 51 | // create a user 52 | var user = factory.newResource(NS, 'User', 'BabeDev'); 53 | 54 | // create the asset 55 | var asset = factory.newResource(NS, assetType, 'ASSET_001'); 56 | asset.value = 'old-value'; 57 | 58 | var changeAssetValue = factory.newTransaction(NS, 'ChangeAssetValue'); 59 | changeAssetValue.relatedAsset = factory.newRelationship(NS, assetType, asset.$identifier); 60 | changeAssetValue.newValue = 'new-value'; 61 | 62 | // Get the asset registry. 63 | return businessNetworkConnection.getAssetRegistry(NS + '.' + assetType) 64 | .then(function(registry) { 65 | 66 | // Add the Asset to the asset registry. 67 | return registry.add(asset) 68 | .then(function() { 69 | return businessNetworkConnection.getParticipantRegistry(NS + '.User'); 70 | }) 71 | .then(function(userRegistry) { 72 | return userRegistry.add(user); 73 | }) 74 | .then(function() { 75 | // submit the transaction 76 | return businessNetworkConnection.submitTransaction(changeAssetValue); 77 | }) 78 | .then(function() { 79 | return businessNetworkConnection.getAssetRegistry(NS + '.' + assetType); 80 | }) 81 | .then(function(registry) { 82 | // get the listing 83 | return registry.get(asset.$identifier); 84 | }) 85 | .then(function(newAsset) { 86 | newAsset.value.should.equal('new-value'); 87 | }); 88 | }); 89 | }); 90 | }); 91 | }); --------------------------------------------------------------------------------