From 5d139faea44ecc713f956adcc9231b28b0a49499 Mon Sep 17 00:00:00 2001 From: vishal Date: Wed, 3 Jun 2026 20:13:17 +0530 Subject: [PATCH] issue 1376 --- .../contracts/asset-transfer-go/README.md | 15 + .../asset-transfer-chaincode-vars.yml | 11 + .../contracts/asset-transfer-go/asset.go | 14 + .../contracts/asset-transfer-go/contract.go | 312 ++++++++++++++++++ .../contracts/asset-transfer-go/go.mod | 28 ++ .../contracts/asset-transfer-go/go.sum | 81 +++++ .../contracts/asset-transfer-go/main.go | 18 + 7 files changed, 479 insertions(+) create mode 100644 full-stack-asset-transfer-guide/contracts/asset-transfer-go/README.md create mode 100644 full-stack-asset-transfer-guide/contracts/asset-transfer-go/asset-transfer-chaincode-vars.yml create mode 100644 full-stack-asset-transfer-guide/contracts/asset-transfer-go/asset.go create mode 100644 full-stack-asset-transfer-guide/contracts/asset-transfer-go/contract.go create mode 100644 full-stack-asset-transfer-guide/contracts/asset-transfer-go/go.mod create mode 100644 full-stack-asset-transfer-guide/contracts/asset-transfer-go/go.sum create mode 100644 full-stack-asset-transfer-guide/contracts/asset-transfer-go/main.go diff --git a/full-stack-asset-transfer-guide/contracts/asset-transfer-go/README.md b/full-stack-asset-transfer-guide/contracts/asset-transfer-go/README.md new file mode 100644 index 00000000..8f24ccfa --- /dev/null +++ b/full-stack-asset-transfer-guide/contracts/asset-transfer-go/README.md @@ -0,0 +1,15 @@ +# Go chaincode for the full-stack asset transfer guide + +This folder contains a Go implementation of the `asset-transfer` smart contract used by the full-stack asset transfer guide. + +The contract implements the following operations: + +- `CreateAsset` +- `ReadAsset` +- `UpdateAsset` +- `DeleteAsset` +- `AssetExists` +- `TransferAsset` +- `GetAllAssets` + +The implementation preserves the same asset data model and state-based endorsement behavior as the existing TypeScript contract implementation. diff --git a/full-stack-asset-transfer-guide/contracts/asset-transfer-go/asset-transfer-chaincode-vars.yml b/full-stack-asset-transfer-guide/contracts/asset-transfer-go/asset-transfer-chaincode-vars.yml new file mode 100644 index 00000000..0838df68 --- /dev/null +++ b/full-stack-asset-transfer-guide/contracts/asset-transfer-go/asset-transfer-chaincode-vars.yml @@ -0,0 +1,11 @@ +# +# SPDX-License-Identifier: Apache-2.0 +# +--- +smart_contract_name: "asset-transfer" +smart_contract_version: "1.0.0" +smart_contract_sequence: 1 +smart_contract_package: "asset-transfer.tgz" +# smart_contract_constructor: "initLedger" +smart_contract_endorsement_policy: "" +smart_contract_collections_file: "" diff --git a/full-stack-asset-transfer-guide/contracts/asset-transfer-go/asset.go b/full-stack-asset-transfer-guide/contracts/asset-transfer-go/asset.go new file mode 100644 index 00000000..c3d544f9 --- /dev/null +++ b/full-stack-asset-transfer-guide/contracts/asset-transfer-go/asset.go @@ -0,0 +1,14 @@ +package main + +type Asset struct { + ID string `json:"ID"` + Color string `json:"Color"` + Owner string `json:"Owner"` + AppraisedValue int `json:"AppraisedValue"` + Size int `json:"Size"` +} + +type ownerIdentifier struct { + Org string `json:"org"` + User string `json:"user"` +} diff --git a/full-stack-asset-transfer-guide/contracts/asset-transfer-go/contract.go b/full-stack-asset-transfer-guide/contracts/asset-transfer-go/contract.go new file mode 100644 index 00000000..15450127 --- /dev/null +++ b/full-stack-asset-transfer-guide/contracts/asset-transfer-go/contract.go @@ -0,0 +1,312 @@ +package main + +import ( + "encoding/json" + "fmt" + "regexp" + + "github.com/hyperledger/fabric-chaincode-go/v2/pkg/statebased" + "github.com/hyperledger/fabric-contract-api-go/v2/contractapi" +) + +type SmartContract struct { + contractapi.Contract +} + +func (s *SmartContract) CreateAsset(ctx contractapi.TransactionContextInterface, asset Asset) error { + if asset.ID == "" { + return fmt.Errorf("Missing ID") + } + if asset.Owner == "" { + return fmt.Errorf("Missing Owner") + } + + exists, err := s.AssetExists(ctx, asset.ID) + if err != nil { + return err + } + if exists { + return fmt.Errorf("The asset %s already exists", asset.ID) + } + + ownerID, err := clientIdentifier(ctx, asset.Owner) + if err != nil { + return err + } + asset.Owner, err = toJSON(ownerID) + if err != nil { + return err + } + + assetBytes, err := json.Marshal(asset) + if err != nil { + return fmt.Errorf("failed to marshal asset: %v", err) + } + + if err := ctx.GetStub().PutState(asset.ID, assetBytes); err != nil { + return fmt.Errorf("failed to put asset state: %v", err) + } + + mspID, err := ctx.GetClientIdentity().GetMSPID() + if err != nil { + return fmt.Errorf("failed to get client MSPID: %v", err) + } + if err := setEndorsingOrgs(ctx, asset.ID, mspID); err != nil { + return err + } + + return ctx.GetStub().SetEvent("CreateAsset", assetBytes) +} + +func (s *SmartContract) ReadAsset(ctx contractapi.TransactionContextInterface, id string) (*Asset, error) { + asset, err := s.readAsset(ctx, id) + if err != nil { + return nil, err + } + return asset, nil +} + +func (s *SmartContract) readAsset(ctx contractapi.TransactionContextInterface, id string) (*Asset, error) { + assetBytes, err := ctx.GetStub().GetState(id) + if err != nil { + return nil, fmt.Errorf("failed to read asset: %v", err) + } + if len(assetBytes) == 0 { + return nil, fmt.Errorf("Sorry, asset %s has not been created", id) + } + + var asset Asset + if err := json.Unmarshal(assetBytes, &asset); err != nil { + return nil, fmt.Errorf("failed to unmarshal asset: %v", err) + } + + return &asset, nil +} + +func (s *SmartContract) UpdateAsset(ctx contractapi.TransactionContextInterface, assetUpdate Asset) error { + if assetUpdate.ID == "" { + return fmt.Errorf("No asset ID specified") + } + + existingAsset, err := s.readAsset(ctx, assetUpdate.ID) + if err != nil { + return err + } + + permission, err := hasWritePermission(ctx, existingAsset) + if err != nil { + return err + } + if !permission { + return fmt.Errorf("Only owner can update assets") + } + + updatedAsset := *existingAsset + if assetUpdate.Color != "" { + updatedAsset.Color = assetUpdate.Color + } + if assetUpdate.Size != 0 { + updatedAsset.Size = assetUpdate.Size + } + if assetUpdate.AppraisedValue != 0 { + updatedAsset.AppraisedValue = assetUpdate.AppraisedValue + } + updatedAsset.Owner = existingAsset.Owner + + updatedBytes, err := json.Marshal(updatedAsset) + if err != nil { + return fmt.Errorf("failed to marshal updated asset: %v", err) + } + + if err := ctx.GetStub().PutState(updatedAsset.ID, updatedBytes); err != nil { + return fmt.Errorf("failed to update asset state: %v", err) + } + + mspID, err := ctx.GetClientIdentity().GetMSPID() + if err != nil { + return fmt.Errorf("failed to get client MSPID: %v", err) + } + if err := setEndorsingOrgs(ctx, updatedAsset.ID, mspID); err != nil { + return err + } + + return ctx.GetStub().SetEvent("UpdateAsset", updatedBytes) +} + +func (s *SmartContract) DeleteAsset(ctx contractapi.TransactionContextInterface, id string) error { + asset, err := s.readAsset(ctx, id) + if err != nil { + return err + } + + permission, err := hasWritePermission(ctx, asset) + if err != nil { + return err + } + if !permission { + return fmt.Errorf("Only owner can delete assets") + } + + assetBytes, err := json.Marshal(asset) + if err != nil { + return fmt.Errorf("failed to marshal deleted asset: %v", err) + } + + if err := ctx.GetStub().DelState(id); err != nil { + return fmt.Errorf("failed to delete asset state: %v", err) + } + + if err := ctx.GetStub().SetEvent("DeleteAsset", assetBytes); err != nil { + return fmt.Errorf("failed to set delete event: %v", err) + } + + return nil +} + +func (s *SmartContract) AssetExists(ctx contractapi.TransactionContextInterface, id string) (bool, error) { + assetJSON, err := ctx.GetStub().GetState(id) + if err != nil { + return false, fmt.Errorf("failed to read asset state: %v", err) + } + + return len(assetJSON) > 0, nil +} + +func (s *SmartContract) TransferAsset(ctx contractapi.TransactionContextInterface, id string, newOwner string, newOwnerOrg string) error { + asset, err := s.readAsset(ctx, id) + if err != nil { + return err + } + + permission, err := hasWritePermission(ctx, asset) + if err != nil { + return err + } + if !permission { + return fmt.Errorf("Only owner can transfer assets") + } + + ownerID := ownerIdentifier{Org: newOwnerOrg, User: newOwner} + asset.Owner, err = toJSON(ownerID) + if err != nil { + return err + } + + assetBytes, err := json.Marshal(asset) + if err != nil { + return fmt.Errorf("failed to marshal transferred asset: %v", err) + } + + if err := ctx.GetStub().PutState(id, assetBytes); err != nil { + return fmt.Errorf("failed to update asset state: %v", err) + } + + if err := setEndorsingOrgs(ctx, id, newOwnerOrg); err != nil { + return err + } + + return ctx.GetStub().SetEvent("TransferAsset", assetBytes) +} + +func (s *SmartContract) GetAllAssets(ctx contractapi.TransactionContextInterface) ([]*Asset, error) { + iterator, err := ctx.GetStub().GetStateByRange("", "") + if err != nil { + return nil, fmt.Errorf("failed to get assets by range: %v", err) + } + defer iterator.Close() + + var assets []*Asset + for iterator.HasNext() { + queryResponse, err := iterator.Next() + if err != nil { + return nil, fmt.Errorf("failed to iterate assets: %v", err) + } + + var asset Asset + if err := json.Unmarshal(queryResponse.Value, &asset); err != nil { + continue + } + assets = append(assets, &asset) + } + + return assets, nil +} + +func hasWritePermission(ctx contractapi.TransactionContextInterface, asset *Asset) (bool, error) { + clientID, err := clientIdentifier(ctx, "") + if err != nil { + return false, err + } + + var owner ownerIdentifier + if err := json.Unmarshal([]byte(asset.Owner), &owner); err != nil { + return false, fmt.Errorf("failed to unmarshal owner identifier: %v", err) + } + + return clientID.Org == owner.Org, nil +} + +func clientIdentifier(ctx contractapi.TransactionContextInterface, user string) (ownerIdentifier, error) { + mspID, err := ctx.GetClientIdentity().GetMSPID() + if err != nil { + return ownerIdentifier{}, fmt.Errorf("failed to get client MSPID: %v", err) + } + + if user == "" { + commonName, err := clientCommonName(ctx) + if err != nil { + return ownerIdentifier{}, err + } + user = commonName + } + + return ownerIdentifier{Org: mspID, User: user}, nil +} + +func clientCommonName(ctx contractapi.TransactionContextInterface) (string, error) { + cert, err := ctx.GetClientIdentity().GetX509Certificate() + if err != nil { + return "", fmt.Errorf("failed to read client certificate: %v", err) + } + + if cert.Subject.CommonName != "" { + return cert.Subject.CommonName, nil + } + + matches := regexp.MustCompile(`^CN=(.*)$`).FindStringSubmatch(cert.Subject.String()) + if len(matches) != 2 { + return "", fmt.Errorf("unable to identify client identity common name: %s", cert.Subject.String()) + } + + return matches[1], nil +} + +func ownerIdentifier(user string, org string) ownerIdentifier { + return ownerIdentifier{Org: org, User: user} +} + +func toJSON(o interface{}) (string, error) { + bytes, err := json.Marshal(o) + if err != nil { + return "", fmt.Errorf("failed to marshal owner identifier: %v", err) + } + return string(bytes), nil +} + +func setEndorsingOrgs(ctx contractapi.TransactionContextInterface, ledgerKey string, orgs ...string) error { + policy, err := statebased.NewStateEP(nil) + if err != nil { + return fmt.Errorf("failed to create state endorsement policy: %v", err) + } + + if err := policy.AddOrgs(statebased.RoleTypePeer, orgs...); err != nil { + return fmt.Errorf("failed to add orgs to endorsement policy: %v", err) + } + + policyBytes, err := policy.Policy() + if err != nil { + return fmt.Errorf("failed to marshal endorsement policy: %v", err) + } + + return ctx.GetStub().SetStateValidationParameter(ledgerKey, policyBytes) +} diff --git a/full-stack-asset-transfer-guide/contracts/asset-transfer-go/go.mod b/full-stack-asset-transfer-guide/contracts/asset-transfer-go/go.mod new file mode 100644 index 00000000..2a3118bc --- /dev/null +++ b/full-stack-asset-transfer-guide/contracts/asset-transfer-go/go.mod @@ -0,0 +1,28 @@ +module github.com/hyperledger/fabric-samples/full-stack-asset-transfer-guide/contracts/asset-transfer-go + +go 1.23.0 + +require ( + github.com/hyperledger/fabric-chaincode-go/v2 v2.0.0 + github.com/hyperledger/fabric-contract-api-go/v2 v2.2.0 +) + +require ( + github.com/go-openapi/jsonpointer v0.21.0 // indirect + github.com/go-openapi/jsonreference v0.21.0 // indirect + github.com/go-openapi/spec v0.21.0 // indirect + github.com/go-openapi/swag v0.23.0 // indirect + github.com/hyperledger/fabric-protos-go-apiv2 v0.3.4 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect + github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect + github.com/xeipuuv/gojsonschema v1.2.0 // indirect + golang.org/x/net v0.38.0 // indirect + golang.org/x/sys v0.31.0 // indirect + golang.org/x/text v0.23.0 // indirect + google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect + google.golang.org/grpc v1.71.0 // indirect + google.golang.org/protobuf v1.36.4 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/full-stack-asset-transfer-guide/contracts/asset-transfer-go/go.sum b/full-stack-asset-transfer-guide/contracts/asset-transfer-go/go.sum new file mode 100644 index 00000000..dc8539ee --- /dev/null +++ b/full-stack-asset-transfer-guide/contracts/asset-transfer-go/go.sum @@ -0,0 +1,81 @@ +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= +github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= +github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= +github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= +github.com/go-openapi/spec v0.21.0 h1:LTVzPc3p/RzRnkQqLRndbAzjY0d0BCL72A6j3CdL9ZY= +github.com/go-openapi/spec v0.21.0/go.mod h1:78u6VdPw81XU44qEWGhtr982gJ5BWg2c0I5XwVMotYk= +github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= +github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/hyperledger/fabric-chaincode-go/v2 v2.0.0 h1:IhkHfrl5X/fVnmB6pWeCYCdIJRi9bxj+WTnVN8DtW3c= +github.com/hyperledger/fabric-chaincode-go/v2 v2.0.0/go.mod h1:PHHaFffjw7p7n9bmCfcm7RqDqYdivNEsJdiNIKZo5Lk= +github.com/hyperledger/fabric-contract-api-go/v2 v2.2.0 h1:rmUoBmciB0GL/miqcbJmJbgp5QTWoJUrZo+CNxrNLF4= +github.com/hyperledger/fabric-contract-api-go/v2 v2.2.0/go.mod h1:FeWeO/jwGjiME7ak3GufqKIcwkejtzrDG4QxbfKydWs= +github.com/hyperledger/fabric-protos-go-apiv2 v0.3.4 h1:YJrd+gMaeY0/vsN0aS0QkEKTivGoUnSRIXxGJ7KI+Pc= +github.com/hyperledger/fabric-protos-go-apiv2 v0.3.4/go.mod h1:bau/6AJhvEcu9GKKYHlDXAxXKzYNfhP6xu2GXuxEcFk= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= +github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= +go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= +go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= +go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= +go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= +go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= +go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= +go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk= +go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w= +go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= +go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= +golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= +golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= +golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= +golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f h1:BWUVssLB0HVOSY78gIdvk1dTVYtT1y8SBWtPYuTJ/6w= +google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg= +google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= +google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM= +google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/full-stack-asset-transfer-guide/contracts/asset-transfer-go/main.go b/full-stack-asset-transfer-guide/contracts/asset-transfer-go/main.go new file mode 100644 index 00000000..4859293a --- /dev/null +++ b/full-stack-asset-transfer-guide/contracts/asset-transfer-go/main.go @@ -0,0 +1,18 @@ +package main + +import ( + "log" + + "github.com/hyperledger/fabric-contract-api-go/v2/contractapi" +) + +func main() { + chaincode, err := contractapi.NewChaincode(new(SmartContract)) + if err != nil { + log.Panicf("Error creating asset-transfer chaincode: %v", err) + } + + if err := chaincode.Start(); err != nil { + log.Panicf("Error starting asset-transfer chaincode: %v", err) + } +}