Updated erc721 by additin TokenMinted event, changed marketplace buy method to not invoke erc20 transfer if price is 0, updated dependencies for erc20/721 to overcome deployment problem

This commit is contained in:
Serhii Romaniv 2023-05-18 19:20:58 +03:00
parent aa27103fbe
commit d003a24291
10 changed files with 904 additions and 2316 deletions

View file

@ -2,6 +2,17 @@
# Hyperledger Fabric Samples
## To build using docker image use the following command
`docker run --platform linux/amd64 --rm -v $(pwd)/token-erc-20/chaincode-go:/source golang:1.20-alpine /bin/sh -c "cd /source; go mod tidy; go mod vendor"`
`docker run --platform linux/amd64 --rm -v $(pwd)/token-erc-721/chaincode-go:/source golang:1.20-alpine /bin/sh -c "cd /source; go mod tidy; go mod vendor"`
`docker run --platform linux/amd64 --rm -v $(pwd)/marketplace/chaincode-go:/source golang:1.20-alpine /bin/sh -c "cd /source; go mod tidy; go mod vendor"`
`export PACKAGE_NAME=token-erc-20-v1; docker run --platform linux/amd64 --rm -v $(pwd)/token-erc-20/chaincode-go:/source -v $(pwd)/output:/output hyperledger/fabric-tools:2.5 peer lifecycle chaincode package -p /source --label $PACKAGE_NAME /output/$PACKAGE_NAME.zip`
`export PACKAGE_NAME=token-erc-721-v4; docker run --platform linux/amd64 --rm -v $(pwd)/token-erc-721/chaincode-go:/source -v $(pwd)/output:/output hyperledger/fabric-tools:2.5 peer lifecycle chaincode package -p /source --label $PACKAGE_NAME /output/$PACKAGE_NAME.zip`
`export PACKAGE_NAME=marketplace-v5; docker run --platform linux/amd64 --rm -v $(pwd)/marketplace/chaincode-go:/source -v $(pwd)/output:/output hyperledger/fabric-tools:2.5 peer lifecycle chaincode package -p /source --label $PACKAGE_NAME /output/$PACKAGE_NAME.zip`
`export PACKAGE_NAME=marketplace-v5; ff deploy fabric firefly-dev ./output/$PACKAGE_NAME.zip firefly $PACKAGE_NAME 0.0.1`
[![Build Status](https://dev.azure.com/Hyperledger/Fabric-Samples/_apis/build/status/Fabric-Samples?branchName=main)](https://dev.azure.com/Hyperledger/Fabric-Samples/_build/latest?definitionId=28&branchName=main)
You can use Fabric samples to get started working with Hyperledger Fabric, explore important Fabric features, and learn how to build applications that can interact with blockchain networks using the Fabric SDKs. To learn more about Hyperledger Fabric, visit the [Fabric documentation](https://hyperledger-fabric.readthedocs.io/en/latest).

View file

@ -5,13 +5,13 @@
package main
import (
"fmt"
"strconv"
"encoding/base64"
"encoding/json"
"encoding/base64"
"encoding/json"
"fmt"
"github.com/hyperledger/fabric-chaincode-go/shim"
"github.com/hyperledger/fabric-contract-api-go/contractapi"
"github.com/hyperledger/fabric-contract-api-go/metadata"
"github.com/hyperledger/fabric-chaincode-go/shim"
"strconv"
)
type MarketplaceContract struct {
@ -19,39 +19,39 @@ type MarketplaceContract struct {
}
type ListingItem struct {
TokenAddr string `json:"tokenAddr"`
Id string `json:"id"`
TokenAddr string `json:"tokenAddr"`
Id string `json:"id"`
}
type Listing struct {
ListingId string `json:"listingId"`
Creator string `json:"creator"`
Price int `json:"price"`
CurrencyAddr string `json:"currencyAddr"`
ListingId string `json:"listingId"`
Creator string `json:"creator"`
Price int `json:"price"`
CurrencyAddr string `json:"currencyAddr"`
}
type ListingCreated struct {
ListingId string `json:"listingId"`
Creator string `json:"creator"`
Price int `json:"price"`
CurrencyAddr string `json:"currencyAddr"`
Nfts []ListingItem `json:"nfts"`
Batches []ListingItem `json:"batches"`
Collections []ListingItem `json:"collections"`
ListingId string `json:"listingId"`
Creator string `json:"creator"`
Price int `json:"price"`
CurrencyAddr string `json:"currencyAddr"`
Nfts []ListingItem `json:"nfts"`
Batches []ListingItem `json:"batches"`
Collections []ListingItem `json:"collections"`
}
type ListingItemSold struct {
ListingId string `json:"listingId"`
Creator string `json:"creator"`
Price int `json:"price"`
TokenAddr string `json:"tokenAddr"`
CurrencyAddr string `json:"currencyAddr"`
TokenId string `json:"tokenId"`
Buyer string `json:"buyer"`
ListingId string `json:"listingId"`
Creator string `json:"creator"`
Price int `json:"price"`
TokenAddr string `json:"tokenAddr"`
CurrencyAddr string `json:"currencyAddr"`
TokenId string `json:"tokenId"`
Buyer string `json:"buyer"`
}
type ListingCanceled struct {
ListingId string `json:"listingId"`
ListingId string `json:"listingId"`
}
const listingPrefix = "listing"
@ -78,179 +78,180 @@ func _readListing(ctx contractapi.TransactionContextInterface, listingId string)
func (c *MarketplaceContract) List(ctx contractapi.TransactionContextInterface, creator string, listingId string, currencyAddr string, nfts []ListingItem, batches []ListingItem, collections []ListingItem, price int) (*Listing, error) {
listing := new(Listing)
listing.ListingId = listingId
listing.Creator = creator
listing.Price = price
listing.CurrencyAddr = currencyAddr
listing := new(Listing)
listing.ListingId = listingId
listing.Creator = creator
listing.Price = price
listing.CurrencyAddr = currencyAddr
listingKey, err := ctx.GetStub().CreateCompositeKey(listingPrefix, []string{listingId})
listingKey, err := ctx.GetStub().CreateCompositeKey(listingPrefix, []string{listingId})
if err != nil {
return nil, fmt.Errorf("failed to CreateCompositeKey to nftKey: %v", err)
}
if err != nil {
return nil, fmt.Errorf("failed to CreateCompositeKey to nftKey: %v", err)
}
listingBytes, err := json.Marshal(listing)
if err != nil {
return nil, fmt.Errorf("failed to marshal listing: %v", err)
}
listingBytes, err := json.Marshal(listing)
if err != nil {
return nil, fmt.Errorf("failed to marshal listing: %v", err)
}
err = ctx.GetStub().PutState(listingKey, listingBytes)
if err != nil {
return nil, fmt.Errorf("failed to PutState listingBytes %s: %v", listingBytes, err)
}
err = ctx.GetStub().PutState(listingKey, listingBytes)
if err != nil {
return nil, fmt.Errorf("failed to PutState listingBytes %s: %v", listingBytes, err)
}
listingCreated := new(ListingCreated)
listingCreated.ListingId = listingId
listingCreated.Creator = creator
listingCreated.Price = price
listingCreated.CurrencyAddr = currencyAddr
listingCreated.Nfts = nfts
listingCreated.Batches = batches
listingCreated.Collections = collections
listingCreated := new(ListingCreated)
listingCreated.ListingId = listingId
listingCreated.Creator = creator
listingCreated.Price = price
listingCreated.CurrencyAddr = currencyAddr
listingCreated.Nfts = nfts
listingCreated.Batches = batches
listingCreated.Collections = collections
listingCreatedBytes, err := json.Marshal(listingCreated)
if err != nil {
return nil, fmt.Errorf("failed to marshal listingCreatedBytes: %v", err)
}
listingCreatedBytes, err := json.Marshal(listingCreated)
if err != nil {
return nil, fmt.Errorf("failed to marshal listingCreatedBytes: %v", err)
}
err = ctx.GetStub().SetEvent("ListingCreated", listingCreatedBytes)
if err != nil {
return nil, fmt.Errorf("failed to SetEvent listingCreatedBytes %s: %v", listingCreatedBytes, err)
}
err = ctx.GetStub().SetEvent("ListingCreated", listingCreatedBytes)
if err != nil {
return nil, fmt.Errorf("failed to SetEvent listingCreatedBytes %s: %v", listingCreatedBytes, err)
}
return listing, nil
return listing, nil
}
func (c *MarketplaceContract) CancelListing(ctx contractapi.TransactionContextInterface, listingId string) (bool, error) {
sender64, err := ctx.GetClientIdentity().GetID()
if err != nil {
return false, fmt.Errorf("failed to GetClientIdentity: %v", err)
}
sender64, err := ctx.GetClientIdentity().GetID()
if err != nil {
return false, fmt.Errorf("failed to GetClientIdentity: %v", err)
}
senderBytes, err := base64.StdEncoding.DecodeString(sender64)
if err != nil {
return false, fmt.Errorf("failed to DecodeString senderBytes: %v", err)
}
sender := string(senderBytes)
senderBytes, err := base64.StdEncoding.DecodeString(sender64)
if err != nil {
return false, fmt.Errorf("failed to DecodeString senderBytes: %v", err)
}
sender := string(senderBytes)
listing, err := _readListing(ctx, listingId);
if err != nil {
return false, fmt.Errorf("failed to _readListing: %v", err)
}
listing, err := _readListing(ctx, listingId)
if err != nil {
return false, fmt.Errorf("failed to _readListing: %v", err)
}
if (listing.Creator != sender) {
return false, fmt.Errorf("sender is not owner of listing")
}
if listing.Creator != sender {
return false, fmt.Errorf("sender is not owner of listing")
}
listingKey, err := ctx.GetStub().CreateCompositeKey(listingPrefix, []string{listingId})
listingKey, err := ctx.GetStub().CreateCompositeKey(listingPrefix, []string{listingId})
if err != nil {
return false, fmt.Errorf("failed to CreateCompositeKey to nftKey: %v", err)
}
if err != nil {
return false, fmt.Errorf("failed to CreateCompositeKey to nftKey: %v", err)
}
err = ctx.GetStub().DelState(listingKey)
if err != nil {
return false, fmt.Errorf("failed to DelState %s: %v", listingKey, err)
}
err = ctx.GetStub().DelState(listingKey)
if err != nil {
return false, fmt.Errorf("failed to DelState %s: %v", listingKey, err)
}
listingCanceled := new(ListingCanceled)
listingCanceled.ListingId = listingId
listingCanceled := new(ListingCanceled)
listingCanceled.ListingId = listingId
listingCanceledBytes, err := json.Marshal(listingCanceled)
if err != nil {
return false, fmt.Errorf("failed to marshal listingCanceledBytes: %v", err)
}
listingCanceledBytes, err := json.Marshal(listingCanceled)
if err != nil {
return false, fmt.Errorf("failed to marshal listingCanceledBytes: %v", err)
}
err = ctx.GetStub().SetEvent("ListingCanceled", listingCanceledBytes)
if err != nil {
return false, fmt.Errorf("failed to SetEvent listingCanceledBytes %s: %v", listingCanceledBytes, err)
}
err = ctx.GetStub().SetEvent("ListingCanceled", listingCanceledBytes)
if err != nil {
return false, fmt.Errorf("failed to SetEvent listingCanceledBytes %s: %v", listingCanceledBytes, err)
}
return true, nil
return true, nil
}
func (c *MarketplaceContract) Buy(ctx contractapi.TransactionContextInterface, buyer string, listingId string, tokenAddr string, tokenId string) (bool, error) {
listing, err := _readListing(ctx, listingId);
if err != nil {
return false, fmt.Errorf("failed to _readListing: %v", err)
}
listing, err := _readListing(ctx, listingId)
if err != nil {
return false, fmt.Errorf("failed to _readListing: %v", err)
}
// payment
stub := ctx.GetStub()
// payment
stub := ctx.GetStub()
params := []string{"TransferFrom", buyer, listing.Creator, strconv.Itoa(listing.Price)}
invokeArgs := make([][]byte, len(params))
if listing.Price > 0 {
params := []string{"TransferFrom", buyer, listing.Creator, strconv.Itoa(listing.Price)}
invokeArgs := make([][]byte, len(params))
for i, arg := range params {
invokeArgs[i] = []byte(arg)
}
for i, arg := range params {
invokeArgs[i] = []byte(arg)
}
response := stub.InvokeChaincode(listing.CurrencyAddr, invokeArgs, "firefly")
response := stub.InvokeChaincode(listing.CurrencyAddr, invokeArgs, "firefly")
if response.Status != shim.OK {
return false, fmt.Errorf("Failed to invoke erc-20 chaincode. Got error: %v %s %s %s", response, buyer, listing.Creator, strconv.Itoa(listing.Price))
}
if response.Status != shim.OK {
return false, fmt.Errorf("Failed to invoke erc-20 chaincode. Got error: %v %s %s %s", response, buyer, listing.Creator, strconv.Itoa(listing.Price))
}
}
// transfer tokens
tokenTransferParams := []string{"TransferFrom", listing.Creator, buyer, tokenId}
tokenTransferInvokeArgs := make([][]byte, len(tokenTransferParams))
// transfer tokens
tokenTransferParams := []string{"TransferFrom", listing.Creator, buyer, tokenId}
tokenTransferInvokeArgs := make([][]byte, len(tokenTransferParams))
for i, arg := range tokenTransferParams {
tokenTransferInvokeArgs[i] = []byte(arg)
}
for i, arg := range tokenTransferParams {
tokenTransferInvokeArgs[i] = []byte(arg)
}
tokenTransferResponse := stub.InvokeChaincode(tokenAddr, tokenTransferInvokeArgs, "firefly")
tokenTransferResponse := stub.InvokeChaincode(tokenAddr, tokenTransferInvokeArgs, "firefly")
if tokenTransferResponse.Status != shim.OK {
return false, fmt.Errorf("Failed to invoke erc-721 chaincode. Got error: %s", tokenTransferResponse.Payload)
}
if tokenTransferResponse.Status != shim.OK {
return false, fmt.Errorf("Failed to invoke erc-721 chaincode. Got error: %s", tokenTransferResponse.Payload)
}
listingItemSold := new(ListingItemSold)
listingItemSold.ListingId = listingId
listingItemSold.Creator = listing.Creator
listingItemSold.Price = listing.Price
listingItemSold.CurrencyAddr = listing.CurrencyAddr
listingItemSold.TokenAddr = tokenAddr
listingItemSold.Buyer = buyer
listingItemSold.TokenId = tokenId
listingItemSold := new(ListingItemSold)
listingItemSold.ListingId = listingId
listingItemSold.Creator = listing.Creator
listingItemSold.Price = listing.Price
listingItemSold.CurrencyAddr = listing.CurrencyAddr
listingItemSold.TokenAddr = tokenAddr
listingItemSold.Buyer = buyer
listingItemSold.TokenId = tokenId
listingItemSoldBytes, err := json.Marshal(listingItemSold)
if err != nil {
return false, fmt.Errorf("failed to marshal listingItemSoldBytes: %v", err)
}
listingItemSoldBytes, err := json.Marshal(listingItemSold)
if err != nil {
return false, fmt.Errorf("failed to marshal listingItemSoldBytes: %v", err)
}
err = ctx.GetStub().SetEvent("ListingItemSold", listingItemSoldBytes)
if err != nil {
return false, fmt.Errorf("failed to SetEvent listingItemSoldBytes %s: %v", listingItemSoldBytes, err)
}
err = ctx.GetStub().SetEvent("ListingItemSold", listingItemSoldBytes)
if err != nil {
return false, fmt.Errorf("failed to SetEvent listingItemSoldBytes %s: %v", listingItemSoldBytes, err)
}
return true, nil
return true, nil
}
func main() {
marketplaceContract := new(MarketplaceContract)
marketplaceContract.Info.Version = "0.0.1"
marketplaceContract.Info.Description = "MarketplaceContract fabric port"
marketplaceContract.Info.License = new(metadata.LicenseMetadata)
marketplaceContract.Info.License.Name = "Apache-2.0"
marketplaceContract.Info.Contact = new(metadata.ContactMetadata)
marketplaceContract.Info.Contact.Name = "Marketplace"
marketplaceContract := new(MarketplaceContract)
marketplaceContract.Info.Version = "0.0.1"
marketplaceContract.Info.Description = "MarketplaceContract fabric port"
marketplaceContract.Info.License = new(metadata.LicenseMetadata)
marketplaceContract.Info.License.Name = "Apache-2.0"
marketplaceContract.Info.Contact = new(metadata.ContactMetadata)
marketplaceContract.Info.Contact.Name = "Marketplace"
chaincode, err := contractapi.NewChaincode(marketplaceContract)
chaincode.Info.Title = "Marketplace chaincode"
chaincode.Info.Version = "0.0.1"
chaincode, err := contractapi.NewChaincode(marketplaceContract)
chaincode.Info.Title = "Marketplace chaincode"
chaincode.Info.Version = "0.0.1"
if err != nil {
panic("Could not create chaincode from MarketplaceContract." + err.Error())
}
if err != nil {
panic("Could not create chaincode from MarketplaceContract." + err.Error())
}
err = chaincode.Start()
err = chaincode.Start()
if err != nil {
panic("Failed to start chaincode. " + err.Error())
}
if err != nil {
panic("Failed to start chaincode. " + err.Error())
}
}

View file

@ -0,0 +1,305 @@
{
"namespace": "default",
"name": "marketplace",
"description": "Spec interface for the Marketplace golang chaincode",
"version": "0.0.1",
"methods": [
{
"name": "List",
"pathname": "",
"description": "Lists tokens",
"params": [
{
"name": "creator",
"schema": {
"type": "string"
}
},
{
"name": "listingId",
"schema": {
"type": "string"
}
},
{
"name": "currencyAddr",
"schema": {
"type": "string"
}
},
{
"name": "nfts",
"schema": {
"type": "array",
"items": {
"type": "object",
"properties": {
"TokenAddr": {
"type": "string"
},
"Id": {
"type": "string"
}
}
}
}
},
{
"name": "batches",
"schema": {
"type": "array",
"items": {
"type": "object",
"properties": {
"TokenAddr": {
"type": "string"
},
"Id": {
"type": "string"
}
}
}
}
},
{
"name": "collections",
"schema": {
"type": "array",
"items": {
"type": "object",
"properties": {
"TokenAddr": {
"type": "string"
},
"Id": {
"type": "string"
}
}
}
}
},
{
"name": "price",
"schema": {
"type": "integer"
}
}
],
"returns": [
{
"name": "success",
"schema": {
"type": "string"
}
},
{
"name": "error",
"schema": {
"type": "string"
}
}
]
},
{
"name": "CancelListing",
"pathname": "",
"description": "Cancel Listing",
"params": [
{
"name": "listingId",
"schema": {
"type": "string"
}
}
],
"returns": [
{
"name": "success",
"schema": {
"type": "boolean"
}
},
{
"name": "error",
"schema": {
"type": "string"
}
}
]
},
{
"name": "Buy",
"pathname": "",
"description": "Buy tokens",
"params": [
{
"name": "buyer",
"schema": {
"type": "string"
}
},
{
"name": "listingId",
"schema": {
"type": "string"
}
},
{
"name": "tokenAddr",
"schema": {
"type": "string"
}
},
{
"name": "tokenId",
"schema": {
"type": "string"
}
}
],
"returns": [
{
"name": "success",
"schema": {
"type": "string"
}
},
{
"name": "error",
"schema": {
"type": "string"
}
}
]
}
],
"events": [
{
"name": "ListingCreated",
"params": [
{
"name": "listingId",
"schema": {
"type": "string"
}
},
{
"name": "creator",
"schema": {
"type": "string"
}
},
{
"name": "price",
"schema": {
"type": "integer"
}
},
{
"name": "currencyAddr",
"schema": {
"type": "string"
}
},
{
"name": "nfts",
"schema": {
"type": "array",
"items": {
"type": "object",
"properties": {
"TokenAddr": {
"type": "string"
},
"Id": {
"type": "string"
}
}
}
}
},
{
"name": "batches",
"schema": {
"type": "array",
"items": {
"type": "object",
"properties": {
"TokenAddr": {
"type": "string"
},
"Id": {
"type": "string"
}
}
}
}
},
{
"name": "collections",
"schema": {
"type": "array",
"items": {
"type": "object",
"properties": {
"TokenAddr": {
"type": "string"
},
"Id": {
"type": "string"
}
}
}
}
}
]
},
{
"name": "ListingItemSold",
"params": [
{
"name": "listingId",
"schema": {
"type": "string"
}
},
{
"name": "creator",
"schema": {
"type": "string"
}
},
{
"name": "price",
"schema": {
"type": "integer"
}
},
{
"name": "tokenAddr",
"schema": {
"type": "string"
}
},
{
"name": "currencyAddr",
"schema": {
"type": "string"
}
},
{
"name": "tokenId",
"schema": {
"type": "string"
}
},
{
"name": "buyer",
"schema": {
"type": "string"
}
}
]
}
]
}

View file

@ -1,8 +1,8 @@
module github.com/hyperledger/fabric-samples/token-erc-20/chaincode-go
go 1.17
go 1.18
require github.com/hyperledger/fabric-contract-api-go v1.2.1
require github.com/hyperledger/fabric-contract-api-go v1.2.0
require (
github.com/go-openapi/jsonpointer v0.19.5 // indirect

File diff suppressed because it is too large Load diff

363
token-erc-20/erc20_ffi.json Normal file
View file

@ -0,0 +1,363 @@
{
"namespace": "default",
"name": "token_erc_20",
"description": "Spec interface for the TokenERC20 golang chaincode",
"version": "0.0.2",
"methods": [
{
"name": "BalanceOf",
"pathname": "",
"description": "returns the balance of the given account",
"params": [
{
"name": "account",
"schema": {
"type": "string"
}
}
],
"returns": [
{
"name": "balance",
"schema": {
"type": "integer"
}
}
]
},
{
"name": "Approve",
"pathname": "",
"description": "allows the spender to withdraw from the calling client's token account",
"params": [
{
"name": "spender",
"schema": {
"type": "string"
}
},
{
"name": "value",
"schema": {
"type": "integer"
}
}
],
"returns": [
{
"name": "success",
"schema": {
"type": "boolean"
}
}
]
},
{
"name": "Approve",
"pathname": "",
"description": "allows the spender to withdraw from the calling client's token account",
"params": [
{
"name": "spender",
"schema": {
"type": "string"
}
},
{
"name": "value",
"schema": {
"type": "integer"
}
}
],
"returns": [
{
"name": "success",
"schema": {
"type": "boolean"
}
}
]
},
{
"name": "TransferFrom",
"pathname": "",
"description": "transfers the value amount from the \"from\" address to the \"to\" address",
"params": [
{
"name": "from",
"schema": {
"type": "string"
}
},
{
"name": "to",
"schema": {
"type": "string"
}
},
{
"name": "value",
"schema": {
"type": "integer"
}
}
],
"returns": [
{
"name": "success",
"schema": {
"type": "boolean"
}
}
]
},
{
"name": "Initialize",
"pathname": "",
"description": "Initialize the contract with the name and symbol of the token",
"params": [
{
"name": "name",
"schema": {
"type": "string"
}
},
{
"name": "symbol",
"schema": {
"type": "string"
}
},
{
"name": "decimals",
"schema": {
"type": "string"
}
}
],
"returns": [
{
"name": "success",
"schema": {
"type": "boolean"
}
}
]
},
{
"name": "Name",
"pathname": "",
"description": "Returns the name of the token",
"params": [],
"returns": [
{
"name": "name",
"schema": {
"type": "string"
}
}
]
},
{
"name": "Symbol",
"pathname": "",
"description": "Returns the symbol of the token",
"params": [],
"returns": [
{
"name": "symbol",
"schema": {
"type": "string"
}
}
]
},
{
"name": "TotalSupply",
"pathname": "",
"description": "Returns the total supply of tokens",
"params": [],
"returns": [
{
"name": "count",
"schema": {
"type": "integer"
}
}
]
},
{
"name": "Burn",
"pathname": "",
"description": "redeems tokens the minter's account balance",
"params": [
{
"name": "amount",
"schema": {
"type": "integer"
}
}
],
"returns": [
{
"name": "success",
"schema": {
"type": "boolean"
}
}
]
},
{
"name": "ClientAccountBalance",
"pathname": "",
"description": "Returns the balance of the requesting client's account",
"params": [],
"returns": [
{
"name": "balance",
"schema": {
"type": "integer"
}
}
]
},
{
"name": "ClientAccountID",
"pathname": "",
"description": "Returns the ID of the requesting client's account",
"params": [],
"returns": [
{
"name": "clientAccountID",
"schema": {
"type": "string"
}
}
]
},
{
"name": "Mint",
"pathname": "",
"description": "creates new tokens and adds them to minter's account balance",
"params": [
{
"name": "amount",
"schema": {
"type": "integer"
}
}
],
"returns": [
{
"name": "success",
"schema": {
"type": "boolean"
}
}
]
},
{
"name": "Transfer",
"pathname": "",
"description": "transfers tokens from client account to recipient account",
"params": [
{
"name": "recipient",
"schema": {
"type": "string"
}
},
{
"name": "amount",
"schema": {
"type": "integer"
}
}
],
"returns": [
{
"name": "success",
"schema": {
"type": "boolean"
}
}
]
},
{
"name": "Allowance",
"pathname": "",
"description": "returns the amount still available for the spender to withdraw from the owner",
"params": [
{
"name": "owner",
"schema": {
"type": "string"
}
},
{
"name": "spender",
"schema": {
"type": "string"
}
}
],
"returns": [
{
"name": "allowance",
"schema": {
"type": "integer"
}
}
]
}
],
"events": [
{
"name": "Transfer",
"params": [
{
"name": "from",
"schema": {
"type": "string"
}
},
{
"name": "to",
"schema": {
"type": "string"
}
},
{
"name": "value",
"schema": {
"type": "integer"
}
}
]
},
{
"name": "Approval",
"params": [
{
"name": "from",
"schema": {
"type": "string"
}
},
{
"name": "to",
"schema": {
"type": "string"
}
},
{
"name": "value",
"schema": {
"type": "integer"
}
}
]
}
]
}

View file

@ -230,30 +230,29 @@ func (c *TokenERC721Contract) SetLock(ctx contractapi.TransactionContextInterfac
}
lockUnlockEvent := new(LockUnlock)
lockUnlockEvent.Owner = sender
lockUnlockEvent.TokenId = nft.TokenId
lockUnlockEvent.Owner = sender
lockUnlockEvent.TokenId = nft.TokenId
lockUnlockEventBytes, err := json.Marshal(lockUnlockEvent)
if err != nil {
return false, fmt.Errorf("failed to marshal lockUnlockEventBytes: %v", err)
}
lockUnlockEventBytes, err := json.Marshal(lockUnlockEvent)
if err != nil {
return false, fmt.Errorf("failed to marshal lockUnlockEventBytes: %v", err)
}
if (nft.Locked) {
err = ctx.GetStub().SetEvent("Lock", lockUnlockEventBytes)
if err != nil {
return false, fmt.Errorf("failed to SetEvent Lock: %v", err)
}
} else {
err = ctx.GetStub().SetEvent("Unlock", lockUnlockEventBytes)
if err != nil {
return false, fmt.Errorf("failed to SetEvent Unlock: %v", err)
}
}
if nft.Locked {
err = ctx.GetStub().SetEvent("Lock", lockUnlockEventBytes)
if err != nil {
return false, fmt.Errorf("failed to SetEvent Lock: %v", err)
}
} else {
err = ctx.GetStub().SetEvent("Unlock", lockUnlockEventBytes)
if err != nil {
return false, fmt.Errorf("failed to SetEvent Unlock: %v", err)
}
}
return true, nil
}
// SetApprovalForAll enables or disables approval for a third party ("operator")
// to manage all the message sender's assets
// param {String} operator A client to add to the set of authorized operators
@ -404,9 +403,9 @@ func (c *TokenERC721Contract) TransferFrom(ctx contractapi.TransactionContextInt
return false, fmt.Errorf("failed to _readNFT : %v", err)
}
if (nft.Locked) {
return false, fmt.Errorf("Token %s is locked", nft.TokenId)
}
if nft.Locked {
return false, fmt.Errorf("Token %s is locked", nft.TokenId)
}
owner := nft.Owner
operator := nft.Approved
@ -707,19 +706,19 @@ func (c *TokenERC721Contract) MintWithTokenURI(ctx contractapi.TransactionContex
}
// Emit the Transfer event
transferEvent := new(Transfer)
transferEvent.From = "0x0"
transferEvent.To = minter
transferEvent.TokenId = tokenId
mintedEvent := new(TokenMinted)
mintedEvent.To = minter
mintedEvent.TokenId = tokenId
mintedEvent.TokenURI = tokenURI
transferEventBytes, err := json.Marshal(transferEvent)
mintedEventBytes, err := json.Marshal(mintedEvent)
if err != nil {
return nil, fmt.Errorf("failed to marshal transferEventBytes: %v", err)
}
err = ctx.GetStub().SetEvent("Transfer", transferEventBytes)
err = ctx.GetStub().SetEvent("TokenMinted", mintedEventBytes)
if err != nil {
return nil, fmt.Errorf("failed to SetEvent transferEventBytes %s: %v", transferEventBytes, err)
return nil, fmt.Errorf("failed to SetEvent mintedEventBytes %s: %v", mintedEventBytes, err)
}
return nft, nil
@ -759,9 +758,9 @@ func (c *TokenERC721Contract) Burn(ctx contractapi.TransactionContextInterface,
return false, fmt.Errorf("non-fungible token %s is not owned by %s", tokenId, owner)
}
if (nft.Locked) {
return false, fmt.Errorf("Token %s is locked", nft.TokenId)
}
if nft.Locked {
return false, fmt.Errorf("Token %s is locked", nft.TokenId)
}
// Delete the token
nftKey, err := ctx.GetStub().CreateCompositeKey(nftPrefix, []string{tokenId})

View file

@ -26,11 +26,17 @@ type Transfer struct {
}
type LockUnlock struct {
Owner string `json:"owner"`
TokenId string `json:"tokenId"`
Owner string `json:"owner"`
TokenId string `json:"tokenId"`
}
type Burn struct {
Owner string `json:"owner"`
TokenId string `json:"tokenId"`
Owner string `json:"owner"`
TokenId string `json:"tokenId"`
}
type TokenMinted struct {
To string `json:"to"`
TokenId string `json:"tokenId"`
TokenURI string `json:"tokenURI"`
}

View file

@ -1,10 +1,10 @@
module github.com/hyperledger/fabric-samples/token-erc-721/chaincode-go
go 1.17
go 1.18
require (
github.com/hyperledger/fabric-chaincode-go v0.0.0-20230228194215-b84622ba6a7a
github.com/hyperledger/fabric-contract-api-go v1.2.1
github.com/hyperledger/fabric-chaincode-go v0.0.0-20220720122508-9207360bbddd
github.com/hyperledger/fabric-contract-api-go v1.2.0
github.com/hyperledger/fabric-protos-go v0.3.0
github.com/stretchr/testify v1.8.2
)
@ -13,7 +13,7 @@ require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/jsonreference v0.20.0 // indirect
github.com/go-openapi/spec v0.20.8 // indirect
github.com/go-openapi/spec v0.20.6 // indirect
github.com/go-openapi/swag v0.21.1 // indirect
github.com/gobuffalo/envy v1.10.1 // indirect
github.com/gobuffalo/packd v1.0.1 // indirect
@ -28,11 +28,11 @@ require (
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.7.0 // indirect
golang.org/x/sys v0.5.0 // indirect
golang.org/x/text v0.7.0 // indirect
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect
google.golang.org/grpc v1.53.0 // indirect
golang.org/x/net v0.0.0-20220708220712-1185a9018129 // indirect
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
golang.org/x/text v0.3.7 // indirect
google.golang.org/genproto v0.0.0-20220719170305-83ca9fad585f // indirect
google.golang.org/grpc v1.48.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect

File diff suppressed because it is too large Load diff