github.com/darrenli6/fabric-sdk-example@v0.0.0-20220109053535-94b13b56df8c/imocc/application/main.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"context"
     7  	"time"
     8  
     9  	"net/http"
    10  
    11  	"bytes"
    12  
    13  	"github.com/gin-gonic/gin"
    14  	"github.com/hyperledger/fabric-sdk-go/pkg/client/channel"
    15  	"github.com/hyperledger/fabric-sdk-go/pkg/client/event"
    16  	"github.com/hyperledger/fabric-sdk-go/pkg/client/ledger"
    17  	"github.com/hyperledger/fabric-sdk-go/pkg/client/resmgmt"
    18  	"github.com/hyperledger/fabric-sdk-go/pkg/core/config"
    19  	"github.com/hyperledger/fabric-sdk-go/pkg/fabsdk"
    20  )
    21  
    22  func main() {
    23  	router := gin.Default()
    24  
    25  	// 定义路由
    26  	{
    27  		router.POST("/users", userRegister)
    28  		router.GET("/users/:id", queryUser)
    29  		router.DELETE("/users/:id", deleteUser)
    30  		router.GET("/assets/get/:id", queryAsset)
    31  		router.POST("/assets/enroll", assetsEnroll)
    32  		router.POST("/assets/exchange", assetsExchange)
    33  		router.GET("/assets/exchange/history", assetsExchangeHistory)
    34  	}
    35  
    36  	router.Run() // listen and serve on 0.0.0.0:8080
    37  }
    38  
    39  type UserRegisterRequest struct {
    40  	Id   string `form:"id" binding:"required"`
    41  	Name string `form:"name" binding:"required"`
    42  }
    43  
    44  // 用户开户
    45  func userRegister(ctx *gin.Context) {
    46  	// 参数处理
    47  	req := new(UserRegisterRequest)
    48  	if err := ctx.ShouldBind(req); err != nil {
    49  		ctx.AbortWithError(400, err)
    50  		return
    51  	}
    52  
    53  	// 区块链交互
    54  	resp, err := channelExecute("userRegister", [][]byte{
    55  		[]byte(req.Name),
    56  		[]byte(req.Id),
    57  	})
    58  
    59  	if err != nil {
    60  		ctx.String(http.StatusOK, err.Error())
    61  		return
    62  	}
    63  
    64  	ctx.JSON(http.StatusOK, resp)
    65  }
    66  
    67  // 查询用户
    68  func queryUser(ctx *gin.Context) {
    69  	userId := ctx.Param("id")
    70  
    71  	resp, err := channelQuery("queryUser", [][]byte{
    72  		[]byte(userId),
    73  	})
    74  
    75  	if err != nil {
    76  		ctx.String(http.StatusOK, err.Error())
    77  		return
    78  	}
    79  
    80  	//ctx.JSON(http.StatusOK, resp)
    81  	ctx.String(http.StatusOK, bytes.NewBuffer(resp.Payload).String())
    82  }
    83  
    84  // 用户销户
    85  func deleteUser(ctx *gin.Context) {
    86  	userId := ctx.Param("id")
    87  
    88  	resp, err := channelExecute("userDestroy", [][]byte{
    89  		[]byte(userId),
    90  	})
    91  
    92  	if err != nil {
    93  		ctx.String(http.StatusOK, err.Error())
    94  		return
    95  	}
    96  
    97  	ctx.JSON(http.StatusOK, resp)
    98  }
    99  
   100  // 资产查询
   101  func queryAsset(ctx *gin.Context) {
   102  	assetId := ctx.Param("id")
   103  
   104  	resp, err := channelQuery("queryAsset", [][]byte{
   105  		[]byte(assetId),
   106  	})
   107  
   108  	if err != nil {
   109  		ctx.String(http.StatusOK, err.Error())
   110  		return
   111  	}
   112  
   113  	//ctx.JSON(http.StatusOK, resp)
   114  	ctx.String(http.StatusOK, bytes.NewBuffer(resp.Payload).String())
   115  }
   116  
   117  type AssetsEnrollRequest struct {
   118  	AssetId   string `form:"assetsid" binding:"required"`
   119  	AssetName string `form:"assetname" binding:"required"`
   120  	Metadata  string `form:"metadata" binding:"required"`
   121  	OwnerId   string `form:"ownerid" binding:"required"`
   122  }
   123  
   124  // 资产登记
   125  func assetsEnroll(ctx *gin.Context) {
   126  	req := new(AssetsEnrollRequest)
   127  	if err := ctx.ShouldBind(req); err != nil {
   128  		ctx.AbortWithError(400, err)
   129  		return
   130  	}
   131  
   132  	resp, err := channelExecute("assetEnroll", [][]byte{
   133  		[]byte(req.AssetName),
   134  		[]byte(req.AssetId),
   135  		[]byte(req.Metadata),
   136  		[]byte(req.OwnerId),
   137  	})
   138  
   139  	if err != nil {
   140  		ctx.String(http.StatusOK, err.Error())
   141  		return
   142  	}
   143  
   144  	ctx.JSON(http.StatusOK, resp)
   145  }
   146  
   147  type AssetsExchangeRequest struct {
   148  	AssetId        string `form:"assetsid" binding:"required"`
   149  	OriginOwnerId  string `form:"originownerid" binding:"required"`
   150  	CurrentOwnerId string `form:"currentownerid" binding:"required"`
   151  }
   152  
   153  // 资产转让
   154  func assetsExchange(ctx *gin.Context) {
   155  	req := new(AssetsExchangeRequest)
   156  	if err := ctx.ShouldBind(req); err != nil {
   157  		ctx.AbortWithError(400, err)
   158  		return
   159  	}
   160  
   161  	resp, err := channelExecute("assetExchange", [][]byte{
   162  		[]byte(req.OriginOwnerId),
   163  		[]byte(req.AssetId),
   164  		[]byte(req.CurrentOwnerId),
   165  	})
   166  
   167  	if err != nil {
   168  		ctx.String(http.StatusOK, err.Error())
   169  		return
   170  	}
   171  
   172  	ctx.JSON(http.StatusOK, resp)
   173  }
   174  
   175  // 资产历史变更记录
   176  func assetsExchangeHistory(ctx *gin.Context) {
   177  	assetId := ctx.Query("assetid")
   178  	queryType := ctx.Query("querytype")
   179  
   180  	resp, err := channelQuery("queryAssetHistory", [][]byte{
   181  		[]byte(assetId),
   182  		[]byte(queryType),
   183  	})
   184  
   185  	if err != nil {
   186  		ctx.String(http.StatusOK, err.Error())
   187  		return
   188  	}
   189  
   190  	//ctx.JSON(http.StatusOK, resp)
   191  	ctx.String(http.StatusOK, bytes.NewBuffer(resp.Payload).String())
   192  }
   193  
   194  var (
   195  	sdk           *fabsdk.FabricSDK
   196  	channelName   = "assetschannel"
   197  	chaincodeName = "assets"
   198  	org           = "org1"
   199  	user          = "Admin"
   200  	//configPath    = "$GOPATH/src/github.com/hyperledger/fabric/imocc/application/config.yaml"
   201  	configPath = "./config.yaml"
   202  )
   203  
   204  func init() {
   205  	var err error
   206  	sdk, err = fabsdk.New(config.FromFile(configPath))
   207  	if err != nil {
   208  		panic(err)
   209  	}
   210  }
   211  
   212  // 区块链管理
   213  func manageBlockchain() {
   214  	// 表明身份
   215  	ctx := sdk.Context(fabsdk.WithOrg(org), fabsdk.WithUser(user))
   216  
   217  	cli, err := resmgmt.New(ctx)
   218  	if err != nil {
   219  		panic(err)
   220  	}
   221  
   222  	// 具体操作
   223  	cli.SaveChannel(resmgmt.SaveChannelRequest{}, resmgmt.WithOrdererEndpoint("orderer.imocc.com"), resmgmt.WithTargetEndpoints())
   224  }
   225  
   226  // 区块链数据查询 账本的查询
   227  func queryBlockchain() {
   228  	ctx := sdk.ChannelContext(channelName, fabsdk.WithOrg(org), fabsdk.WithUser(user))
   229  
   230  	cli, err := ledger.New(ctx)
   231  	if err != nil {
   232  		panic(err)
   233  	}
   234  
   235  	resp, err := cli.QueryInfo(ledger.WithTargetEndpoints("peer0.org1.imocc.com"))
   236  	if err != nil {
   237  		panic(err)
   238  	}
   239  
   240  	fmt.Println(resp)
   241  
   242  	// 1
   243  	cli.QueryBlockByHash(resp.BCI.CurrentBlockHash)
   244  
   245  	// 2
   246  	for i := uint64(0); i <= resp.BCI.Height; i++ {
   247  		cli.QueryBlock(i)
   248  	}
   249  }
   250  
   251  // 区块链交互
   252  func channelExecute(fcn string, args [][]byte) (channel.Response, error) {
   253  	ctx := sdk.ChannelContext(channelName, fabsdk.WithOrg(org), fabsdk.WithUser(user))
   254  
   255  	cli, err := channel.New(ctx)
   256  	if err != nil {
   257  		return channel.Response{}, err
   258  	}
   259  
   260  	// 状态更新,insert/update/delete
   261  	resp, err := cli.Execute(channel.Request{
   262  		ChaincodeID: chaincodeName,
   263  		Fcn:         fcn,
   264  		Args:        args,
   265  	}, channel.WithTargetEndpoints("peer0.org1.imocc.com"))
   266  	if err != nil {
   267  		return channel.Response{}, err
   268  	}
   269  
   270  	// 链码事件监听
   271  	go func() {
   272  		// channel
   273  		reg, ccevt, err := cli.RegisterChaincodeEvent(chaincodeName, "eventname")
   274  		if err != nil {
   275  			return
   276  		}
   277  		defer cli.UnregisterChaincodeEvent(reg)
   278  
   279  		timeoutctx, cancel := context.WithTimeout(context.Background(), time.Minute)
   280  		defer cancel()
   281  
   282  		for {
   283  			select {
   284  			case evt := <-ccevt:
   285  				fmt.Printf("received event of tx %s: %+v", resp.TransactionID, evt)
   286  			case <-timeoutctx.Done():
   287  				fmt.Println("event timeout, exit!")
   288  				return
   289  			}
   290  		}
   291  
   292  		// event
   293  		//eventcli, err := event.New(ctx)
   294  		//if err != nil {
   295  		//	return
   296  		//}
   297  
   298  		//eventcli.RegisterChaincodeEvent(chaincodeName, "eventname")
   299  	}()
   300  
   301  	// 交易状态事件监听
   302  	go func() {
   303  		eventcli, err := event.New(ctx)
   304  		if err != nil {
   305  			return
   306  		}
   307  
   308  		reg, status, err := eventcli.RegisterTxStatusEvent(string(resp.TransactionID))
   309  		defer eventcli.Unregister(reg) // 注册必有注销
   310  
   311  		timeoutctx, cancel := context.WithTimeout(context.Background(), time.Minute)
   312  		defer cancel()
   313  
   314  		for {
   315  			select {
   316  			case evt := <-status:
   317  				fmt.Printf("received event of tx %s: %+v", resp.TransactionID, evt)
   318  			case <-timeoutctx.Done():
   319  				fmt.Println("event timeout, exit!")
   320  				return
   321  			}
   322  		}
   323  	}()
   324  
   325  	return resp, nil
   326  }
   327  
   328  func channelQuery(fcn string, args [][]byte) (channel.Response, error) {
   329  	ctx := sdk.ChannelContext(channelName, fabsdk.WithOrg(org), fabsdk.WithUser(user))
   330  
   331  	cli, err := channel.New(ctx)
   332  	if err != nil {
   333  		return channel.Response{}, err
   334  	}
   335  
   336  	// 状态的查询,select
   337  	return cli.Query(channel.Request{
   338  		ChaincodeID: chaincodeName,
   339  		Fcn:         fcn,
   340  		Args:        args,
   341  	}, channel.WithTargetEndpoints("peer0.org1.imocc.com"))
   342  }
   343  
   344  // 事件监听
   345  func eventHandle() {
   346  	ctx := sdk.ChannelContext(channelName, fabsdk.WithOrg(org), fabsdk.WithUser(user))
   347  
   348  	cli, err := event.New(ctx)
   349  	if err != nil {
   350  		panic(err)
   351  	}
   352  
   353  	// 交易状态事件
   354  	// 链码事件 业务事件
   355  	// 区块事件
   356  	reg, blkevent, err := cli.RegisterBlockEvent()
   357  	if err != nil {
   358  		panic(err)
   359  	}
   360  	defer cli.Unregister(reg)
   361  
   362  	timeoutctx, cancel := context.WithTimeout(context.Background(), time.Minute)
   363  	defer cancel()
   364  
   365  	for {
   366  		select {
   367  		case evt := <-blkevent:
   368  			fmt.Printf("received a block", evt)
   369  		case <-timeoutctx.Done():
   370  			fmt.Println("event timeout, exit!")
   371  			return
   372  		}
   373  	}
   374  }