mirror of
https://github.com/hyperledger/fabric-samples.git
synced 2026-06-23 01:55:10 +00:00
添加网关
This commit is contained in:
parent
8fb2cc951a
commit
346e1296e3
13 changed files with 578 additions and 280 deletions
284
asset-transfer-basic/application-gateway-go/assetTransfer.go
Executable file → Normal file
284
asset-transfer-basic/application-gateway-go/assetTransfer.go
Executable file → Normal file
|
|
@ -7,290 +7,14 @@ SPDX-License-Identifier: Apache-2.0
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"assetTransfer/cmd"
|
||||||
"context"
|
|
||||||
"crypto/x509"
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/hyperledger/fabric-gateway/pkg/client"
|
|
||||||
"github.com/hyperledger/fabric-gateway/pkg/hash"
|
|
||||||
"github.com/hyperledger/fabric-gateway/pkg/identity"
|
|
||||||
"github.com/hyperledger/fabric-protos-go-apiv2/gateway"
|
|
||||||
"google.golang.org/grpc"
|
|
||||||
"google.golang.org/grpc/credentials"
|
|
||||||
"google.golang.org/grpc/status"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
mspID = "Org1MSP"
|
|
||||||
cryptoPath = "../../test-network/organizations/peerOrganizations/org1.example.com"
|
|
||||||
certPath = cryptoPath + "/users/User1@org1.example.com/msp/signcerts"
|
|
||||||
keyPath = cryptoPath + "/users/User1@org1.example.com/msp/keystore"
|
|
||||||
tlsCertPath = cryptoPath + "/peers/peer0.org1.example.com/tls/ca.crt"
|
|
||||||
peerEndpoint = "dns:///localhost:7051"
|
|
||||||
gatewayPeer = "peer0.org1.example.com"
|
|
||||||
)
|
|
||||||
|
|
||||||
var now = time.Now()
|
|
||||||
var assetId = fmt.Sprintf("asset%d", now.Unix()*1e3+int64(now.Nanosecond())/1e6)
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
// The gRPC client connection should be shared by all Gateway connections to this endpoint
|
if err := cmd.Execute(); err != nil {
|
||||||
clientConnection := newGrpcConnection()
|
fmt.Println("Error:", err)
|
||||||
defer clientConnection.Close()
|
os.Exit(1)
|
||||||
|
|
||||||
id := newIdentity()
|
|
||||||
sign := newSign()
|
|
||||||
|
|
||||||
// Create a Gateway connection for a specific client identity
|
|
||||||
gw, err := client.Connect(
|
|
||||||
id,
|
|
||||||
client.WithSign(sign),
|
|
||||||
client.WithHash(hash.SHA256),
|
|
||||||
client.WithClientConnection(clientConnection),
|
|
||||||
// Default timeouts for different gRPC calls
|
|
||||||
client.WithEvaluateTimeout(5*time.Second),
|
|
||||||
client.WithEndorseTimeout(15*time.Second),
|
|
||||||
client.WithSubmitTimeout(5*time.Second),
|
|
||||||
client.WithCommitStatusTimeout(1*time.Minute),
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
defer gw.Close()
|
|
||||||
|
|
||||||
// Override default values for chaincode and channel name as they may differ in testing contexts.
|
|
||||||
chaincodeName := "basic"
|
|
||||||
if ccname := os.Getenv("CHAINCODE_NAME"); ccname != "" {
|
|
||||||
chaincodeName = ccname
|
|
||||||
}
|
|
||||||
|
|
||||||
channelName := "mychannel"
|
|
||||||
if cname := os.Getenv("CHANNEL_NAME"); cname != "" {
|
|
||||||
channelName = cname
|
|
||||||
}
|
|
||||||
|
|
||||||
network := gw.GetNetwork(channelName)
|
|
||||||
contract := network.GetContract(chaincodeName)
|
|
||||||
|
|
||||||
initLedger(contract)
|
|
||||||
getAllAssets(contract)
|
|
||||||
createAsset(contract)
|
|
||||||
readAssetByID(contract)
|
|
||||||
transferAssetAsync(contract)
|
|
||||||
exampleErrorHandling(contract)
|
|
||||||
}
|
|
||||||
|
|
||||||
// newGrpcConnection creates a gRPC connection to the Gateway server.
|
|
||||||
func newGrpcConnection() *grpc.ClientConn {
|
|
||||||
certificatePEM, err := os.ReadFile(tlsCertPath)
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Errorf("failed to read TLS certifcate file: %w", err))
|
|
||||||
}
|
|
||||||
|
|
||||||
certificate, err := identity.CertificateFromPEM(certificatePEM)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
certPool := x509.NewCertPool()
|
|
||||||
certPool.AddCert(certificate)
|
|
||||||
transportCredentials := credentials.NewClientTLSFromCert(certPool, gatewayPeer)
|
|
||||||
|
|
||||||
connection, err := grpc.NewClient(peerEndpoint, grpc.WithTransportCredentials(transportCredentials))
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Errorf("failed to create gRPC connection: %w", err))
|
|
||||||
}
|
|
||||||
|
|
||||||
return connection
|
|
||||||
}
|
|
||||||
|
|
||||||
// newIdentity creates a client identity for this Gateway connection using an X.509 certificate.
|
|
||||||
func newIdentity() *identity.X509Identity {
|
|
||||||
certificatePEM, err := readFirstFile(certPath)
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Errorf("failed to read certificate file: %w", err))
|
|
||||||
}
|
|
||||||
|
|
||||||
certificate, err := identity.CertificateFromPEM(certificatePEM)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
id, err := identity.NewX509Identity(mspID, certificate)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return id
|
|
||||||
}
|
|
||||||
|
|
||||||
// newSign creates a function that generates a digital signature from a message digest using a private key.
|
|
||||||
func newSign() identity.Sign {
|
|
||||||
privateKeyPEM, err := readFirstFile(keyPath)
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Errorf("failed to read private key file: %w", err))
|
|
||||||
}
|
|
||||||
|
|
||||||
privateKey, err := identity.PrivateKeyFromPEM(privateKeyPEM)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
sign, err := identity.NewPrivateKeySign(privateKey)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return sign
|
|
||||||
}
|
|
||||||
|
|
||||||
func readFirstFile(dirPath string) ([]byte, error) {
|
|
||||||
dir, err := os.Open(dirPath)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
fileNames, err := dir.Readdirnames(1)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return os.ReadFile(path.Join(dirPath, fileNames[0]))
|
|
||||||
}
|
|
||||||
|
|
||||||
// This type of transaction would typically only be run once by an application the first time it was started after its
|
|
||||||
// initial deployment. A new version of the chaincode deployed later would likely not need to run an "init" function.
|
|
||||||
func initLedger(contract *client.Contract) {
|
|
||||||
fmt.Printf("\n--> Submit Transaction: InitLedger, function creates the initial set of assets on the ledger \n")
|
|
||||||
|
|
||||||
_, err := contract.SubmitTransaction("InitLedger")
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Errorf("failed to submit transaction: %w", err))
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("*** Transaction committed successfully\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Evaluate a transaction to query ledger state.
|
|
||||||
func getAllAssets(contract *client.Contract) {
|
|
||||||
fmt.Println("\n--> Evaluate Transaction: GetAllAssets, function returns all the current assets on the ledger")
|
|
||||||
|
|
||||||
evaluateResult, err := contract.EvaluateTransaction("GetAllAssets")
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Errorf("failed to evaluate transaction: %w", err))
|
|
||||||
}
|
|
||||||
result := formatJSON(evaluateResult)
|
|
||||||
|
|
||||||
fmt.Printf("*** Result:%s\n", result)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Submit a transaction synchronously, blocking until it has been committed to the ledger.
|
|
||||||
func createAsset(contract *client.Contract) {
|
|
||||||
fmt.Printf("\n--> Submit Transaction: CreateAsset, creates new asset with ID, Color, Size, Owner and AppraisedValue arguments \n")
|
|
||||||
|
|
||||||
_, err := contract.SubmitTransaction("CreateAsset", assetId, "yellow", "5", "Tom", "1300")
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Errorf("failed to submit transaction: %w", err))
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("*** Transaction committed successfully\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Evaluate a transaction by assetID to query ledger state.
|
|
||||||
func readAssetByID(contract *client.Contract) {
|
|
||||||
fmt.Printf("\n--> Evaluate Transaction: ReadAsset, function returns asset attributes\n")
|
|
||||||
|
|
||||||
evaluateResult, err := contract.EvaluateTransaction("ReadAsset", assetId)
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Errorf("failed to evaluate transaction: %w", err))
|
|
||||||
}
|
|
||||||
result := formatJSON(evaluateResult)
|
|
||||||
|
|
||||||
fmt.Printf("*** Result:%s\n", result)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Submit transaction asynchronously, blocking until the transaction has been sent to the orderer, and allowing
|
|
||||||
// this thread to process the chaincode response (e.g. update a UI) without waiting for the commit notification
|
|
||||||
func transferAssetAsync(contract *client.Contract) {
|
|
||||||
fmt.Printf("\n--> Async Submit Transaction: TransferAsset, updates existing asset owner")
|
|
||||||
|
|
||||||
submitResult, commit, err := contract.SubmitAsync("TransferAsset", client.WithArguments(assetId, "Mark"))
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Errorf("failed to submit transaction asynchronously: %w", err))
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("\n*** Successfully submitted transaction to transfer ownership from %s to Mark. \n", string(submitResult))
|
|
||||||
fmt.Println("*** Waiting for transaction commit.")
|
|
||||||
|
|
||||||
if commitStatus, err := commit.Status(); err != nil {
|
|
||||||
panic(fmt.Errorf("failed to get commit status: %w", err))
|
|
||||||
} else if !commitStatus.Successful {
|
|
||||||
panic(fmt.Errorf("transaction %s failed to commit with status: %d", commitStatus.TransactionID, int32(commitStatus.Code)))
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("*** Transaction committed successfully\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Submit transaction, passing in the wrong number of arguments ,expected to throw an error containing details of any error responses from the smart contract.
|
|
||||||
func exampleErrorHandling(contract *client.Contract) {
|
|
||||||
fmt.Println("\n--> Submit Transaction: UpdateAsset asset70, asset70 does not exist and should return an error")
|
|
||||||
|
|
||||||
_, err := contract.SubmitTransaction("UpdateAsset", "asset70", "blue", "5", "Tomoko", "300")
|
|
||||||
if err == nil {
|
|
||||||
panic("******** FAILED to return an error")
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println("*** Successfully caught the error:")
|
|
||||||
|
|
||||||
var endorseErr *client.EndorseError
|
|
||||||
var submitErr *client.SubmitError
|
|
||||||
var commitStatusErr *client.CommitStatusError
|
|
||||||
var commitErr *client.CommitError
|
|
||||||
|
|
||||||
if errors.As(err, &endorseErr) {
|
|
||||||
fmt.Printf("Endorse error for transaction %s with gRPC status %v: %s\n", endorseErr.TransactionID, status.Code(endorseErr), endorseErr)
|
|
||||||
} else if errors.As(err, &submitErr) {
|
|
||||||
fmt.Printf("Submit error for transaction %s with gRPC status %v: %s\n", submitErr.TransactionID, status.Code(submitErr), submitErr)
|
|
||||||
} else if errors.As(err, &commitStatusErr) {
|
|
||||||
if errors.Is(err, context.DeadlineExceeded) {
|
|
||||||
fmt.Printf("Timeout waiting for transaction %s commit status: %s", commitStatusErr.TransactionID, commitStatusErr)
|
|
||||||
} else {
|
|
||||||
fmt.Printf("Error obtaining commit status for transaction %s with gRPC status %v: %s\n", commitStatusErr.TransactionID, status.Code(commitStatusErr), commitStatusErr)
|
|
||||||
}
|
|
||||||
} else if errors.As(err, &commitErr) {
|
|
||||||
fmt.Printf("Transaction %s failed to commit with status %d: %s\n", commitErr.TransactionID, int32(commitErr.Code), err)
|
|
||||||
} else {
|
|
||||||
panic(fmt.Errorf("unexpected error type %T: %w", err, err))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Any error that originates from a peer or orderer node external to the gateway will have its details
|
|
||||||
// embedded within the gRPC status error. The following code shows how to extract that.
|
|
||||||
statusErr := status.Convert(err)
|
|
||||||
|
|
||||||
details := statusErr.Details()
|
|
||||||
if len(details) > 0 {
|
|
||||||
fmt.Println("Error Details:")
|
|
||||||
|
|
||||||
for _, detail := range details {
|
|
||||||
switch detail := detail.(type) {
|
|
||||||
case *gateway.ErrorDetail:
|
|
||||||
fmt.Printf("- address: %s; mspId: %s; message: %s\n", detail.Address, detail.MspId, detail.Message)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Format JSON data
|
|
||||||
func formatJSON(data []byte) string {
|
|
||||||
var prettyJSON bytes.Buffer
|
|
||||||
if err := json.Indent(&prettyJSON, data, "", " "); err != nil {
|
|
||||||
panic(fmt.Errorf("failed to parse JSON: %w", err))
|
|
||||||
}
|
|
||||||
return prettyJSON.String()
|
|
||||||
}
|
|
||||||
|
|
|
||||||
62
asset-transfer-basic/application-gateway-go/cmd/root.go
Normal file
62
asset-transfer-basic/application-gateway-go/cmd/root.go
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"assetTransfer/internal/conf"
|
||||||
|
"assetTransfer/internal/grpc"
|
||||||
|
"assetTransfer/internal/log"
|
||||||
|
"assetTransfer/internal/router"
|
||||||
|
"fmt"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
port string
|
||||||
|
configPath string
|
||||||
|
)
|
||||||
|
|
||||||
|
var rootCmd = &cobra.Command{
|
||||||
|
Use: "ledger-gw",
|
||||||
|
RunE: run,
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
rootCmd.PersistentFlags().StringVarP(&port, "port", "p", "8080", "Port to run the server on")
|
||||||
|
rootCmd.PersistentFlags().StringVarP(&configPath, "config", "c", "./config.yaml", "Path of the configuration file")
|
||||||
|
|
||||||
|
if err := rootCmd.MarkPersistentFlagRequired("port"); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
if err := rootCmd.MarkPersistentFlagRequired("config"); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func run(_ *cobra.Command, _ []string) error {
|
||||||
|
if err := config.InitConfig(configPath); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := log.InitLog(config.GetLogLevel(), config.GetLogPath()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化网关连接
|
||||||
|
grpc.InitGWConnect()
|
||||||
|
defer grpc.CloseGWConnect()
|
||||||
|
|
||||||
|
gin.SetMode(config.GetServerMode())
|
||||||
|
r := gin.Default()
|
||||||
|
router.SetupRoutes(r)
|
||||||
|
if err := r.Run(":" + port); err != nil {
|
||||||
|
fmt.Println("Failed to start server:", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Execute() error {
|
||||||
|
if err := rootCmd.Execute(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
6
asset-transfer-basic/application-gateway-go/config.yaml
Normal file
6
asset-transfer-basic/application-gateway-go/config.yaml
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
server:
|
||||||
|
mode: debug
|
||||||
|
|
||||||
|
log:
|
||||||
|
level: debug
|
||||||
|
path: ./logs/culture_platform.log
|
||||||
|
|
@ -3,13 +3,40 @@ module assetTransfer
|
||||||
go 1.23.0
|
go 1.23.0
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/gin-gonic/gin v1.10.0
|
||||||
github.com/hyperledger/fabric-gateway v1.7.0
|
github.com/hyperledger/fabric-gateway v1.7.0
|
||||||
github.com/hyperledger/fabric-protos-go-apiv2 v0.3.4
|
github.com/hyperledger/fabric-protos-go-apiv2 v0.3.4
|
||||||
|
github.com/spf13/cobra v1.9.1
|
||||||
|
go.uber.org/zap v1.27.0
|
||||||
google.golang.org/grpc v1.67.1
|
google.golang.org/grpc v1.67.1
|
||||||
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/bytedance/sonic v1.11.6 // indirect
|
||||||
|
github.com/bytedance/sonic/loader v0.1.1 // indirect
|
||||||
|
github.com/cloudwego/base64x v0.1.4 // indirect
|
||||||
|
github.com/cloudwego/iasm v0.2.0 // indirect
|
||||||
|
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
||||||
|
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||||
|
github.com/go-playground/locales v0.14.1 // indirect
|
||||||
|
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||||
|
github.com/go-playground/validator/v10 v10.20.0 // indirect
|
||||||
|
github.com/goccy/go-json v0.10.2 // indirect
|
||||||
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
|
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
|
||||||
|
github.com/leodido/go-urn v1.4.0 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/miekg/pkcs11 v1.1.1 // indirect
|
github.com/miekg/pkcs11 v1.1.1 // indirect
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
|
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
||||||
|
github.com/spf13/pflag v1.0.6 // indirect
|
||||||
|
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||||
|
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||||
|
go.uber.org/multierr v1.10.0 // indirect
|
||||||
|
golang.org/x/arch v0.8.0 // indirect
|
||||||
golang.org/x/crypto v0.28.0 // indirect
|
golang.org/x/crypto v0.28.0 // indirect
|
||||||
golang.org/x/net v0.28.0 // indirect
|
golang.org/x/net v0.28.0 // indirect
|
||||||
golang.org/x/sys v0.26.0 // indirect
|
golang.org/x/sys v0.26.0 // indirect
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,98 @@
|
||||||
|
github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
|
||||||
|
github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
|
||||||
|
github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
|
||||||
|
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
||||||
|
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
|
||||||
|
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
|
||||||
|
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
|
||||||
|
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||||
|
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 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
|
||||||
|
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
|
||||||
|
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||||
|
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||||
|
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
|
||||||
|
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
|
||||||
|
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||||
|
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||||
|
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||||
|
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||||
|
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||||
|
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||||
|
github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8=
|
||||||
|
github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
|
||||||
|
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||||
|
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
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/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/hyperledger/fabric-gateway v1.7.0 h1:bd1quU8qYPYqYO69m1tPIDSjB+D+u/rBJfE1eWFcpjY=
|
github.com/hyperledger/fabric-gateway v1.7.0 h1:bd1quU8qYPYqYO69m1tPIDSjB+D+u/rBJfE1eWFcpjY=
|
||||||
github.com/hyperledger/fabric-gateway v1.7.0/go.mod h1:TItDGnq71eJcgz5TW+m5Sq3kWGp0AEI1HPCNxj0Eu7k=
|
github.com/hyperledger/fabric-gateway v1.7.0/go.mod h1:TItDGnq71eJcgz5TW+m5Sq3kWGp0AEI1HPCNxj0Eu7k=
|
||||||
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 h1:YJrd+gMaeY0/vsN0aS0QkEKTivGoUnSRIXxGJ7KI+Pc=
|
||||||
github.com/hyperledger/fabric-protos-go-apiv2 v0.3.4/go.mod h1:bau/6AJhvEcu9GKKYHlDXAxXKzYNfhP6xu2GXuxEcFk=
|
github.com/hyperledger/fabric-protos-go-apiv2 v0.3.4/go.mod h1:bau/6AJhvEcu9GKKYHlDXAxXKzYNfhP6xu2GXuxEcFk=
|
||||||
|
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||||
|
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||||
|
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||||
|
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||||
|
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||||
|
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
|
||||||
|
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||||
|
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
|
||||||
|
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||||
|
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||||
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU=
|
github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU=
|
||||||
github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
|
github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||||
|
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||||
|
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
|
||||||
|
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
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/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
|
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
|
||||||
|
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
|
||||||
|
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
|
||||||
|
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
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/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.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
|
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
|
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||||
|
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||||
|
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
|
||||||
|
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||||
|
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||||
|
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||||
|
go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
|
||||||
|
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||||
|
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||||
|
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||||
|
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||||
|
golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
|
||||||
|
golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
||||||
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
|
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
|
||||||
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
|
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
|
||||||
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
|
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
|
||||||
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
|
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
|
||||||
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
|
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
|
||||||
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
|
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
|
||||||
|
|
@ -28,5 +103,10 @@ google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E=
|
||||||
google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA=
|
google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA=
|
||||||
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
|
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
|
||||||
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
|
||||||
|
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
|
||||||
|
ierror "assetTransfer/internal/error"
|
||||||
|
"assetTransfer/internal/grpc"
|
||||||
|
)
|
||||||
|
|
||||||
|
func SubmitTransaction(c *gin.Context) {
|
||||||
|
funcName, args, err := getCommonParams(c)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(400, gin.H{"error": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := grpc.Contract.SubmitTransaction(funcName, args...)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(500, gin.H{"error": ierror.ErrorHandling(err)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.JSON(200, gin.H{"result": result})
|
||||||
|
}
|
||||||
|
|
||||||
|
func EvaluateTransaction(c *gin.Context) {
|
||||||
|
funcName, args, err := getCommonParams(c)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(400, gin.H{"error": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := grpc.Contract.EvaluateTransaction(funcName, args...)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(500, gin.H{"error": ierror.ErrorHandling(err)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.JSON(200, gin.H{"result": result})
|
||||||
|
}
|
||||||
|
|
||||||
|
func getCommonParams(c *gin.Context) (string, []string, error) {
|
||||||
|
type RequestBody struct {
|
||||||
|
FuncName string `json:"func"`
|
||||||
|
Args []string `json:"args"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var body RequestBody
|
||||||
|
if err := c.ShouldBindJSON(&body); err != nil {
|
||||||
|
return "", nil, fmt.Errorf("invalid request body: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if body.FuncName == "" {
|
||||||
|
return "", nil, fmt.Errorf("func is required")
|
||||||
|
}
|
||||||
|
if len(body.Args) == 0 {
|
||||||
|
return "", nil, fmt.Errorf("args is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
return body.FuncName, body.Args, nil
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
|
"io/ioutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
Config struct {
|
||||||
|
Server Server `yaml:"server"`
|
||||||
|
Log Log `yaml:"log"`
|
||||||
|
}
|
||||||
|
|
||||||
|
Server struct {
|
||||||
|
Mode string `yaml:"mode"`
|
||||||
|
}
|
||||||
|
|
||||||
|
Log struct {
|
||||||
|
Level string `yaml:"level"`
|
||||||
|
Path string `yaml:"path"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
var config Config
|
||||||
|
|
||||||
|
func InitConfig(configPath string) error {
|
||||||
|
// 读取配置文件
|
||||||
|
yamlFile, err := ioutil.ReadFile(configPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析YAML文件到config结构体
|
||||||
|
err = yaml.Unmarshal(yamlFile, &config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetServerMode() string { return config.Server.Mode }
|
||||||
|
|
||||||
|
func GetLogLevel() string { return config.Log.Level }
|
||||||
|
func GetLogPath() string { return config.Log.Path }
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
package error
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"github.com/hyperledger/fabric-protos-go-apiv2/gateway"
|
||||||
|
|
||||||
|
"github.com/hyperledger/fabric-gateway/pkg/client"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ErrorHandling(err error) string {
|
||||||
|
var endorseErr *client.EndorseError
|
||||||
|
var submitErr *client.SubmitError
|
||||||
|
var commitStatusErr *client.CommitStatusError
|
||||||
|
var commitErr *client.CommitError
|
||||||
|
var res string
|
||||||
|
|
||||||
|
if errors.As(err, &endorseErr) {
|
||||||
|
res = fmt.Sprintf("Endorse error for transaction %s with gRPC status %v: %s\n", endorseErr.TransactionID, status.Code(endorseErr), endorseErr)
|
||||||
|
} else if errors.As(err, &submitErr) {
|
||||||
|
res = fmt.Sprintf("Submit error for transaction %s with gRPC status %v: %s\n", submitErr.TransactionID, status.Code(submitErr), submitErr)
|
||||||
|
} else if errors.As(err, &commitStatusErr) {
|
||||||
|
if errors.Is(err, context.DeadlineExceeded) {
|
||||||
|
res = fmt.Sprintf("Timeout waiting for transaction %s commit status: %s", commitStatusErr.TransactionID, commitStatusErr)
|
||||||
|
} else {
|
||||||
|
res = fmt.Sprintf("Error obtaining commit status for transaction %s with gRPC status %v: %s\n", commitStatusErr.TransactionID, status.Code(commitStatusErr), commitStatusErr)
|
||||||
|
}
|
||||||
|
} else if errors.As(err, &commitErr) {
|
||||||
|
res = fmt.Sprintf("Transaction %s failed to commit with status %d: %s\n", commitErr.TransactionID, int32(commitErr.Code), err)
|
||||||
|
} else {
|
||||||
|
panic(fmt.Errorf("unexpected error type %T: %w", err, err))
|
||||||
|
}
|
||||||
|
|
||||||
|
statusErr := status.Convert(err)
|
||||||
|
details := statusErr.Details()
|
||||||
|
if len(details) > 0 {
|
||||||
|
fmt.Println("Error Details:")
|
||||||
|
|
||||||
|
for _, detail := range details {
|
||||||
|
switch detail := detail.(type) {
|
||||||
|
case *gateway.ErrorDetail:
|
||||||
|
res = fmt.Sprintf("- address: %s; mspId: %s; message: %s\n", detail.Address, detail.MspId, detail.Message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,154 @@
|
||||||
|
package grpc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/x509"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/hyperledger/fabric-gateway/pkg/client"
|
||||||
|
"github.com/hyperledger/fabric-gateway/pkg/hash"
|
||||||
|
"github.com/hyperledger/fabric-gateway/pkg/identity"
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
"google.golang.org/grpc/credentials"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
rootPath = "/root/go/src/github.com/BennielAllan/fabric-samples"
|
||||||
|
mspID = "Org1MSP"
|
||||||
|
cryptoPath = rootPath + "/test-network/organizations/peerOrganizations/org1.example.com"
|
||||||
|
certPath = cryptoPath + "/users/User1@org1.example.com/msp/signcerts"
|
||||||
|
keyPath = cryptoPath + "/users/User1@org1.example.com/msp/keystore"
|
||||||
|
tlsCertPath = cryptoPath + "/peers/peer0.org1.example.com/tls/ca.crt"
|
||||||
|
peerEndpoint = "dns:///localhost:7051"
|
||||||
|
gatewayPeer = "peer0.org1.example.com"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ClientConnection *grpc.ClientConn
|
||||||
|
GateWay *client.Gateway
|
||||||
|
Contract *client.Contract
|
||||||
|
)
|
||||||
|
|
||||||
|
func InitGWConnect() {
|
||||||
|
// The gRPC client connection should be shared by all Gateway connections to this endpoint
|
||||||
|
ClientConnection = newGrpcConnection()
|
||||||
|
|
||||||
|
id := newIdentity()
|
||||||
|
sign := newSign()
|
||||||
|
|
||||||
|
// Create a Gateway connection for a specific client identity
|
||||||
|
var err error
|
||||||
|
GateWay, err = client.Connect(
|
||||||
|
id,
|
||||||
|
client.WithSign(sign),
|
||||||
|
client.WithHash(hash.SHA256),
|
||||||
|
client.WithClientConnection(ClientConnection),
|
||||||
|
// Default timeouts for different gRPC calls
|
||||||
|
client.WithEvaluateTimeout(5*time.Second),
|
||||||
|
client.WithEndorseTimeout(15*time.Second),
|
||||||
|
client.WithSubmitTimeout(5*time.Second),
|
||||||
|
client.WithCommitStatusTimeout(1*time.Minute),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
// ./network.sh deployCC -ccn ledger -ccp /root/go/src/github.com/BennielAllan/fabric-samples/asset-transfer-ledger-queries/chaincode-go/ -ccl go
|
||||||
|
// Override default values for chaincode and channel name as they may differ in testing contexts.
|
||||||
|
chaincodeName := "ledger"
|
||||||
|
if ccname := os.Getenv("CHAINCODE_NAME"); ccname != "" {
|
||||||
|
chaincodeName = ccname
|
||||||
|
}
|
||||||
|
|
||||||
|
channelName := "mychannel"
|
||||||
|
if cname := os.Getenv("CHANNEL_NAME"); cname != "" {
|
||||||
|
channelName = cname
|
||||||
|
}
|
||||||
|
|
||||||
|
network := GateWay.GetNetwork(channelName)
|
||||||
|
Contract = network.GetContract(chaincodeName)
|
||||||
|
}
|
||||||
|
|
||||||
|
func CloseGWConnect() {
|
||||||
|
GateWay.Close()
|
||||||
|
ClientConnection.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// newGrpcConnection creates a gRPC connection to the Gateway server.
|
||||||
|
func newGrpcConnection() *grpc.ClientConn {
|
||||||
|
certificatePEM, err := os.ReadFile(tlsCertPath)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Errorf("failed to read TLS certifcate file: %w", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
certificate, err := identity.CertificateFromPEM(certificatePEM)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
certPool := x509.NewCertPool()
|
||||||
|
certPool.AddCert(certificate)
|
||||||
|
transportCredentials := credentials.NewClientTLSFromCert(certPool, gatewayPeer)
|
||||||
|
|
||||||
|
connection, err := grpc.NewClient(peerEndpoint, grpc.WithTransportCredentials(transportCredentials))
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Errorf("failed to create gRPC connection: %w", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
return connection
|
||||||
|
}
|
||||||
|
|
||||||
|
// newIdentity creates a client identity for this Gateway connection using an X.509 certificate.
|
||||||
|
func newIdentity() *identity.X509Identity {
|
||||||
|
certificatePEM, err := readFirstFile(certPath)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Errorf("failed to read certificate file: %w", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
certificate, err := identity.CertificateFromPEM(certificatePEM)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
id, err := identity.NewX509Identity(mspID, certificate)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
|
||||||
|
// newSign creates a function that generates a digital signature from a message digest using a private key.
|
||||||
|
func newSign() identity.Sign {
|
||||||
|
privateKeyPEM, err := readFirstFile(keyPath)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Errorf("failed to read private key file: %w", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
privateKey, err := identity.PrivateKeyFromPEM(privateKeyPEM)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
sign, err := identity.NewPrivateKeySign(privateKey)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return sign
|
||||||
|
}
|
||||||
|
|
||||||
|
func readFirstFile(dirPath string) ([]byte, error) {
|
||||||
|
dir, err := os.Open(dirPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
fileNames, err := dir.Readdirnames(1)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return os.ReadFile(path.Join(dirPath, fileNames[0]))
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
package log
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go.uber.org/zap"
|
||||||
|
"go.uber.org/zap/zapcore"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
var logger *zap.Logger
|
||||||
|
|
||||||
|
func InitLog(level, path string) error {
|
||||||
|
// 配置日志级别
|
||||||
|
var logLevel zapcore.Level
|
||||||
|
switch level {
|
||||||
|
case "debug":
|
||||||
|
logLevel = zap.DebugLevel
|
||||||
|
case "info":
|
||||||
|
logLevel = zap.InfoLevel
|
||||||
|
case "warn":
|
||||||
|
logLevel = zap.WarnLevel
|
||||||
|
case "error":
|
||||||
|
logLevel = zap.ErrorLevel
|
||||||
|
case "dpanic":
|
||||||
|
logLevel = zap.DPanicLevel
|
||||||
|
case "panic":
|
||||||
|
logLevel = zap.PanicLevel
|
||||||
|
case "fatal":
|
||||||
|
logLevel = zap.FatalLevel
|
||||||
|
default:
|
||||||
|
logLevel = zap.InfoLevel
|
||||||
|
}
|
||||||
|
|
||||||
|
// 配置日志输出到文件
|
||||||
|
fileEncoderConfig := zap.NewProductionEncoderConfig()
|
||||||
|
fileEncoderConfig.TimeKey = "timestamp"
|
||||||
|
fileEncoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
|
||||||
|
fileEncoder := zapcore.NewJSONEncoder(fileEncoderConfig)
|
||||||
|
|
||||||
|
if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
file, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fileWriter := zapcore.AddSync(file)
|
||||||
|
fileCore := zapcore.NewCore(fileEncoder, fileWriter, logLevel)
|
||||||
|
|
||||||
|
// 创建 logger
|
||||||
|
logger = zap.New(fileCore, zap.AddCaller(), zap.AddStacktrace(zap.ErrorLevel))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetLogger() *zap.Logger {
|
||||||
|
return logger
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
package router
|
||||||
|
|
||||||
|
import (
|
||||||
|
"assetTransfer/internal/api"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SetupRoutes 设置路由
|
||||||
|
func SetupRoutes(r *gin.Engine) {
|
||||||
|
// 定义路由
|
||||||
|
r.POST("/submit", api.SubmitTransaction)
|
||||||
|
r.POST("/evaluate", api.EvaluateTransaction)
|
||||||
|
}
|
||||||
20
asset-transfer-basic/application-gateway-go/main.go
Executable file
20
asset-transfer-basic/application-gateway-go/main.go
Executable file
|
|
@ -0,0 +1,20 @@
|
||||||
|
/*
|
||||||
|
Copyright 2021 IBM All Rights Reserved.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"assetTransfer/cmd"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
if err := cmd.Execute(); err != nil {
|
||||||
|
fmt.Println("Error:", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue