From 517463e10f6f3a1fee047db9f0f1d64dbcc783de Mon Sep 17 00:00:00 2001 From: sapthasurendran Date: Fri, 4 Feb 2022 18:09:48 +0530 Subject: [PATCH] initial commit Signed-off-by: sapthasurendran Code refactor Signed-off-by: sapthasurendran --- .../.eslintrc.json | 45 ++ .../application-gateway-typescript/.gitignore | 14 + .../package.json | 32 ++ .../application-gateway-typescript/src/app.ts | 434 ++++++++++++++++++ .../src/connect.ts | 103 +++++ .../tsconfig.json | 18 + 6 files changed, 646 insertions(+) create mode 100644 asset-transfer-secured-agreement/application-gateway-typescript/.eslintrc.json create mode 100644 asset-transfer-secured-agreement/application-gateway-typescript/.gitignore create mode 100644 asset-transfer-secured-agreement/application-gateway-typescript/package.json create mode 100644 asset-transfer-secured-agreement/application-gateway-typescript/src/app.ts create mode 100644 asset-transfer-secured-agreement/application-gateway-typescript/src/connect.ts create mode 100644 asset-transfer-secured-agreement/application-gateway-typescript/tsconfig.json diff --git a/asset-transfer-secured-agreement/application-gateway-typescript/.eslintrc.json b/asset-transfer-secured-agreement/application-gateway-typescript/.eslintrc.json new file mode 100644 index 00000000..cc7230a8 --- /dev/null +++ b/asset-transfer-secured-agreement/application-gateway-typescript/.eslintrc.json @@ -0,0 +1,45 @@ +{ + "env": { + "node": true, + "es6": true + }, + "root": true, + "ignorePatterns": [ + "dist/" + ], + "extends": [ + "eslint:recommended" + ], + "rules": { + "indent": [ + "error", + 4 + ], + "quotes": [ + "error", + "single" + ] + }, + "overrides": [ + { + "files": [ + "**/*.ts" + ], + "parser": "@typescript-eslint/parser", + "parserOptions": { + "sourceType": "module", + "ecmaFeatures": { + "impliedStrict": true + } + }, + "plugins": [ + "@typescript-eslint" + ], + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/eslint-recommended", + "plugin:@typescript-eslint/recommended" + ] + } + ] + } \ No newline at end of file diff --git a/asset-transfer-secured-agreement/application-gateway-typescript/.gitignore b/asset-transfer-secured-agreement/application-gateway-typescript/.gitignore new file mode 100644 index 00000000..99e5af9f --- /dev/null +++ b/asset-transfer-secured-agreement/application-gateway-typescript/.gitignore @@ -0,0 +1,14 @@ +# +# SPDX-License-Identifier: Apache-2.0 +# + + +# Coverage directory used by tools like istanbul +coverage + +# Dependency directories +node_modules/ +jspm_packages/ + +# Compiled TypeScript files +dist diff --git a/asset-transfer-secured-agreement/application-gateway-typescript/package.json b/asset-transfer-secured-agreement/application-gateway-typescript/package.json new file mode 100644 index 00000000..71fa0da7 --- /dev/null +++ b/asset-transfer-secured-agreement/application-gateway-typescript/package.json @@ -0,0 +1,32 @@ +{ + "name": "asset-transfer-basic", + "version": "1.0.0", + "description": "Asset Transfer Secured Agreement Application implemented in typeScript using fabric-gateway", + "main": "dist/index.js", + "typings": "dist/index.d.ts", + "engines": { + "node": ">=14" + }, + "scripts": { + "build": "tsc", + "build:watch": "tsc -w", + "lint": "eslint . --ext .ts", + "prepare": "npm run build", + "pretest": "npm run lint", + "start": "node dist/app.js" + }, + "engineStrict": true, + "author": "Hyperledger", + "license": "Apache-2.0", + "dependencies": { + "@hyperledger/fabric-gateway": "^1.0.0", + "@grpc/grpc-js": "^1.5.0" + }, + "devDependencies": { + "@tsconfig/node14": "^1.0.1", + "@typescript-eslint/eslint-plugin": "^5.6.0", + "@typescript-eslint/parser": "^5.6.0", + "eslint": "^8.4.1", + "typescript": "~4.5.2" + } +} diff --git a/asset-transfer-secured-agreement/application-gateway-typescript/src/app.ts b/asset-transfer-secured-agreement/application-gateway-typescript/src/app.ts new file mode 100644 index 00000000..030f2aab --- /dev/null +++ b/asset-transfer-secured-agreement/application-gateway-typescript/src/app.ts @@ -0,0 +1,434 @@ +/* + * Copyright IBM Corp. All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +import { connect, Contract} from '@hyperledger/fabric-gateway'; +import { TextDecoder } from 'util'; +import crpto from 'crypto'; +import { newGrpcConnection,newIdentity,newSigner,tlsCertPathOrg1,peerEndpointOrg1,peerNameOrg1,certPathOrg1,mspIdOrg1,keyDirectoryPathOrg1,tlsCertPathOrg2,peerEndpointOrg2,peerNameOrg2,certPathOrg2,mspIdOrg2,keyDirectoryPathOrg2} from './connect' + +const utf8Decoder = new TextDecoder(); + +const RED = '\x1b[31m\n'; +const GREEN = '\x1b[32m\n'; +const RESET = '\x1b[0m'; + +const channelName = 'mychannel'; +const chaincodeName = 'secured'; + +//Use a random key so that we can run multiple times +const now = Date.now(); +const assetKey= `asset${now}`; + +//Generate random bytes using crypto +const randomBytes = crpto.randomBytes(256).toString('hex') + +async function main(): Promise { + + // The gRPC client connection from org1 should be shared by all Gateway connections to this endpoint. + const clientOrg1 = await newGrpcConnection( + tlsCertPathOrg1, + peerEndpointOrg1, + peerNameOrg1 + ); + + const gatewayOrg1 = connect({ + client: clientOrg1, + identity: await newIdentity(certPathOrg1, mspIdOrg1), + signer: await newSigner(keyDirectoryPathOrg1), + }); + + // The gRPC client connection from org2 should be shared by all Gateway connections to this endpoint. + const clientOrg2 = await newGrpcConnection( + tlsCertPathOrg2, + peerEndpointOrg2, + peerNameOrg2 + ); + + const gatewayOrg2 = connect({ + client: clientOrg2, + identity: await newIdentity(certPathOrg2, mspIdOrg2), + signer: await newSigner(keyDirectoryPathOrg2), + }); + + + try { + // Get the smart contract from the network for Org1. + const contractOrg1 = gatewayOrg1.getNetwork(channelName).getContract(chaincodeName); + + // Get the smart contract from the network for Org2. + const contractOrg2 = gatewayOrg2.getNetwork(channelName).getContract(chaincodeName); + + // Create an asset by organization Org1, this only requires the owning organization to endorse. + await createAsset(contractOrg1,mspIdOrg1); + + // Read the public details by org1. + await readAsset(assetKey, mspIdOrg1, contractOrg1,mspIdOrg1); + + // Read the public details by org2. + await readAsset(assetKey, mspIdOrg1, contractOrg2,mspIdOrg2); + + // Org1 should be able to read the private data details of the asset. + await readPrivateAsset(assetKey,mspIdOrg1,contractOrg1) + + // Org2 is not the owner and does not have the private details, read expected to fail. + await readPrivateAsset(assetKey,mspIdOrg2,contractOrg2) + + // Org1 updates the assets public description. + await changePublicDescription(assetKey,mspIdOrg1,`Asset ${assetKey} owned by ${mspIdOrg1} is for sale`,contractOrg1) + + // Read the public details by org1. + await readAsset(assetKey, mspIdOrg1, contractOrg1,mspIdOrg1); + + // Read the public details by org2. + await readAsset(assetKey, mspIdOrg1, contractOrg2,mspIdOrg2); + + // This is an update to the public state and requires the owner(Org1) to endorse and sent by the owner org client (Org1). + // Since the client is from Org2, which is not the owner, this will fail + await changePublicDescription(assetKey,mspIdOrg2,`Asset ${assetKey} owned by ${mspIdOrg2} is NOT for sale`,contractOrg2); + + // Read the public details by org1. + await readAsset(assetKey, mspIdOrg1, contractOrg1,mspIdOrg1); + + // Read the public details by org2. + await readAsset(assetKey, mspIdOrg1, contractOrg2,mspIdOrg2); + + // Agree to a sell by org1. + await agreeToSell(assetKey,mspIdOrg1,110,contractOrg1); + + // Check the private information about the asset from Org2. Org1 would have to send Org2 asset details, + // so the hash of the details may be checked by the chaincode. + await verifyAssetProperties(assetKey,mspIdOrg2,contractOrg2); + + // Agree to a buy by org2. + await agreeToBuy(assetKey,mspIdOrg2,100,contractOrg2); + + // Org1 should be able to read the sale price of this asset + await readSalePrice(assetKey, mspIdOrg1, contractOrg1); + + // Org2 has not set a sale price and this should fail + await readSalePrice(assetKey, mspIdOrg2, contractOrg2); + + // Org1 has not agreed to buy so this should fail + await readBidPrice(assetKey, mspIdOrg1, contractOrg1); + + // Org2 should be able to see the price it has agreed + await readBidPrice(assetKey, mspIdOrg2, contractOrg2); + + // Org1 will try to transfer the asset to Org2 + // This will fail due to the sell price and the bid price are not the same + await transferAsset(assetKey, mspIdOrg1,mspIdOrg2, 110,contractOrg1); + + // Agree to a sell by Org1,the seller will agree to the bid price of Org2 + await agreeToSell(assetKey,mspIdOrg1,100,contractOrg1); + + // Read the public details by org1. + await readAsset(assetKey, mspIdOrg1, contractOrg1,mspIdOrg1); + + // Read the public details by org2. + await readAsset(assetKey, mspIdOrg1, contractOrg2,mspIdOrg2); + + // Org1 should be able to read the private data details of the asset. + await readPrivateAsset(assetKey,mspIdOrg1,contractOrg1) + + // Org1 should be able to read the sale price of this asset + await readSalePrice(assetKey, mspIdOrg1, contractOrg1); + + // Org2 should be able to see the price it has agreed + await readBidPrice(assetKey, mspIdOrg2, contractOrg2); + + // Org2 user will try to transfer the asset to Org1 + // This will fail as the owner is Org1 + await transferAsset(assetKey, mspIdOrg2,mspIdOrg2, 100,contractOrg2); + + // Org1 will transfer the asset to Org2 + // This will now complete as the sell price and the bid price are the same + await transferAsset(assetKey, mspIdOrg1,mspIdOrg2, 100, contractOrg1); + + // Read the public details by org1. + await readAsset(assetKey, mspIdOrg2, contractOrg1,mspIdOrg1); + + // Read the public details by org2. + await readAsset(assetKey, mspIdOrg2, contractOrg2,mspIdOrg2); + + // Org2 should be able to read the private data details of this asset + await readPrivateAssetAfterTransfer(assetKey, mspIdOrg2, contractOrg2); + + // Org1 should not be able to read the private data details of this asset,expected to fail + await readPrivateAssetAfterTransfer(assetKey, mspIdOrg1, contractOrg1); + + // This is an update to the public state and requires only the owner to endorse. + // Org2 wants to indicate that the items is no longer for sale + await changePublicDescriptionAfterTransfer(assetKey,mspIdOrg2,`Asset ${assetKey} owned by ${mspIdOrg2} is NOT for sale`,contractOrg2); + + // Read the public details by org1. + await readAsset(assetKey, mspIdOrg2, contractOrg1,mspIdOrg1); + + // Read the public details by org2. + await readAsset(assetKey, mspIdOrg2, contractOrg2,mspIdOrg2); + + } finally { + gatewayOrg1.close(); + gatewayOrg2.close(); + clientOrg1.close(); + clientOrg2.close(); + } +} + +main().catch(error => { + console.error('******** FAILED to run the application:', error); + process.exitCode = 1; +}); + +async function createAsset(contract:Contract,org:string):Promise { + const asset_properties = { + object_type: 'asset_properties', + asset_id: assetKey, + color: 'blue', + size: 35, + salt: randomBytes + }; + console.log(`${GREEN}--> Submit Transaction: CreateAsset, ${assetKey} as ${org} - endorsed by Org1${RESET}`); + + await contract.submit('CreateAsset', { + arguments:[assetKey,`Asset ${assetKey} owned by ${org} is not for sale`], + transientData: { asset_properties: JSON.stringify(asset_properties) }, + }); + + console.log(`*** Result: committed, asset ${assetKey} is owned by Org1`); +} + +async function readAsset(assetKey:string, ownerOrg:string, contract:Contract,org:string):Promise { + console.log(`${GREEN}--> Evaluate Transactions: ReadAsset as ${org}, - ${assetKey} should be owned by ${ownerOrg}${RESET}`); + + const resultBytes = await contract.evaluateTransaction('ReadAsset', assetKey); + + const resultString = utf8Decoder.decode(resultBytes); + if (resultString.length !== 0) { + + const result:{ objectType: string, assetID: string, ownerOrg: string, publicDescription: string } = JSON.parse(resultString); + if (result?.ownerOrg === ownerOrg) { + console.log(`*** Result from ${org} - asset ${result.assetID} owned by ${result.ownerOrg} DESC:${result.publicDescription}`); + } else { + console.log(`${RED}*** Failed owner check from ${org} - asset ${result.assetID} owned by ${result.ownerOrg} DESC:${result.publicDescription}${RESET}`); + } + }else{ + console.log(`${RED}*** Failed ReadAsset ${RESET}`); + } +} + +async function readPrivateAsset(assetKey:string, org:string, contract:Contract):Promise { + try{ + console.log(`${GREEN}--> Evaluate Transaction: GetAssetPrivateProperties, - ${assetKey} from organization ${org}${RESET}`); + if(org === mspIdOrg2){ + console.log(`${GREEN}* Expected to fail as ${org} is not the owner and does not have the private details${RESET}`) + } + const resultBytes = await contract.evaluateTransaction('GetAssetPrivateProperties', assetKey); + + const resultString = utf8Decoder.decode(resultBytes); + const result = JSON.parse(resultString); + + console.log('*** Result:', result); + } + catch(e){ + console.log(`${RED}*** Failed evaluateTransaction readPrivateAsset: ${e}${RESET}`); + } +} + +async function changePublicDescription(assetKey:string, org:string, description:string,contract:Contract):Promise { + try { + console.log(`${GREEN}--> Submit Transaction: ChangePublicDescription ${assetKey}, as ${org} - endorse by ${org}${RESET}`); + if(org===mspIdOrg2){ + console.log(`${GREEN}* Expected to fail as ${org} is not the owner${RESET}`) + } + + await contract.submit('ChangePublicDescription', { + arguments:[assetKey,description], + }); + + console.log(`*** Result: committed, asset ${assetKey} is now for sale by ${org}`); + } catch (e) { + console.log(`${RED}*** Failed: ChangePublicDescription - ${e}${RESET}`); + } +} + +async function agreeToSell(assetKey:string, org:string, price:number,contract:Contract):Promise { + try { + const asset_price = { + asset_id: assetKey, + price:price, + trade_id: now.toString() + }; + console.log(`${GREEN}--> Submit Transaction: AgreeToSell, ${assetKey} as ${org} - endorsed by ${org}${RESET}`); + + await contract.submit('AgreeToSell',{ + arguments:[assetKey], + transientData: { asset_price: JSON.stringify(asset_price) } + }); + + console.log(`*** Result: committed, ${org} has agreed to sell asset ${assetKey} for ${price}`); + } catch (e) { + console.log(`${RED}*** Failed: AgreeToSell - ${e}${RESET}`); + } +} + +async function verifyAssetProperties(assetKey:string, org:string, contract:Contract):Promise { + try { + const asset_properties = { + object_type: 'asset_properties', + asset_id: assetKey, + color: 'blue', + size: 35, + salt: randomBytes + }; + console.log(`${GREEN}--> Evalute: VerifyAssetProperties, ${assetKey} as ${org} - endorsed by ${org}${RESET}`); + + const resultBytes = await contract.evaluate('VerifyAssetProperties',{ + arguments:[assetKey], + transientData: { asset_properties: JSON.stringify(asset_properties) }, + }); + + const resultString = utf8Decoder.decode(resultBytes); + + if (resultString.length !==0) { + const result = JSON.parse(resultString); + if (result) { + console.log(`*** Success VerifyAssetProperties, private information about asset ${assetKey} has been verified by ${org}`); + } else { + console.log(`*** Failed: VerifyAssetProperties, private information about asset ${assetKey} has not been verified by ${org}`); + } + } else { + console.log(`*** Failed: VerifyAssetProperties, private information about asset ${assetKey} has not been verified by ${org}`); + } + } catch (e) { + console.log(`${RED}*** Failed: VerifyAssetProperties - ${e}${RESET}`); + } +} + +async function agreeToBuy(assetKey:string, org:string, price:number, contract:Contract):Promise { + try { + const asset_price = { + asset_id: assetKey, + price:price, + trade_id: now.toString() + }; + console.log(`${GREEN}--> Submit Transaction: AgreeToBuy, ${assetKey} as ${org} - endorsed by ${org}${RESET}`); + + await contract.submit('AgreeToBuy',{ + arguments:[assetKey], + transientData: { asset_price: JSON.stringify(asset_price) } + }); + + console.log(`*** Result: committed, ${org} has agreed to buy asset ${assetKey} for 100`); + } catch (e) { + console.log(`${RED}*** Failed: AgreeToBuy - ${e}${RESET}`); + } +} + +async function readSalePrice(assetKey:string, org:string, contract:Contract):Promise { + try { + console.log(`${GREEN}--> Evaluate Transaction: GetAssetSalesPrice, - ${assetKey} from organization ${org}${RESET}`); + if(org===mspIdOrg2){ + console.log(`${GREEN}* Expected to fail as ${org} has not set a sale price${RESET}`) + } + + const resultBytes = await contract.evaluateTransaction('GetAssetSalesPrice', assetKey); + + const resultString = utf8Decoder.decode(resultBytes); + const result = JSON.parse(resultString); + console.log('*** Result: GetAssetSalesPrice', result); + } catch (e) { + console.log(`${RED}*** Failed evaluateTransaction GetAssetSalesPrice: ${e}${RESET}`); + } +} + +async function readBidPrice(assetKey:string, org:string, contract:Contract):Promise { + try{ + console.log(`${GREEN}--> Evaluate Transaction: GetAssetBidPrice, - ${assetKey} from organization ${org}${RESET}`); + if(org===mspIdOrg1){ + console.log(`${GREEN}* Expected to fail as Org1 has not agreed to buy${RESET}`) + } + + const resultBytes = await contract.evaluateTransaction('GetAssetBidPrice', assetKey); + + const resultString = utf8Decoder.decode(resultBytes); + const result = JSON.parse(resultString); + + console.log('*** Result: GetAssetBidPrice', result); + } catch (e) { + console.log(`${RED}*** Failed evaluateTransaction GetAssetBidPrice: ${e}${RESET}`); + } +} + +async function transferAsset(assetKey:string, org:string,buyerOrgID:string, price:number,contract:Contract):Promise { + try{ + const asset_properties = { + object_type: 'asset_properties', + asset_id: assetKey, + color: 'blue', + size: 35, + salt: randomBytes + }; + const asset_price = { + asset_id: assetKey, + price:price, + trade_id: now.toString() + }; + + console.log(`${GREEN}--> Submit Transaction: TransferAsset, ${assetKey} as ${org} - endorsed by ${org}${RESET}`); + if(org === mspIdOrg2){ + console.log(`${GREEN}* Expected to fail as the owner is Org1${RESET}`) + }else if(price === 110){ + console.log(`${GREEN}* Expected to fail as sell price and the bid price are not the same${RESET}`) + } + + await contract.submit('TransferAsset', { + arguments:[assetKey,buyerOrgID], + transientData: { + asset_properties: JSON.stringify(asset_properties), + asset_price: JSON.stringify(asset_price) }, + endorsingOrganizations:[mspIdOrg1,mspIdOrg2] + }); + + console.log(`${GREEN}*** Result: committed, ${org} has transfered the asset ${assetKey} to ${mspIdOrg2} ${RESET}`); + } catch (e) { + console.log(`${RED}*** Failed: TransferAsset - ${e}${RESET}`); + } +} + +async function readPrivateAssetAfterTransfer(assetKey:string, org:string, contract:Contract):Promise { + try{ + console.log(`${GREEN}--> Evaluate Transaction: GetAssetPrivateProperties, - ${assetKey} from organization ${org}${RESET}`); + if(org === mspIdOrg1){ + console.log(`${GREEN}* Expected to fail as ${org} is not the owner and does not have the private details${RESET}`) + } + const resultBytes = await contract.evaluateTransaction('GetAssetPrivateProperties', assetKey); + + const resultString = utf8Decoder.decode(resultBytes); + const result = JSON.parse(resultString); + + console.log('*** Result:', result); + } + catch(e){ + console.log(`${RED}*** Failed evaluateTransaction readPrivateAsset: ${e}${RESET}`); + } +} + +async function changePublicDescriptionAfterTransfer(assetKey:string, org:string, description:string,contract:Contract):Promise { + try { + console.log(`${GREEN}--> Submit Transaction: changePublicDescription ${assetKey}, as ${org} - endorse by ${org}${RESET}`); + if(org===mspIdOrg1){ + console.log(`${GREEN}* Expected to fail as ${org} is not the owner${RESET}`) + } + + await contract.submit('ChangePublicDescription', { + arguments:[assetKey,description], + }); + + console.log(`*** Result: committed, asset ${assetKey} is now for sale by ${org}`); + } catch (e) { + console.log(`${RED}*** Failed: changePublicDescription - ${e}${RESET}`); + } +} \ No newline at end of file diff --git a/asset-transfer-secured-agreement/application-gateway-typescript/src/connect.ts b/asset-transfer-secured-agreement/application-gateway-typescript/src/connect.ts new file mode 100644 index 00000000..e10f8bd6 --- /dev/null +++ b/asset-transfer-secured-agreement/application-gateway-typescript/src/connect.ts @@ -0,0 +1,103 @@ +/* + * Copyright IBM Corp. All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +import * as grpc from '@grpc/grpc-js'; +import { Identity, Signer, signers } from '@hyperledger/fabric-gateway'; +import * as crypto from 'crypto'; +import { promises as fs } from 'fs'; +import * as path from 'path'; + +// MSP Id's of Organizations +export const mspIdOrg1 = 'Org1MSP'; +export const mspIdOrg2 = 'Org2MSP'; + +// Path to org1 crypto materials. +export const cryptoPathOrg1 = path.resolve(__dirname, '..', '..', '..', 'test-network', 'organizations', 'peerOrganizations', 'org1.example.com'); + +// Path to user private key directory. +export const keyDirectoryPathOrg1 = path.resolve(cryptoPathOrg1, 'users', 'User1@org1.example.com', 'msp', 'keystore'); + +// Path to user certificate. +export const certPathOrg1 = path.resolve(cryptoPathOrg1, 'users', 'User1@org1.example.com', 'msp', 'signcerts', 'cert.pem'); + +// Path to peer tls certificate. +export const tlsCertPathOrg1 = path.resolve(cryptoPathOrg1, 'peers', 'peer0.org1.example.com', 'tls', 'ca.crt'); + +// Path to org2 crypto materials. +export const cryptoPathOrg2 = path.resolve( + __dirname, + '..', + '..', + '..', + 'test-network', + 'organizations', + 'peerOrganizations', + 'org2.example.com' +); + +// Path to org2 user private key directory. +export const keyDirectoryPathOrg2 = path.resolve( + cryptoPathOrg2, + 'users', + 'User1@org2.example.com', + 'msp', + 'keystore' +); + +// Path to org2 user certificate. +export const certPathOrg2 = path.resolve( + cryptoPathOrg2, + 'users', + 'User1@org2.example.com', + 'msp', + 'signcerts', + 'cert.pem' +); + +// Path to org2 peer tls certificate. +export const tlsCertPathOrg2 = path.resolve( + cryptoPathOrg2, + 'peers', + 'peer0.org2.example.com', + 'tls', + 'ca.crt' +); +// Gateway peer endpoint. +export const peerEndpointOrg1 = 'localhost:7051'; +export const peerEndpointOrg2 = 'localhost:9051'; + +// Gateway peer container name. +export const peerNameOrg1 = 'peer0.org1.example.com'; +export const peerNameOrg2 = 'peer0.org2.example.com'; + +//Collection Names +export const org1PrivateCollectionName = 'Org1MSPPrivateCollection'; +export const org2PrivateCollectionName = 'Org2MSPPrivateCollection'; + +export async function newGrpcConnection( + tlsCertPath: string, + peerEndpoint: string, + peerName: string +): Promise { + const tlsRootCert = await fs.readFile(tlsCertPath); + const tlsCredentials = grpc.credentials.createSsl(tlsRootCert); + return new grpc.Client(peerEndpoint, tlsCredentials, { + 'grpc.ssl_target_name_override': peerName, + }); +} + +export async function newIdentity(certPath: string, mspId: string): Promise { + const credentials = await fs.readFile(certPath); + return { mspId, credentials }; +} + +export async function newSigner(keyDirectoryPath: string): Promise { + const files = await fs.readdir(keyDirectoryPath); + const keyPath = path.resolve(keyDirectoryPath, files[0]); + const privateKeyPem = await fs.readFile(keyPath); + const privateKey = crypto.createPrivateKey(privateKeyPem); + return signers.newPrivateKeySigner(privateKey); +} \ No newline at end of file diff --git a/asset-transfer-secured-agreement/application-gateway-typescript/tsconfig.json b/asset-transfer-secured-agreement/application-gateway-typescript/tsconfig.json new file mode 100644 index 00000000..2052fb6e --- /dev/null +++ b/asset-transfer-secured-agreement/application-gateway-typescript/tsconfig.json @@ -0,0 +1,18 @@ +{ + "extends":"@tsconfig/node14/tsconfig.json", + "compilerOptions": { + "experimentalDecorators": true, + "emitDecoratorMetadata": true, + "outDir": "dist", + "moduleResolution": "node", + "declaration": true, + "sourceMap": true, + "noImplicitAny": true + }, + "include": [ + "./src/**/*" + ], + "exclude": [ + "./src/**/*.spec.ts" + ] +}