mirror of
https://github.com/hyperledger/fabric-samples.git
synced 2026-06-17 15:35:09 +00:00
121 lines
3 KiB
Go
121 lines
3 KiB
Go
package commands
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/hyperledger/fabric-gateway/pkg/client"
|
|
"github.com/hyperledger/fabric-protos-go-apiv2/peer"
|
|
)
|
|
|
|
const retries = 2
|
|
|
|
type Asset struct {
|
|
ID string `json:"ID"`
|
|
Color string `json:"Color"`
|
|
Size int `json:"Size"`
|
|
Owner string `json:"Owner"`
|
|
AppraisedValue float64 `json:"AppraisedValue"`
|
|
}
|
|
|
|
type contractCaller interface {
|
|
Submit(name string, options ...client.ProposalOption) ([]byte, error)
|
|
Evaluate(name string, options ...client.ProposalOption) ([]byte, error)
|
|
}
|
|
|
|
type AssetTransfer struct {
|
|
contract contractCaller
|
|
}
|
|
|
|
func NewAssetTransfer(contract *client.Contract) *AssetTransfer {
|
|
return &AssetTransfer{contract: contract}
|
|
}
|
|
|
|
func (a *AssetTransfer) CreateAsset(asset Asset) error {
|
|
data, err := json.Marshal(asset)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to marshal asset: %w", err)
|
|
}
|
|
_, err = a.contract.Submit("CreateAsset", client.WithArguments(string(data)))
|
|
return err
|
|
}
|
|
|
|
func (a *AssetTransfer) GetAllAssets() ([]Asset, error) {
|
|
result, err := a.contract.Evaluate("GetAllAssets")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if len(result) == 0 {
|
|
return []Asset{}, nil
|
|
}
|
|
|
|
var assets []Asset
|
|
if err := json.Unmarshal(result, &assets); err != nil {
|
|
return nil, fmt.Errorf("failed to unmarshal assets: %w", err)
|
|
}
|
|
return assets, nil
|
|
}
|
|
|
|
func (a *AssetTransfer) ReadAsset(id string) (*Asset, error) {
|
|
result, err := a.contract.Evaluate("ReadAsset", client.WithArguments(id))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var asset Asset
|
|
if err := json.Unmarshal(result, &asset); err != nil {
|
|
return nil, fmt.Errorf("failed to unmarshal asset: %w", err)
|
|
}
|
|
return &asset, nil
|
|
}
|
|
|
|
func (a *AssetTransfer) UpdateAsset(asset Asset) error {
|
|
data, err := json.Marshal(asset)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to marshal asset: %w", err)
|
|
}
|
|
return submitWithRetry(func() error {
|
|
_, err := a.contract.Submit("UpdateAsset", client.WithArguments(string(data)))
|
|
return err
|
|
})
|
|
}
|
|
|
|
func (a *AssetTransfer) DeleteAsset(id string) error {
|
|
return submitWithRetry(func() error {
|
|
_, err := a.contract.Submit("DeleteAsset", client.WithArguments(id))
|
|
return err
|
|
})
|
|
}
|
|
|
|
func (a *AssetTransfer) AssetExists(id string) (bool, error) {
|
|
result, err := a.contract.Evaluate("AssetExists", client.WithArguments(id))
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return string(result) == "true", nil
|
|
}
|
|
|
|
func (a *AssetTransfer) TransferAsset(id, newOwner, newOwnerOrg string) error {
|
|
fmt.Printf("transferring asset '%s' to %s, %s\n", id, newOwner, newOwnerOrg)
|
|
_, err := a.contract.Submit("TransferAsset", client.WithArguments(id, newOwner, newOwnerOrg))
|
|
return err
|
|
}
|
|
|
|
func submitWithRetry(submit func() error) error {
|
|
var lastErr error
|
|
for i := 0; i < retries; i++ {
|
|
err := submit()
|
|
if err == nil {
|
|
return nil
|
|
}
|
|
lastErr = err
|
|
|
|
var commitErr *client.CommitError
|
|
if errors.As(err, &commitErr) && commitErr.Code == peer.TxValidationCode_MVCC_READ_CONFLICT {
|
|
continue
|
|
}
|
|
break
|
|
}
|
|
return lastErr
|
|
}
|