fabric-samples/asset-transfer-secured-agreement/chaincode-go/asset_transfer_queries.go
Tiffany Harris 7b2dcbf2ed Rename GetAsset to ReadAsset
Signed-off-by: Tiffany Harris <tiffany.harris@ibm.com>
2020-06-10 08:43:33 -04:00

191 lines
6 KiB
Go

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package main
import (
"encoding/json"
"fmt"
"time"
"github.com/hyperledger/fabric-contract-api-go/contractapi"
)
// QueryResult structure used for handling result of query
type QueryResult struct {
Record *Asset
TxId string `json:"txId"`
Timestamp time.Time `json:"timestamp"`
}
type Agreement struct {
ID string `json:"asset_id"`
Price int `json:"price"`
TradeID string `json:"trade_id"`
}
// ReadAsset returns the public asset data
func (s *SmartContract) ReadAsset(ctx contractapi.TransactionContextInterface, assetID string) (*Asset, error) {
// since only public data is accessed in this function, no access control is required
assetJSON, err := ctx.GetStub().GetState(assetID)
if err != nil {
return nil, fmt.Errorf("failed to read from world state: %s", err.Error())
}
if assetJSON == nil {
return nil, fmt.Errorf("%s does not exist", assetID)
}
asset := new(Asset)
_ = json.Unmarshal(assetJSON, asset)
return asset, nil
}
// GetAssetPrivateProperties returns the immutable asset properties from owner's private data collection
func (s *SmartContract) GetAssetPrivateProperties(ctx contractapi.TransactionContextInterface, assetID string) (string, error) {
// Get client org id and verify it matches peer org id.
// In this scenario, client is only authorized to read/write private data from its own peer.
collection, err := getClientImplicitCollectionName(ctx)
if err != nil {
return "", err
}
immutableProperties, err := ctx.GetStub().GetPrivateData(collection, assetID)
if err != nil {
return "", fmt.Errorf("failed to read asset private properties from client org's collection: %s", err.Error())
}
if immutableProperties == nil {
return "", fmt.Errorf("asset private details does not exist in client org's collection: %s", assetID)
}
return string(immutableProperties), nil
}
// GetAssetSalesPrice returns the sales price as an integer
func (s *SmartContract) GetAssetSalesPrice(ctx contractapi.TransactionContextInterface, assetID string) (string, error) {
return getAssetPrice(ctx, assetID, typeAssetForSale)
}
// GetAssetBidPrice returns the bid price as an integer
func (s *SmartContract) GetAssetBidPrice(ctx contractapi.TransactionContextInterface, assetID string) (string, error) {
return getAssetPrice(ctx, assetID, typeAssetBid)
}
// getAssetPrice gets the bid or ask price from caller's implicit private data collection
func getAssetPrice(ctx contractapi.TransactionContextInterface, assetID string, priceType string) (string, error) {
collection, err := getClientImplicitCollectionName(ctx)
if err != nil {
return "", err
}
assetPriceKey, err := ctx.GetStub().CreateCompositeKey(priceType, []string{assetID})
if err != nil {
return "", fmt.Errorf("failed to create composite key: %s", err.Error())
}
assetPriceJSON, err := ctx.GetStub().GetPrivateData(collection, assetPriceKey)
if err != nil {
return "", fmt.Errorf("failed to read asset price from implicit private data collection: %s", err.Error())
}
if assetPriceJSON == nil {
return "", fmt.Errorf("asset price does not exist: %s", assetID)
}
return string(assetPriceJSON), nil
}
// QueryAssetSaleAgreements returns all of an organization's proposed sales
func (s *SmartContract) QueryAssetSaleAgreements(ctx contractapi.TransactionContextInterface) ([]Agreement, error) {
return queryAgreementsByType(ctx, typeAssetForSale)
}
// QueryAssetBuyAgreements returns all of an organization's proposed buys
func (s *SmartContract) QueryAssetBuyAgreements(ctx contractapi.TransactionContextInterface) ([]Agreement, error) {
return queryAgreementsByType(ctx, typeAssetBid)
}
func queryAgreementsByType(ctx contractapi.TransactionContextInterface, agreeType string) ([]Agreement, error) {
collection, err := getClientImplicitCollectionName(ctx)
if err != nil {
return nil, err
}
// Query for any object type starting with `agreeType`
agreementsIterator, err := ctx.GetStub().GetPrivateDataByPartialCompositeKey(collection, agreeType, []string{})
if err != nil {
return nil, fmt.Errorf("failed to read from private data collection: %s", err.Error())
}
defer agreementsIterator.Close()
agreements := []Agreement{}
for agreementsIterator.HasNext() {
resp, err := agreementsIterator.Next()
if err != nil {
return nil, err
}
newAgree := new(Agreement)
err = json.Unmarshal(resp.Value, newAgree)
if err != nil {
return nil, err
}
agreements = append(agreements, *newAgree)
}
return agreements, nil
}
// QueryAssetHistory returns the chain of custody for a asset since issuance
func (s *SmartContract) QueryAssetHistory(ctx contractapi.TransactionContextInterface, assetID string) ([]QueryResult, error) {
resultsIterator, err := ctx.GetStub().GetHistoryForKey(assetID)
if err != nil {
return nil, err
}
defer resultsIterator.Close()
records := []QueryResult{}
for resultsIterator.HasNext() {
response, err := resultsIterator.Next()
if err != nil {
return nil, err
}
asset := new(Asset)
err = json.Unmarshal(response.Value, asset)
if err != nil {
return nil, err
}
record := QueryResult{
TxId: response.TxId,
Timestamp: time.Unix(response.Timestamp.Seconds, int64(response.Timestamp.Nanos)),
Record: asset,
}
records = append(records, record)
}
return records, nil
}