mirror of
https://github.com/hyperledger/fabric-samples.git
synced 2026-06-17 07:25:10 +00:00
refactor folder structure to match other token samples (#652)
* go port to token-erc-721 Signed-off-by: Matias Salimbene <matias.saimbene@gmail.com> Signed-off-by: Matias Salimbene <matias.salimbene@gmail.com> * refactor folder structure Signed-off-by: Matias Salimbene <matias.salimbene@gmail.com> * refactor folder structure Signed-off-by: Matias Salimbene <matias.salimbene@gmail.com> * refactor chaincode go folder structure Signed-off-by: Matias Salimbene <matias.salimbene@gmail.com> * refactor folder struncture Signed-off-by: Matias Salimbene <matias.salimbene@gmail.com> Co-authored-by: Matias Salimbene <matias.saimbene@gmail.com>
This commit is contained in:
parent
2457b387c4
commit
5b480ce597
6 changed files with 1151 additions and 0 deletions
619
token-erc-721/chaincode-go/chaincode/erc721-contract.go
Normal file
619
token-erc-721/chaincode-go/chaincode/erc721-contract.go
Normal file
|
|
@ -0,0 +1,619 @@
|
|||
package chaincode
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/hyperledger/fabric-contract-api-go/contractapi"
|
||||
)
|
||||
|
||||
// Define objectType names for prefix
|
||||
const balancePrefix = "balance"
|
||||
const nftPrefix = "nft"
|
||||
const approvalPrefix = "approval"
|
||||
|
||||
// Define key names for options
|
||||
const nameKey = "name"
|
||||
const symbolKey = "symbol"
|
||||
|
||||
// TokenERC721Contract contract for managing CRUD operations
|
||||
type TokenERC721Contract struct {
|
||||
contractapi.Contract
|
||||
}
|
||||
|
||||
func _readNFT(ctx contractapi.TransactionContextInterface, tokenId string) (*Nft, error) {
|
||||
nftKey, err := ctx.GetStub().CreateCompositeKey(nftPrefix, []string{tokenId})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to CreateCompositeKey %s: %v", tokenId, err)
|
||||
}
|
||||
|
||||
nftBytes, err := ctx.GetStub().GetState(nftKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to GetState %s: %v", tokenId, err)
|
||||
}
|
||||
|
||||
nft := new(Nft)
|
||||
err = json.Unmarshal(nftBytes, nft)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to Unmarshal nftBytes: %v", err)
|
||||
}
|
||||
|
||||
return nft, nil
|
||||
}
|
||||
|
||||
func _nftExists(ctx contractapi.TransactionContextInterface, tokenId string) bool {
|
||||
nftKey, err := ctx.GetStub().CreateCompositeKey(nftPrefix, []string{tokenId})
|
||||
if err != nil {
|
||||
panic("error creating CreateCompositeKey:" + err.Error())
|
||||
}
|
||||
|
||||
nftBytes, err := ctx.GetStub().GetState(nftKey)
|
||||
if err != nil {
|
||||
panic("error GetState nftBytes:" + err.Error())
|
||||
}
|
||||
|
||||
return len(nftBytes) > 0
|
||||
}
|
||||
|
||||
// BalanceOf counts all non-fungible tokens assigned to an owner
|
||||
// param owner {String} An owner for whom to query the balance
|
||||
// returns {int} The number of non-fungible tokens owned by the owner, possibly zero
|
||||
func (c *TokenERC721Contract) BalanceOf(ctx contractapi.TransactionContextInterface, owner string) int {
|
||||
// There is a key record for every non-fungible token in the format of balancePrefix.owner.tokenId.
|
||||
// BalanceOf() queries for and counts all records matching balancePrefix.owner.*
|
||||
|
||||
iterator, err := ctx.GetStub().GetStateByPartialCompositeKey(balancePrefix, []string{owner})
|
||||
if err != nil {
|
||||
panic("Error creating asset chaincode:" + err.Error())
|
||||
}
|
||||
|
||||
// Count the number of returned composite keys
|
||||
balance := 0
|
||||
for iterator.HasNext() {
|
||||
_, err := iterator.Next()
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
balance++
|
||||
|
||||
}
|
||||
return balance
|
||||
}
|
||||
|
||||
// OwnerOf finds the owner of a non-fungible token
|
||||
// param {String} tokenId The identifier for a non-fungible token
|
||||
// returns {String} Return the owner of the non-fungible token
|
||||
func (c *TokenERC721Contract) OwnerOf(ctx contractapi.TransactionContextInterface, tokenId string) (string, error) {
|
||||
nft, err := _readNFT(ctx, tokenId)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("could not process OwnerOf for tokenId: %w", err)
|
||||
}
|
||||
|
||||
return nft.Owner, nil
|
||||
}
|
||||
|
||||
// Approve changes or reaffirms the approved client for a non-fungible token
|
||||
// param {String} operator The new approved client
|
||||
// param {String} tokenId the non-fungible token to approve
|
||||
// returns {Boolean} Return whether the approval was successful or not
|
||||
func (c *TokenERC721Contract) Approve(ctx contractapi.TransactionContextInterface, operator string, tokenId string) (bool, error) {
|
||||
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)
|
||||
|
||||
nft, err := _readNFT(ctx, tokenId)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to _readNFT: %v", err)
|
||||
}
|
||||
|
||||
// Check if the sender is the current owner of the non-fungible token
|
||||
// or an authorized operator of the current owner
|
||||
owner := nft.Owner
|
||||
operatorApproval, err := c.IsApprovedForAll(ctx, owner, sender)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to get IsApprovedForAll: %v", err)
|
||||
}
|
||||
if owner != sender && !operatorApproval {
|
||||
return false, fmt.Errorf("the sender is not the current owner nor an authorized operator")
|
||||
}
|
||||
|
||||
// Update the approved operator of the non-fungible token
|
||||
nft.Approved = operator
|
||||
nftKey, err := ctx.GetStub().CreateCompositeKey(nftPrefix, []string{tokenId})
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to CreateCompositeKey %s: %v", nftKey, err)
|
||||
}
|
||||
|
||||
nftBytes, err := json.Marshal(nft)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to marshal nftBytes: %v", err)
|
||||
}
|
||||
|
||||
err = ctx.GetStub().PutState(nftKey, nftBytes)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to PutState for nftKey: %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
|
||||
// param {Boolean} approved True if the operator is approved, false to revoke approval
|
||||
// returns {Boolean} Return whether the approval was successful or not
|
||||
func (c *TokenERC721Contract) SetApprovalForAll(ctx contractapi.TransactionContextInterface, operator string, approved bool) (bool, error) {
|
||||
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 sender: %v", err)
|
||||
}
|
||||
sender := string(senderBytes)
|
||||
|
||||
nftApproval := new(Approval)
|
||||
nftApproval.Owner = sender
|
||||
nftApproval.Operator = operator
|
||||
nftApproval.Approved = approved
|
||||
|
||||
approvalKey, err := ctx.GetStub().CreateCompositeKey(approvalPrefix, []string{sender, operator})
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to CreateCompositeKey: %v", err)
|
||||
}
|
||||
|
||||
approvalBytes, err := json.Marshal(nftApproval)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to marshal approvalBytes: %v", err)
|
||||
}
|
||||
|
||||
err = ctx.GetStub().PutState(approvalKey, approvalBytes)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to PutState approvalBytes: %v", err)
|
||||
}
|
||||
|
||||
// Emit the ApprovalForAll event
|
||||
err = ctx.GetStub().SetEvent("ApprovalForAll", approvalBytes)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to SetEvent ApprovalForAll: %v", err)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// IsApprovedForAll returns if a client is an authorized operator for another client
|
||||
// param {String} owner The client that owns the non-fungible tokens
|
||||
// param {String} operator The client that acts on behalf of the owner
|
||||
// returns {Boolean} Return true if the operator is an approved operator for the owner, false otherwise
|
||||
func (c *TokenERC721Contract) IsApprovedForAll(ctx contractapi.TransactionContextInterface, owner string, operator string) (bool, error) {
|
||||
approvalKey, err := ctx.GetStub().CreateCompositeKey(approvalPrefix, []string{owner, operator})
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to CreateCompositeKey: %v", err)
|
||||
}
|
||||
approvalBytes, err := ctx.GetStub().GetState(approvalKey)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to GetState approvalBytes %s: %v", approvalBytes, err)
|
||||
}
|
||||
|
||||
if len(approvalBytes) < 1 {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
approval := new(Approval)
|
||||
err = json.Unmarshal(approvalBytes, approval)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to Unmarshal: %v, string %s", err, string(approvalBytes))
|
||||
}
|
||||
|
||||
return approval.Approved, nil
|
||||
|
||||
}
|
||||
|
||||
// GetApproved returns the approved client for a single non-fungible token
|
||||
// param {String} tokenId the non-fungible token to find the approved client for
|
||||
// returns {Object} Return the approved client for this non-fungible token, or null if there is none
|
||||
func (c *TokenERC721Contract) GetApproved(ctx contractapi.TransactionContextInterface, tokenId string) (string, error) {
|
||||
nft, err := _readNFT(ctx, tokenId)
|
||||
if err != nil {
|
||||
return "false", fmt.Errorf("failed GetApproved for tokenId : %v", err)
|
||||
}
|
||||
return nft.Approved, nil
|
||||
}
|
||||
|
||||
// TransferFrom transfers the ownership of a non-fungible token
|
||||
// from one owner to another owner
|
||||
// param {String} from The current owner of the non-fungible token
|
||||
// param {String} to The new owner
|
||||
// param {String} tokenId the non-fungible token to transfer
|
||||
// returns {Boolean} Return whether the transfer was successful or not
|
||||
|
||||
func (c *TokenERC721Contract) TransferFrom(ctx contractapi.TransactionContextInterface, from string, to string, tokenId string) (bool, error) {
|
||||
|
||||
// Get ID of submitting client identity
|
||||
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 sender: %v", err)
|
||||
}
|
||||
sender := string(senderBytes)
|
||||
|
||||
nft, err := _readNFT(ctx, tokenId)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to _readNFT : %v", err)
|
||||
}
|
||||
|
||||
owner := nft.Owner
|
||||
operator := nft.Approved
|
||||
operatorApproval, err := c.IsApprovedForAll(ctx, owner, sender)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to get IsApprovedForAll : %v", err)
|
||||
}
|
||||
if owner != sender && operator != sender && !operatorApproval {
|
||||
return false, fmt.Errorf("the sender is not the current owner nor an authorized operator")
|
||||
}
|
||||
|
||||
// Check if `from` is the current owner
|
||||
if owner != from {
|
||||
return false, fmt.Errorf("the from is not the current owner")
|
||||
}
|
||||
|
||||
// Clear the approved client for this non-fungible token
|
||||
nft.Approved = ""
|
||||
|
||||
// Overwrite a non-fungible token to assign a new owner.
|
||||
nft.Owner = to
|
||||
nftKey, err := ctx.GetStub().CreateCompositeKey(nftPrefix, []string{tokenId})
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to CreateCompositeKey: %v", err)
|
||||
}
|
||||
|
||||
nftBytes, err := json.Marshal(nft)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to marshal approval: %v", err)
|
||||
}
|
||||
|
||||
err = ctx.GetStub().PutState(nftKey, nftBytes)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to PutState nftBytes %s: %v", nftBytes, err)
|
||||
}
|
||||
|
||||
// Remove a composite key from the balance of the current owner
|
||||
balanceKeyFrom, err := ctx.GetStub().CreateCompositeKey(balancePrefix, []string{from, tokenId})
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to CreateCompositeKey from: %v", err)
|
||||
}
|
||||
|
||||
err = ctx.GetStub().DelState(balanceKeyFrom)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to DelState balanceKeyFrom %s: %v", nftBytes, err)
|
||||
}
|
||||
|
||||
// Save a composite key to count the balance of a new owner
|
||||
balanceKeyTo, err := ctx.GetStub().CreateCompositeKey(balancePrefix, []string{to, tokenId})
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to CreateCompositeKey to: %v", err)
|
||||
}
|
||||
err = ctx.GetStub().PutState(balanceKeyTo, []byte{0})
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to PutState balanceKeyTo %s: %v", balanceKeyTo, err)
|
||||
}
|
||||
|
||||
// Emit the Transfer event
|
||||
transferEvent := new(Transfer)
|
||||
transferEvent.From = from
|
||||
transferEvent.To = to
|
||||
transferEvent.TokenId = tokenId
|
||||
|
||||
transferEventBytes, err := json.Marshal(transferEvent)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to marshal transferEventBytes: %v", err)
|
||||
}
|
||||
|
||||
err = ctx.GetStub().SetEvent("Transfer", transferEventBytes)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to SetEvent transferEventBytes %s: %v", transferEventBytes, err)
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// ============== ERC721 metadata extension ===============
|
||||
|
||||
// Name returns a descriptive name for a collection of non-fungible tokens in this contract
|
||||
// returns {String} Returns the name of the token
|
||||
|
||||
func (c *TokenERC721Contract) Name(ctx contractapi.TransactionContextInterface) (string, error) {
|
||||
bytes, err := ctx.GetStub().GetState(nameKey)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to get Name bytes: %s", err)
|
||||
}
|
||||
|
||||
return string(bytes), nil
|
||||
}
|
||||
|
||||
// Symbol returns an abbreviated name for non-fungible tokens in this contract.
|
||||
// returns {String} Returns the symbol of the token
|
||||
|
||||
func (c *TokenERC721Contract) Symbol(ctx contractapi.TransactionContextInterface) (string, error) {
|
||||
bytes, err := ctx.GetStub().GetState(symbolKey)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to get Symbol: %v", err)
|
||||
}
|
||||
|
||||
return string(bytes), nil
|
||||
}
|
||||
|
||||
// TokenURI returns a distinct Uniform Resource Identifier (URI) for a given token.
|
||||
// param {string} tokenId The identifier for a non-fungible token
|
||||
// returns {String} Returns the URI of the token
|
||||
|
||||
func (c *TokenERC721Contract) TokenURI(ctx contractapi.TransactionContextInterface, tokenId string) (string, error) {
|
||||
nft, err := _readNFT(ctx, tokenId)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to get TokenURI: %v", err)
|
||||
}
|
||||
return nft.TokenURI, nil
|
||||
}
|
||||
|
||||
// ============== ERC721 enumeration extension ===============
|
||||
// TotalSupply counts non-fungible tokens tracked by this contract.
|
||||
//
|
||||
// @param {Context} ctx the transaction context
|
||||
// @returns {Number} Returns a count of valid non-fungible tokens tracked by this contract,
|
||||
// where each one of them has an assigned and queryable owner.
|
||||
|
||||
func (c *TokenERC721Contract) TotalSupply(ctx contractapi.TransactionContextInterface) int {
|
||||
// There is a key record for every non-fungible token in the format of nftPrefix.tokenId.
|
||||
// TotalSupply() queries for and counts all records matching nftPrefix.*
|
||||
|
||||
iterator, err := ctx.GetStub().GetStateByPartialCompositeKey(nftPrefix, []string{})
|
||||
if err != nil {
|
||||
panic("Error creating GetStateByPartialCompositeKey:" + err.Error())
|
||||
}
|
||||
// Count the number of returned composite keys
|
||||
|
||||
totalSupply := 0
|
||||
for iterator.HasNext() {
|
||||
_, err := iterator.Next()
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
totalSupply++
|
||||
|
||||
}
|
||||
return totalSupply
|
||||
|
||||
}
|
||||
|
||||
// ============== ERC721 enumeration extension ===============
|
||||
// Set optional information for a token.
|
||||
// param {String} name The name of the token
|
||||
// param {String} symbol The symbol of the token
|
||||
|
||||
func (c *TokenERC721Contract) SetOption(ctx contractapi.TransactionContextInterface, name string, symbol string) (bool, error) {
|
||||
// Check minter authorization - this sample assumes Org1 is the issuer with privilege to set the name and symbol
|
||||
clientMSPID, err := ctx.GetClientIdentity().GetMSPID()
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to get clientMSPID: %v", err)
|
||||
} else if clientMSPID != "Org1MSP" {
|
||||
return false, fmt.Errorf("client is not authorized to set the name and symbol of the token")
|
||||
}
|
||||
|
||||
err = ctx.GetStub().PutState(nameKey, []byte(name))
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to PutState nameKey %s: %v", nameKey, err)
|
||||
}
|
||||
|
||||
err = ctx.GetStub().PutState(symbolKey, []byte(symbol))
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to PutState symbolKey %s: %v", symbolKey, err)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// Mint a new non-fungible token
|
||||
// param {String} tokenId Unique ID of the non-fungible token to be minted
|
||||
// param {String} tokenURI URI containing metadata of the minted non-fungible token
|
||||
// returns {Object} Return the non-fungible token object
|
||||
|
||||
func (c *TokenERC721Contract) MintWithTokenURI(ctx contractapi.TransactionContextInterface, tokenId string, tokenURI string) (*Nft, error) {
|
||||
|
||||
// Check minter authorization - this sample assumes Org1 is the issuer with privilege to mint a new token
|
||||
clientMSPID, err := ctx.GetClientIdentity().GetMSPID()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get clientMSPID: %v", err)
|
||||
}
|
||||
|
||||
if clientMSPID != "Org1MSP" {
|
||||
return nil, fmt.Errorf("client is not authorized to set the name and symbol of the token")
|
||||
}
|
||||
|
||||
// Get ID of submitting client identity
|
||||
minter64, err := ctx.GetClientIdentity().GetID()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get minter id: %v", err)
|
||||
}
|
||||
|
||||
minterBytes, err := base64.StdEncoding.DecodeString(minter64)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to DecodeString minter64: %v", err)
|
||||
}
|
||||
minter := string(minterBytes)
|
||||
|
||||
// Check if the token to be minted does not exist
|
||||
exists := _nftExists(ctx, tokenId)
|
||||
if exists {
|
||||
return nil, fmt.Errorf("the token %s is already minted.: %v", tokenId, err)
|
||||
}
|
||||
|
||||
// Add a non-fungible token
|
||||
nft := new(Nft)
|
||||
nft.TokenId = tokenId
|
||||
nft.Owner = minter
|
||||
nft.TokenURI = tokenURI
|
||||
|
||||
nftKey, err := ctx.GetStub().CreateCompositeKey(nftPrefix, []string{tokenId})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to CreateCompositeKey to nftKey: %v", err)
|
||||
}
|
||||
|
||||
nftBytes, err := json.Marshal(nft)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to marshal nft: %v", err)
|
||||
}
|
||||
|
||||
err = ctx.GetStub().PutState(nftKey, nftBytes)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to PutState nftBytes %s: %v", nftBytes, err)
|
||||
}
|
||||
|
||||
// A composite key would be balancePrefix.owner.tokenId, which enables partial
|
||||
// composite key query to find and count all records matching balance.owner.*
|
||||
// An empty value would represent a delete, so we simply insert the null character.
|
||||
|
||||
balanceKey, err := ctx.GetStub().CreateCompositeKey(balancePrefix, []string{minter, tokenId})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to CreateCompositeKey to balanceKey: %v", err)
|
||||
}
|
||||
|
||||
err = ctx.GetStub().PutState(balanceKey, []byte{'\u0000'})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to PutState balanceKey %s: %v", nftBytes, err)
|
||||
}
|
||||
|
||||
// Emit the Transfer event
|
||||
transferEvent := new(Transfer)
|
||||
transferEvent.From = "0x0"
|
||||
transferEvent.To = minter
|
||||
transferEvent.TokenId = tokenId
|
||||
|
||||
transferEventBytes, err := json.Marshal(transferEvent)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to marshal transferEventBytes: %v", err)
|
||||
}
|
||||
|
||||
err = ctx.GetStub().SetEvent("Transfer", transferEventBytes)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to SetEvent transferEventBytes %s: %v", transferEventBytes, err)
|
||||
}
|
||||
|
||||
return nft, nil
|
||||
}
|
||||
|
||||
// Burn a non-fungible token
|
||||
// param {String} tokenId Unique ID of a non-fungible token
|
||||
// returns {Boolean} Return whether the burn was successful or not
|
||||
func (c *TokenERC721Contract) Burn(ctx contractapi.TransactionContextInterface, tokenId string) (bool, error) {
|
||||
owner64, err := ctx.GetClientIdentity().GetID()
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to GetClientIdentity owner64: %v", err)
|
||||
}
|
||||
|
||||
ownerBytes, err := base64.StdEncoding.DecodeString(owner64)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to DecodeString owner64: %v", err)
|
||||
}
|
||||
owner := string(ownerBytes)
|
||||
|
||||
// Check if a caller is the owner of the non-fungible token
|
||||
nft, err := _readNFT(ctx, tokenId)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to _readNFT nft : %v", err)
|
||||
}
|
||||
if nft.Owner != owner {
|
||||
return false, fmt.Errorf("non-fungible token %s is not owned by %s", tokenId, owner)
|
||||
}
|
||||
|
||||
// Delete the token
|
||||
nftKey, err := ctx.GetStub().CreateCompositeKey(nftPrefix, []string{tokenId})
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to CreateCompositeKey tokenId: %v", err)
|
||||
}
|
||||
|
||||
err = ctx.GetStub().DelState(nftKey)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to DelState nftKey: %v", err)
|
||||
}
|
||||
|
||||
// Remove a composite key from the balance of the owner
|
||||
balanceKey, err := ctx.GetStub().CreateCompositeKey(balancePrefix, []string{owner, tokenId})
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to CreateCompositeKey balanceKey %s: %v", balanceKey, err)
|
||||
}
|
||||
|
||||
err = ctx.GetStub().DelState(balanceKey)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to DelState balanceKey %s: %v", balanceKey, err)
|
||||
}
|
||||
|
||||
// Emit the Transfer event
|
||||
transferEvent := new(Transfer)
|
||||
transferEvent.From = owner
|
||||
transferEvent.To = "0x0"
|
||||
transferEvent.TokenId = tokenId
|
||||
|
||||
transferEventBytes, err := json.Marshal(transferEvent)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to marshal transferEventBytes: %v", err)
|
||||
}
|
||||
|
||||
err = ctx.GetStub().SetEvent("Transfer", transferEventBytes)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to SetEvent transferEventBytes: %v", err)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// ClientAccountBalance returns the balance of the requesting client's account.
|
||||
// returns {Number} Returns the account balance
|
||||
func (c *TokenERC721Contract) ClientAccountBalance(ctx contractapi.TransactionContextInterface) (int, error) {
|
||||
// Get ID of submitting client identity
|
||||
clientAccountID64, err := ctx.GetClientIdentity().GetID()
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("failed to GetClientIdentity minter: %v", err)
|
||||
}
|
||||
|
||||
clientAccountIDBytes, err := base64.StdEncoding.DecodeString(clientAccountID64)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("failed to DecodeString sender: %v", err)
|
||||
}
|
||||
|
||||
clientAccountID := string(clientAccountIDBytes)
|
||||
|
||||
return c.BalanceOf(ctx, clientAccountID), nil
|
||||
}
|
||||
|
||||
// ClientAccountID returns the id of the requesting client's account.
|
||||
// In this implementation, the client account ID is the clientId itself.
|
||||
// Users can use this function to get their own account id, which they can then give to others as the payment address
|
||||
|
||||
func (c *TokenERC721Contract) ClientAccountID(ctx contractapi.TransactionContextInterface) (string, error) {
|
||||
// Get ID of submitting client identity
|
||||
clientAccountID64, err := ctx.GetClientIdentity().GetID()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to GetClientIdentity minter: %v", err)
|
||||
}
|
||||
|
||||
clientAccountBytes, err := base64.StdEncoding.DecodeString(clientAccountID64)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to DecodeString clientAccount64: %v", err)
|
||||
}
|
||||
clientAccount := string(clientAccountBytes)
|
||||
|
||||
return clientAccount, nil
|
||||
}
|
||||
282
token-erc-721/chaincode-go/chaincode/erc721-contract_test.go
Normal file
282
token-erc-721/chaincode-go/chaincode/erc721-contract_test.go
Normal file
|
|
@ -0,0 +1,282 @@
|
|||
package chaincode
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"testing"
|
||||
|
||||
"github.com/hyperledger/fabric-chaincode-go/pkg/cid"
|
||||
"github.com/hyperledger/fabric-chaincode-go/shim"
|
||||
"github.com/hyperledger/fabric-contract-api-go/contractapi"
|
||||
"github.com/hyperledger/fabric-protos-go/ledger/queryresult"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
const owner = "x509::CN=minter,OU=client,O=Hyperledger,ST=North Carolina,C=US::CN=ca.org1.example.com,O=org1.example.com,L=Durham,ST=North Carolina,C=US"
|
||||
const operator = "x509::CN=org,OU=client,O=Hyperledger,ST=North Carolina,C=US::CN=ca.org1.example.com,O=org1.example.com,L=Durham,ST=North Carolina,C=AR"
|
||||
|
||||
type MockStub struct {
|
||||
shim.ChaincodeStubInterface
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
func (ms *MockStub) GetStateByPartialCompositeKey(objectType string, keys []string) (shim.StateQueryIteratorInterface, error) {
|
||||
args := ms.Called(objectType, keys)
|
||||
return args.Get(0).(shim.StateQueryIteratorInterface), args.Error(1)
|
||||
}
|
||||
|
||||
func (ms *MockStub) GetState(key string) ([]byte, error) {
|
||||
args := ms.Called(key)
|
||||
return args.Get(0).([]byte), args.Error(1)
|
||||
}
|
||||
|
||||
func (ms *MockStub) PutState(key string, value []byte) error {
|
||||
args := ms.Called(key, value)
|
||||
return args.Error(0)
|
||||
}
|
||||
func (ms *MockStub) SetEvent(key string, value []byte) error {
|
||||
args := ms.Called(key, value)
|
||||
return args.Error(0)
|
||||
}
|
||||
|
||||
func (ms *MockStub) DelState(key string) error {
|
||||
args := ms.Called(key)
|
||||
return args.Error(0)
|
||||
}
|
||||
|
||||
func (ms *MockStub) CreateCompositeKey(objectType string, attributes []string) (string, error) {
|
||||
args := ms.Called(objectType, attributes)
|
||||
return args.Get(0).(string), args.Error(1)
|
||||
}
|
||||
|
||||
type MockClientIdentity struct {
|
||||
cid.ClientIdentity
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
func (mci *MockClientIdentity) GetID() (string, error) {
|
||||
args := mci.Called()
|
||||
return args.Get(0).(string), args.Error(1)
|
||||
}
|
||||
|
||||
func (mci *MockClientIdentity) GetMSPID() (string, error) {
|
||||
args := mci.Called()
|
||||
return args.Get(0).(string), args.Error(1)
|
||||
}
|
||||
|
||||
func (mc *MockContext) GetStub() shim.ChaincodeStubInterface {
|
||||
args := mc.Called()
|
||||
return args.Get(0).(*MockStub)
|
||||
}
|
||||
|
||||
type MockContext struct {
|
||||
contractapi.TransactionContextInterface
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
func (mc *MockContext) GetClientIdentity() cid.ClientIdentity {
|
||||
args := mc.Called()
|
||||
return args.Get(0).(*MockClientIdentity)
|
||||
}
|
||||
|
||||
type MockIterator struct {
|
||||
shim.StateQueryIteratorInterface
|
||||
queryresult.KV
|
||||
}
|
||||
|
||||
func (it *MockIterator) HasNext() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func setupStub() (*MockContext, *MockStub) {
|
||||
balancePrefix := "balance"
|
||||
approvalPrefix := "approval"
|
||||
nftPrefix := "nft"
|
||||
mockTokenId := "101"
|
||||
anyString := mock.AnythingOfType("string")
|
||||
anyUint8Slice := mock.AnythingOfType("[]uint8")
|
||||
nftStr := "{\"tokenId\":\"101\",\"owner\":\"" + owner + "\",\"tokenURI\":\"https://example.com/nft101.json\",\"approved\":\"" + operator + "\"}"
|
||||
approvalStr := "{\"owner\":\"" + owner + "\",\"operator\":\"" + owner + "\",\"approved\":true}"
|
||||
|
||||
ms := new(MockStub)
|
||||
iterator := new(MockIterator)
|
||||
|
||||
ms.On("GetStateByPartialCompositeKey", balancePrefix, []string{owner}).Return(iterator, nil)
|
||||
ms.On("GetStateByPartialCompositeKey", nftPrefix, []string{}).Return(iterator, nil)
|
||||
|
||||
ms.On("CreateCompositeKey", nftPrefix, []string{mockTokenId}).Return("nft101", nil)
|
||||
ms.On("CreateCompositeKey", nftPrefix, []string{"102"}).Return("nft102", nil)
|
||||
ms.On("CreateCompositeKey", approvalPrefix, []string{owner, owner}).Return(approvalPrefix+owner+owner, nil)
|
||||
ms.On("CreateCompositeKey", approvalPrefix, []string{owner, operator}).Return(approvalPrefix+owner+operator, nil)
|
||||
ms.On("CreateCompositeKey", balancePrefix, []string{owner, mockTokenId}).Return(balancePrefix+owner+mockTokenId, nil)
|
||||
ms.On("CreateCompositeKey", balancePrefix, []string{operator, mockTokenId}).Return(balancePrefix+operator+mockTokenId, nil)
|
||||
ms.On("CreateCompositeKey", balancePrefix, []string{owner, "102"}).Return(balancePrefix+owner+mockTokenId, nil)
|
||||
|
||||
ms.On("GetState", "nft101").Return([]byte(nftStr), nil)
|
||||
ms.On("GetState", "nft102").Return([]uint8{}, nil)
|
||||
ms.On("GetState", approvalPrefix+owner+owner).Return([]byte(approvalStr), nil)
|
||||
ms.On("GetState", "name").Return([]byte("lala"), nil)
|
||||
ms.On("GetState", "symbol").Return([]byte("lelo"), nil)
|
||||
|
||||
ms.On("PutState", "name", []byte("someName")).Return(nil)
|
||||
ms.On("PutState", "symbol", []byte("someSymbol")).Return(nil)
|
||||
ms.On("PutState", anyString, anyUint8Slice).Return(nil)
|
||||
ms.On("PutState", balancePrefix+owner+"101", []byte{0}).Return(nil)
|
||||
ms.On("PutState", balancePrefix+owner+"102", []byte{'\u0000'}).Return(nil)
|
||||
ms.On("PutState", "nft101", []byte("nft101")).Return(nil)
|
||||
ms.On("PutState", "nft102", []byte("nft102")).Return(nil)
|
||||
|
||||
ms.On("SetEvent", "ApprovalForAll", anyUint8Slice).Return(nil)
|
||||
ms.On("SetEvent", "Transfer", anyUint8Slice).Return(nil)
|
||||
|
||||
ms.On("DelState", anyString).Return(nil)
|
||||
|
||||
mci := new(MockClientIdentity)
|
||||
owner64 := base64.StdEncoding.EncodeToString([]byte(owner))
|
||||
operator64 := base64.StdEncoding.EncodeToString([]byte(owner))
|
||||
|
||||
mci.On("GetID").Return(owner64, nil)
|
||||
mci.On("GetID").Return(operator64, nil)
|
||||
mci.On("GetMSPID").Return("Org1MSP", nil)
|
||||
|
||||
mc := new(MockContext)
|
||||
mc.On("GetStub").Return(ms)
|
||||
mc.On("GetClientIdentity").Return(mci)
|
||||
return mc, ms
|
||||
}
|
||||
|
||||
func TestBalanceOf(t *testing.T) {
|
||||
ctx, _ := setupStub()
|
||||
c := new(TokenERC721Contract)
|
||||
|
||||
balance := c.BalanceOf(ctx, owner)
|
||||
assert.Equal(t, 0, balance)
|
||||
|
||||
}
|
||||
func TestTotalSupply(t *testing.T) {
|
||||
ctx, _ := setupStub()
|
||||
c := new(TokenERC721Contract)
|
||||
totalNft := c.TotalSupply(ctx)
|
||||
assert.Equal(t, 0, totalNft)
|
||||
|
||||
}
|
||||
|
||||
func TestOwnerOf(t *testing.T) {
|
||||
ctx, _ := setupStub()
|
||||
c := new(TokenERC721Contract)
|
||||
|
||||
owner, _ := c.OwnerOf(ctx, "101")
|
||||
assert.Equal(t, owner, owner)
|
||||
|
||||
}
|
||||
|
||||
func TestApprove(t *testing.T) {
|
||||
ctx, _ := setupStub()
|
||||
c := new(TokenERC721Contract)
|
||||
|
||||
approved, _ := c.Approve(ctx, "", "101")
|
||||
assert.Equal(t, true, approved)
|
||||
|
||||
}
|
||||
|
||||
func TestSetApprovalForAll(t *testing.T) {
|
||||
ctx, _ := setupStub()
|
||||
c := new(TokenERC721Contract)
|
||||
|
||||
appAll, _ := c.SetApprovalForAll(ctx, operator, true)
|
||||
assert.Equal(t, true, appAll)
|
||||
|
||||
}
|
||||
|
||||
func TestIsApprovedForAll(t *testing.T) {
|
||||
ctx, _ := setupStub()
|
||||
c := new(TokenERC721Contract)
|
||||
|
||||
isApp, _ := c.SetApprovalForAll(ctx, operator, true)
|
||||
assert.Equal(t, true, isApp)
|
||||
|
||||
}
|
||||
|
||||
func TestGetApproved(t *testing.T) {
|
||||
ctx, _ := setupStub()
|
||||
c := new(TokenERC721Contract)
|
||||
|
||||
getApp, _ := c.GetApproved(ctx, "101")
|
||||
assert.Equal(t, ""+operator+"", getApp)
|
||||
}
|
||||
|
||||
func TestTransferFrom(t *testing.T) {
|
||||
ctx, _ := setupStub()
|
||||
c := new(TokenERC721Contract)
|
||||
|
||||
transfer, _ := c.TransferFrom(ctx, owner, operator, "101")
|
||||
|
||||
assert.Equal(t, true, transfer)
|
||||
}
|
||||
|
||||
func TestName(t *testing.T) {
|
||||
ctx, _ := setupStub()
|
||||
c := new(TokenERC721Contract)
|
||||
|
||||
name, _ := c.Name(ctx)
|
||||
|
||||
assert.Equal(t, "lala", name)
|
||||
}
|
||||
|
||||
func TestSymbol(t *testing.T) {
|
||||
ctx, _ := setupStub()
|
||||
c := new(TokenERC721Contract)
|
||||
|
||||
symbol, _ := c.Symbol(ctx)
|
||||
|
||||
assert.Equal(t, "lelo", symbol)
|
||||
}
|
||||
|
||||
func TestTokenURI(t *testing.T) {
|
||||
ctx, _ := setupStub()
|
||||
c := new(TokenERC721Contract)
|
||||
|
||||
tokenURI, _ := c.TokenURI(ctx, "101")
|
||||
|
||||
assert.Equal(t, "https://example.com/nft101.json", tokenURI)
|
||||
}
|
||||
|
||||
func TestSetOption(t *testing.T) {
|
||||
ctx, _ := setupStub()
|
||||
c := new(TokenERC721Contract)
|
||||
|
||||
option, _ := c.SetOption(ctx, "someName", "someSymbol")
|
||||
assert.Equal(t, true, option)
|
||||
}
|
||||
|
||||
func TestMintWithTokenURI(t *testing.T) {
|
||||
ctx, _ := setupStub()
|
||||
c := new(TokenERC721Contract)
|
||||
|
||||
mint, _ := c.MintWithTokenURI(ctx, "102", "https://example.com/nft102.json")
|
||||
|
||||
nft := new(Nft)
|
||||
nft.Owner = owner
|
||||
nft.TokenId = "102"
|
||||
nft.TokenURI = "https://example.com/nft102.json"
|
||||
|
||||
assert.Equal(t, nft.Owner, mint.Owner)
|
||||
assert.Equal(t, nft, mint)
|
||||
|
||||
}
|
||||
|
||||
func TestBurn(t *testing.T) {
|
||||
ctx, _ := setupStub()
|
||||
c := new(TokenERC721Contract)
|
||||
|
||||
burn, _ := c.Burn(ctx, "101")
|
||||
assert.Equal(t, true, burn)
|
||||
}
|
||||
|
||||
func TestClientAccoundId(t *testing.T) {
|
||||
ctx, _ := setupStub()
|
||||
c := new(TokenERC721Contract)
|
||||
client, _ := c.ClientAccountID(ctx)
|
||||
assert.Equal(t, owner, client)
|
||||
}
|
||||
25
token-erc-721/chaincode-go/chaincode/erc721.go
Normal file
25
token-erc-721/chaincode-go/chaincode/erc721.go
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package chaincode
|
||||
|
||||
// Define structs to be used by chaincode
|
||||
type Nft struct {
|
||||
TokenId string `json:"tokenId"`
|
||||
Owner string `json:"owner"`
|
||||
TokenURI string `json:"tokenURI"`
|
||||
Approved string `json:"approved"`
|
||||
}
|
||||
|
||||
type Approval struct {
|
||||
Owner string `json:"owner"`
|
||||
Operator string `json:"operator"`
|
||||
Approved bool `json:"approved"`
|
||||
}
|
||||
|
||||
type Transfer struct {
|
||||
From string `json:"from"`
|
||||
To string `json:"to"`
|
||||
TokenId string `json:"tokenId"`
|
||||
}
|
||||
39
token-erc-721/chaincode-go/go.mod
Normal file
39
token-erc-721/chaincode-go/go.mod
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
module github.com/hyperledger/fabric-samples/token-erc-721/chaincode-go
|
||||
|
||||
go 1.17
|
||||
|
||||
require (
|
||||
github.com/hyperledger/fabric-chaincode-go v0.0.0-20220131132609-1476cf1d3206
|
||||
github.com/hyperledger/fabric-contract-api-go v1.1.1
|
||||
github.com/hyperledger/fabric-protos-go v0.0.0-20220202165055-956c75de7b17
|
||||
github.com/stretchr/testify v1.7.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/PuerkitoBio/purell v1.1.1 // indirect
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.19.3 // indirect
|
||||
github.com/go-openapi/jsonreference v0.19.2 // indirect
|
||||
github.com/go-openapi/spec v0.19.4 // indirect
|
||||
github.com/go-openapi/swag v0.19.5 // indirect
|
||||
github.com/gobuffalo/envy v1.7.0 // indirect
|
||||
github.com/gobuffalo/packd v0.3.0 // indirect
|
||||
github.com/gobuffalo/packr v1.30.1 // indirect
|
||||
github.com/golang/protobuf v1.3.2 // indirect
|
||||
github.com/joho/godotenv v1.3.0 // indirect
|
||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/rogpeppe/go-internal v1.3.0 // indirect
|
||||
github.com/stretchr/objx v0.2.0 // indirect
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
|
||||
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 // indirect
|
||||
golang.org/x/sys v0.0.0-20190710143415-6ec70d6a5542 // indirect
|
||||
golang.org/x/text v0.3.2 // indirect
|
||||
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b // indirect
|
||||
google.golang.org/grpc v1.23.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.2.8 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
|
||||
)
|
||||
151
token-erc-721/chaincode-go/go.sum
Normal file
151
token-erc-721/chaincode-go/go.sum
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/DATA-DOG/go-txdb v0.1.3/go.mod h1:DhAhxMXZpUJVGnT+p9IbzJoRKvlArO2pkHjnGX7o0n0=
|
||||
github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
|
||||
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
|
||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
||||
github.com/cucumber/godog v0.8.0/go.mod h1:Cp3tEV1LRAyH/RuCThcxHS/+9ORZ+FMzPva2AZ5Ki+A=
|
||||
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/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
|
||||
github.com/go-openapi/jsonpointer v0.19.3 h1:gihV7YNZK1iK6Tgwwsxo2rJbD1GTbdm72325Bq8FI3w=
|
||||
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||
github.com/go-openapi/jsonreference v0.19.2 h1:o20suLFB4Ri0tuzpWtyHlh7E7HnkqTNLq6aR6WVNS1w=
|
||||
github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
|
||||
github.com/go-openapi/spec v0.19.4 h1:ixzUSnHTd6hCemgtAJgluaTSGYpLNpJY4mA2DIkdOAo=
|
||||
github.com/go-openapi/spec v0.19.4/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo=
|
||||
github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||
github.com/go-openapi/swag v0.19.5 h1:lTz6Ys4CmqqCQmZPBlbQENR1/GucA2bzYTE12Pw4tFY=
|
||||
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/gobuffalo/envy v1.7.0 h1:GlXgaiBkmrYMHco6t4j7SacKO4XUjvh5pwXh0f4uxXU=
|
||||
github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
|
||||
github.com/gobuffalo/logger v1.0.0/go.mod h1:2zbswyIUa45I+c+FLXuWl9zSWEiVuthsk8ze5s8JvPs=
|
||||
github.com/gobuffalo/packd v0.3.0 h1:eMwymTkA1uXsqxS0Tpoop3Lc0u3kTfiMBE6nKtQU4g4=
|
||||
github.com/gobuffalo/packd v0.3.0/go.mod h1:zC7QkmNkYVGKPw4tHpBQ+ml7W/3tIebgeo1b36chA3Q=
|
||||
github.com/gobuffalo/packr v1.30.1 h1:hu1fuVR3fXEZR7rXNW3h8rqSML8EVAf6KNm0NKO/wKg=
|
||||
github.com/gobuffalo/packr v1.30.1/go.mod h1:ljMyFO2EcrnzsHsN99cvbq055Y9OhRrIaviy289eRuk=
|
||||
github.com/gobuffalo/packr/v2 v2.5.1/go.mod h1:8f9c96ITobJlPzI44jj+4tHnEKNt0xXWSVlXRN9X1Iw=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hyperledger/fabric-chaincode-go v0.0.0-20200424173110-d7076418f212/go.mod h1:N7H3sA7Tx4k/YzFq7U0EPdqJtqvM4Kild0JoCc7C0Dc=
|
||||
github.com/hyperledger/fabric-chaincode-go v0.0.0-20220131132609-1476cf1d3206 h1:WAERjn+5lTfT8hVw5ik4uozvtei2F836AcRU+5fipmI=
|
||||
github.com/hyperledger/fabric-chaincode-go v0.0.0-20220131132609-1476cf1d3206/go.mod h1:poNJVTYwPIuHWJH0gyprZZSx70GpdWM2se3u/DEldYc=
|
||||
github.com/hyperledger/fabric-contract-api-go v1.1.1 h1:gDhOC18gjgElNZ85kFWsbCQq95hyUP/21n++m0Sv6B0=
|
||||
github.com/hyperledger/fabric-contract-api-go v1.1.1/go.mod h1:+39cWxbh5py3NtXpRA63rAH7NzXyED+QJx1EZr0tJPo=
|
||||
github.com/hyperledger/fabric-protos-go v0.0.0-20190919234611-2a87503ac7c9/go.mod h1:xVYTjK4DtZRBxZ2D9aE4y6AbLaPwue2o/criQyQbVD0=
|
||||
github.com/hyperledger/fabric-protos-go v0.0.0-20200424173316-dd554ba3746e/go.mod h1:xVYTjK4DtZRBxZ2D9aE4y6AbLaPwue2o/criQyQbVD0=
|
||||
github.com/hyperledger/fabric-protos-go v0.0.0-20220202165055-956c75de7b17 h1:TJzBJlpsO2wjlq/YyoAVLJCnb9MjeddYW2BHtQmbAI4=
|
||||
github.com/hyperledger/fabric-protos-go v0.0.0-20220202165055-956c75de7b17/go.mod h1:xVYTjK4DtZRBxZ2D9aE4y6AbLaPwue2o/criQyQbVD0=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
|
||||
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
|
||||
github.com/karrick/godirwalk v1.10.12/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs=
|
||||
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e h1:hB2xlXdHp/pmPZq0y3QnmWAArdw9PqbmotexnWx/FU8=
|
||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
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.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.3.0 h1:RR9dF3JtopPvtkroDZuVD7qquD0bnHlKSqaQhgwt8yk=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
|
||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/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=
|
||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 h1:k7pJ2yAPLPgbskkFdhRCsA77k2fySZ1zf2zCjvQCiIM=
|
||||
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190710143415-6ec70d6a5542 h1:6ZQFf1D2YYDDI7eSwW8adlkkavTB9sw5I24FVtEvNUQ=
|
||||
golang.org/x/sys v0.0.0-20190710143415-6ec70d6a5542/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190624180213-70d37148ca0c/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b h1:lohp5blsw53GBXtLyLNaTXPXS9pJ1tiTw61ZHUoE9Qw=
|
||||
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/grpc v1.23.0 h1:AzbTB6ux+okLTzP8Ru1Xs41C303zdcfEht7MQnYJt5A=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
35
token-erc-721/chaincode-go/main.go
Normal file
35
token-erc-721/chaincode-go/main.go
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/hyperledger/fabric-contract-api-go/contractapi"
|
||||
"github.com/hyperledger/fabric-contract-api-go/metadata"
|
||||
"github.com/hyperledger/fabric-samples/token-erc-721/chaincode-go/chaincode"
|
||||
)
|
||||
|
||||
func main() {
|
||||
nftContract := new(chaincode.TokenERC721Contract)
|
||||
nftContract.Info.Version = "0.0.1"
|
||||
nftContract.Info.Description = "ERC-721 fabric port"
|
||||
nftContract.Info.License = new(metadata.LicenseMetadata)
|
||||
nftContract.Info.License.Name = "Apache-2.0"
|
||||
nftContract.Info.Contact = new(metadata.ContactMetadata)
|
||||
nftContract.Info.Contact.Name = "Matias Salimbene"
|
||||
|
||||
chaincode, err := contractapi.NewChaincode(nftContract)
|
||||
chaincode.Info.Title = "ERC-721 chaincode"
|
||||
chaincode.Info.Version = "0.0.1"
|
||||
|
||||
if err != nil {
|
||||
panic("Could not create chaincode from TokenERC721Contract." + err.Error())
|
||||
}
|
||||
|
||||
err = chaincode.Start()
|
||||
|
||||
if err != nil {
|
||||
panic("Failed to start chaincode. " + err.Error())
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue