diff --git a/asset-transfer-secured-agreement/application-gateway-typescript/src/app.ts b/asset-transfer-secured-agreement/application-gateway-typescript/src/app.ts index 64733a2d..1b404140 100644 --- a/asset-transfer-secured-agreement/application-gateway-typescript/src/app.ts +++ b/asset-transfer-secured-agreement/application-gateway-typescript/src/app.ts @@ -4,16 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { connect, Contract} from '@hyperledger/fabric-gateway'; -import { TextDecoder } from 'util'; +import { connect } from '@hyperledger/fabric-gateway'; 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'; +import { newGrpcConnection, newIdentity, newSigner, tlsCertPathOrg1, peerEndpointOrg1, peerNameOrg1, certPathOrg1, mspIdOrg1, keyDirectoryPathOrg1, tlsCertPathOrg2, peerEndpointOrg2, peerNameOrg2, certPathOrg2, mspIdOrg2, keyDirectoryPathOrg2 } from './connect'; +import { Asset, AssetPrice, AssetProperties, GREEN, RED, RESET } from './utils'; +import { ContractWrapper } from './contractWrapper'; const channelName = 'mychannel'; const chaincodeName = 'secured'; @@ -23,7 +18,7 @@ const now = Date.now(); const assetKey = `asset${now}`; //Generate random bytes using crypto -const randomBytes = crpto.randomBytes(256).toString('hex') +const randomBytes = crpto.randomBytes(256).toString('hex'); async function main(): Promise { @@ -55,119 +50,122 @@ async function main(): Promise { try { + // Get the smart contract from the network for Org1. const contractOrg1 = gatewayOrg1.getNetwork(channelName).getContract(chaincodeName); + const contractWrapperOrg1 = new ContractWrapper(contractOrg1); // Get the smart contract from the network for Org2. const contractOrg2 = gatewayOrg2.getNetwork(channelName).getContract(chaincodeName); + const contractWrapperOrg2 = new ContractWrapper(contractOrg2); // Create an asset by organization Org1, this only requires the owning organization to endorse. - await createAsset(contractOrg1,mspIdOrg1); + await createAsset(contractWrapperOrg1, mspIdOrg1); - // Read the public details by org1. - await readAsset(assetKey, mspIdOrg1, contractOrg1,mspIdOrg1); + // Read the public details by org1. + await readAsset(contractWrapperOrg1, assetKey, mspIdOrg1, mspIdOrg1); - // Read the public details by org2. - await readAsset(assetKey, mspIdOrg1, contractOrg2,mspIdOrg2); + // Read the public details by org2. + await readAsset(contractWrapperOrg2, assetKey, mspIdOrg1, mspIdOrg2); // Org1 should be able to read the private data details of the asset. - await readPrivateAsset(assetKey,mspIdOrg1,contractOrg1) + await readPrivateAsset(contractWrapperOrg1, assetKey, mspIdOrg1) // Org2 is not the owner and does not have the private details, read expected to fail. - await readPrivateAsset(assetKey,mspIdOrg2,contractOrg2) + await readPrivateAsset(contractWrapperOrg2, assetKey, mspIdOrg2) // Org1 updates the assets public description. - await changePublicDescription(assetKey,mspIdOrg1,`Asset ${assetKey} owned by ${mspIdOrg1} is for sale`,contractOrg1) + await changePublicDescription(contractWrapperOrg1, assetKey, mspIdOrg1, `Asset ${assetKey} owned by ${mspIdOrg1} is for sale`) - // Read the public details by org1. - await readAsset(assetKey, mspIdOrg1, contractOrg1,mspIdOrg1); + // Read the public details by org1. + await readAsset(contractWrapperOrg1, assetKey, mspIdOrg1,mspIdOrg1); - // Read the public details by org2. - await readAsset(assetKey, mspIdOrg1, contractOrg2,mspIdOrg2); + // Read the public details by org2. + await readAsset(contractWrapperOrg2, assetKey, mspIdOrg1,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); + await changePublicDescription(contractWrapperOrg2, assetKey, mspIdOrg2, `Asset ${assetKey} owned by ${mspIdOrg2} is NOT for sale`); - // Read the public details by org1. - await readAsset(assetKey, mspIdOrg1, contractOrg1,mspIdOrg1); + // Read the public details by org1. + await readAsset(contractWrapperOrg1, assetKey, mspIdOrg1, mspIdOrg1); - // Read the public details by org2. - await readAsset(assetKey, mspIdOrg1, contractOrg2,mspIdOrg2); + // Read the public details by org2. + await readAsset(contractWrapperOrg2, assetKey, mspIdOrg1, mspIdOrg2); // Agree to a sell by org1. - await agreeToSell(assetKey,mspIdOrg1,110,contractOrg1); + await agreeToSell(contractWrapperOrg1, assetKey, mspIdOrg1, 110); // 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); + await verifyAssetProperties(contractWrapperOrg2, assetKey, mspIdOrg2); // Agree to a buy by org2. - await agreeToBuy(assetKey,mspIdOrg2,100,contractOrg2); + await agreeToBuy(contractWrapperOrg2, assetKey, mspIdOrg2, 100); // Org1 should be able to read the sale price of this asset - await readSalePrice(assetKey, mspIdOrg1, contractOrg1); + await readSalePrice(contractWrapperOrg1, assetKey, mspIdOrg1); // Org2 has not set a sale price and this should fail - await readSalePrice(assetKey, mspIdOrg2, contractOrg2); + await readSalePrice(contractWrapperOrg2, assetKey, mspIdOrg2); // Org1 has not agreed to buy so this should fail - await readBidPrice(assetKey, mspIdOrg1, contractOrg1); + await readBidPrice(contractWrapperOrg1, assetKey, mspIdOrg1); // Org2 should be able to see the price it has agreed - await readBidPrice(assetKey, mspIdOrg2, contractOrg2); + await readBidPrice(contractWrapperOrg2, assetKey, mspIdOrg2); // 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); + await transferAsset(contractWrapperOrg1, assetKey, mspIdOrg1, mspIdOrg2, 110); // Agree to a sell by Org1,the seller will agree to the bid price of Org2 - await agreeToSell(assetKey,mspIdOrg1,100,contractOrg1); + await agreeToSell(contractWrapperOrg1, assetKey, mspIdOrg1, 100); // Read the public details by org1. - await readAsset(assetKey, mspIdOrg1, contractOrg1,mspIdOrg1); + await readAsset(contractWrapperOrg1, assetKey, mspIdOrg1,mspIdOrg1); // Read the public details by org2. - await readAsset(assetKey, mspIdOrg1, contractOrg2,mspIdOrg2); + await readAsset(contractWrapperOrg2, assetKey, mspIdOrg1, mspIdOrg2); // Org1 should be able to read the private data details of the asset. - await readPrivateAsset(assetKey,mspIdOrg1,contractOrg1) + await readPrivateAsset(contractWrapperOrg1, assetKey, mspIdOrg1,) // Org1 should be able to read the sale price of this asset - await readSalePrice(assetKey, mspIdOrg1, contractOrg1); + await readSalePrice(contractWrapperOrg1, assetKey, mspIdOrg1); // Org2 should be able to see the price it has agreed - await readBidPrice(assetKey, mspIdOrg2, contractOrg2); + await readBidPrice(contractWrapperOrg2, assetKey, mspIdOrg2); // 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); + await transferAsset(contractWrapperOrg2, assetKey, mspIdOrg2, mspIdOrg2, 100); // 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); + await transferAsset(contractWrapperOrg1, assetKey, mspIdOrg1, mspIdOrg2, 100); // Read the public details by org1. - await readAsset(assetKey, mspIdOrg2, contractOrg1,mspIdOrg1); + await readAsset(contractWrapperOrg1, assetKey, mspIdOrg2, mspIdOrg1); // Read the public details by org2. - await readAsset(assetKey, mspIdOrg2, contractOrg2,mspIdOrg2); + await readAsset(contractWrapperOrg2, assetKey, mspIdOrg2, mspIdOrg2); // Org2 should be able to read the private data details of this asset - await readPrivateAssetAfterTransfer(assetKey, mspIdOrg2, contractOrg2); + await readPrivateAssetAfterTransfer(contractWrapperOrg2, assetKey, mspIdOrg2); // Org1 should not be able to read the private data details of this asset,expected to fail - await readPrivateAssetAfterTransfer(assetKey, mspIdOrg1, contractOrg1); + await readPrivateAssetAfterTransfer(contractWrapperOrg1, assetKey, mspIdOrg1); // 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); + await changePublicDescriptionAfterTransfer(contractWrapperOrg2, assetKey, mspIdOrg2, `Asset ${assetKey} owned by ${mspIdOrg2} is NOT for sale`); // Read the public details by org1. - await readAsset(assetKey, mspIdOrg2, contractOrg1,mspIdOrg1); + await readAsset(contractWrapperOrg1, assetKey, mspIdOrg2, mspIdOrg1); // Read the public details by org2. - await readAsset(assetKey, mspIdOrg2, contractOrg2,mspIdOrg2); + await readAsset(contractWrapperOrg2, assetKey, mspIdOrg2, mspIdOrg2); } finally { gatewayOrg1.close(); @@ -182,53 +180,45 @@ main().catch(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 - }; +async function createAsset(contract:ContractWrapper, org:string):Promise { 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) }, + arguments: [assetKey,`Asset ${assetKey} owned by ${org} is not for sale`], + transientData: { asset_properties: AssetProperties.instance('asset_properties', assetKey, 'blue', 35, randomBytes)}, }); console.log(`*** Result: committed, asset ${assetKey} is owned by Org1`); } -async function readAsset(assetKey:string, ownerOrg:string, contract:Contract,org:string):Promise { +async function readAsset(contract:ContractWrapper, assetKey:string, ownerOrg:string, 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); + const resultString = await contract.evaluateTransaction('ReadAsset', assetKey); + const result = Asset.parse(resultString); 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 { +async function readPrivateAsset(contract:ContractWrapper, assetKey:string, org:string):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 = await contract.evaluateTransaction('GetAssetPrivateProperties', assetKey); - const resultString = utf8Decoder.decode(resultBytes); - const result = JSON.parse(resultString); + const result = Asset.parse(resultString); console.log('*** Result:', result); } @@ -237,7 +227,7 @@ async function readPrivateAsset(assetKey:string, org:string, contract:Contract): } } -async function changePublicDescription(assetKey:string, org:string, description:string,contract:Contract):Promise { +async function changePublicDescription(contract:ContractWrapper, assetKey:string, org:string, description:string):Promise { try { console.log(`${GREEN}--> Submit Transaction: ChangePublicDescription ${assetKey}, as ${org} - endorse by ${org}${RESET}`); if(org===mspIdOrg2){ @@ -254,18 +244,13 @@ async function changePublicDescription(assetKey:string, org:string, description: } } -async function agreeToSell(assetKey:string, org:string, price:number,contract:Contract):Promise { +async function agreeToSell(contract:ContractWrapper, assetKey:string, org:string, price:number):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) } + transientData: { asset_price: AssetPrice.instance(assetKey, price, now.toString()) } }); console.log(`*** Result: committed, ${org} has agreed to sell asset ${assetKey} for ${price}`); @@ -274,26 +259,17 @@ async function agreeToSell(assetKey:string, org:string, price:number,contract:Co } } -async function verifyAssetProperties(assetKey:string, org:string, contract:Contract):Promise { +async function verifyAssetProperties(contract:ContractWrapper, assetKey:string, org:string): 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',{ + const resultString = await contract.evaluate('VerifyAssetProperties',{ arguments:[assetKey], - transientData: { asset_properties: JSON.stringify(asset_properties) }, + transientData: { asset_properties: AssetProperties.instance('asset_properties', assetKey, 'blue', 35, randomBytes) }, }); - const resultString = utf8Decoder.decode(resultBytes); - - if (resultString.length !==0) { - const result = JSON.parse(resultString); + if (resultString.length !== 0) { + const result = Asset.parse(resultString); if (result) { console.log(`*** Success VerifyAssetProperties, private information about asset ${assetKey} has been verified by ${org}`); } else { @@ -307,18 +283,13 @@ async function verifyAssetProperties(assetKey:string, org:string, contract:Contr } } -async function agreeToBuy(assetKey:string, org:string, price:number, contract:Contract):Promise { +async function agreeToBuy(contract:ContractWrapper, assetKey:string, org:string, price:number):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) } + transientData: { asset_price: AssetPrice.instance(assetKey,price,now.toString()) } }); console.log(`*** Result: committed, ${org} has agreed to buy asset ${assetKey} for 100`); @@ -327,34 +298,30 @@ async function agreeToBuy(assetKey:string, org:string, price:number, contract:Co } } -async function readSalePrice(assetKey:string, org:string, contract:Contract):Promise { +async function readSalePrice(contract:ContractWrapper, assetKey:string, org:string):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); + const resultString = await contract.evaluateTransaction('GetAssetSalesPrice', assetKey); + const result = Asset.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 { +async function readBidPrice(contract:ContractWrapper, assetKey:string, org:string):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); + const resultString = await contract.evaluateTransaction('GetAssetBidPrice', assetKey); + const result = Asset.parse(resultString); console.log('*** Result: GetAssetBidPrice', result); } catch (e) { @@ -362,20 +329,8 @@ async function readBidPrice(assetKey:string, org:string, contract:Contract):Prom } } -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() - }; +async function transferAsset(contract:ContractWrapper, assetKey:string, org:string,buyerOrgID:string, price:number):Promise { + try { console.log(`${GREEN}--> Submit Transaction: TransferAsset, ${assetKey} as ${org} - endorsed by ${org}${RESET}`); if(org === mspIdOrg2){ @@ -387,8 +342,8 @@ async function transferAsset(assetKey:string, org:string,buyerOrgID:string, pric await contract.submit('TransferAsset', { arguments:[assetKey,buyerOrgID], transientData: { - asset_properties: JSON.stringify(asset_properties), - asset_price: JSON.stringify(asset_price) }, + asset_properties: AssetProperties.instance('asset_properties', assetKey, 'blue', 35, randomBytes), + asset_price: AssetPrice.instance(assetKey, price, now.toString()) }, endorsingOrganizations:[mspIdOrg1,mspIdOrg2] }); @@ -398,16 +353,14 @@ async function transferAsset(assetKey:string, org:string,buyerOrgID:string, pric } } -async function readPrivateAssetAfterTransfer(assetKey:string, org:string, contract:Contract):Promise { +async function readPrivateAssetAfterTransfer(contract:ContractWrapper, assetKey:string, org:string):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); + const resultString = await contract.evaluateTransaction('GetAssetPrivateProperties', assetKey); + const result = Asset.parse(resultString); console.log('*** Result:', result); } @@ -416,7 +369,7 @@ async function readPrivateAssetAfterTransfer(assetKey:string, org:string, contra } } -async function changePublicDescriptionAfterTransfer(assetKey:string, org:string, description:string,contract:Contract):Promise { +async function changePublicDescriptionAfterTransfer(contract:ContractWrapper, assetKey:string, org:string, description:string):Promise { try { console.log(`${GREEN}--> Submit Transaction: changePublicDescription ${assetKey}, as ${org} - endorse by ${org}${RESET}`); if(org===mspIdOrg1){ @@ -431,4 +384,4 @@ async function changePublicDescriptionAfterTransfer(assetKey:string, org:string, } 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 index e10f8bd6..dd7159e3 100644 --- a/asset-transfer-secured-agreement/application-gateway-typescript/src/connect.ts +++ b/asset-transfer-secured-agreement/application-gateway-typescript/src/connect.ts @@ -15,7 +15,7 @@ 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'); +export const cryptoPathOrg1 = path.resolve(__dirname, '..', '..', '..', '../../sample-2.4.3/fabric-samples/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'); @@ -32,7 +32,7 @@ export const cryptoPathOrg2 = path.resolve( '..', '..', '..', - 'test-network', + '../../sample-2.4.3/fabric-samples/test-network', 'organizations', 'peerOrganizations', 'org2.example.com' diff --git a/asset-transfer-secured-agreement/application-gateway-typescript/src/contractWrapper.ts b/asset-transfer-secured-agreement/application-gateway-typescript/src/contractWrapper.ts new file mode 100644 index 00000000..fc62948b --- /dev/null +++ b/asset-transfer-secured-agreement/application-gateway-typescript/src/contractWrapper.ts @@ -0,0 +1,33 @@ +/* + * Copyright IBM Corp. All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ +import { Contract, ProposalOptions } from '@hyperledger/fabric-gateway'; +import { TextDecoder } from 'util'; + +export class ContractWrapper { + + contract?: Contract; + utf8Decoder: TextDecoder = new TextDecoder(); + + public constructor(contract:Contract) { + this.contract = contract; + } + + public async submit(transactionName:string, options: ProposalOptions ) { + await this.contract?.submit(transactionName, options); + return; + } + + public async evaluate(transactionName:string, options: ProposalOptions): Promise { + const resultBytes = await this.contract?.evaluate(transactionName, options); + const result = this.utf8Decoder.decode(resultBytes); + return result; + } + + public async evaluateTransaction(transactionName:string, ...args: (string | Uint8Array)[]): Promise { + const resultBytes = await this.contract?.evaluateTransaction(transactionName, ...args); + return this.utf8Decoder.decode(resultBytes); + } +} \ No newline at end of file diff --git a/asset-transfer-secured-agreement/application-gateway-typescript/src/utils.ts b/asset-transfer-secured-agreement/application-gateway-typescript/src/utils.ts new file mode 100644 index 00000000..b7de50ff --- /dev/null +++ b/asset-transfer-secured-agreement/application-gateway-typescript/src/utils.ts @@ -0,0 +1,112 @@ +/* + * Copyright IBM Corp. All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +export const RED = '\x1b[31m\n'; +export const GREEN = '\x1b[32m\n'; +export const RESET = '\x1b[0m'; + +export interface asset { + objectType: string, + assetID: string, + ownerOrg: string, + publicDescription: string, +} + +export interface asset_properties { + object_type: string, + asset_id: string, + color: string, + size: number, + salt: string +} + +export interface asset_price { + asset_id: string, + price: number, + trade_id: string +} + +export interface asset_price { + asset_id: string, + price: number, + trade_id: string +} + +export class AssetProperties { + + asset_properties: asset_properties; + + private constructor (asset_properties: asset_properties) { + this.asset_properties = asset_properties; + } + + static instance(object_type: string, asset_id: string, color: string, size: number, salt: string): string { + const asset_properties : asset_properties = { + object_type, + asset_id, + color, + size, + salt, + }; + return new AssetProperties(asset_properties).serialize(); + } + + private serialize(): string { + return JSON.stringify(this.asset_properties); + } + +} + +export class Asset { + + asset: asset; + + private constructor (asset: asset) { + this.asset = asset; + } + + static instance( objectType: string, assetID: string, ownerOrg: string, publicDescription: string): string { + const asset = { + objectType, + assetID, + ownerOrg, + publicDescription + } + return new Asset(asset).serialize(); + } + + private serialize(): string { + return JSON.stringify(this.asset); + } + + static parse(asset: string): asset { + return JSON.parse(asset); + } + +} + +export class AssetPrice { + + asset_price: asset_price; + + constructor (asset_price : asset_price) { + this.asset_price = asset_price; + } + + static instance(asset_id: string, price:number, trade_id: string): string { + const asset_price = { + asset_id, + price, + trade_id + } + return new AssetPrice(asset_price).serialize() + } + + private serialize(): string { + return JSON.stringify(this.asset_price); + } + +} \ No newline at end of file