原文链接:https://dev.to/brymes/solana-blinks-with-go-j4i
Blinks 是多元化的链接(metadata-rich links),代表并启用 Solana 生态系统中的链上活动,而无需导航到不同的应用程序或网页。 Blinks 支持 Solana Actions 启用的广泛活动,主要允许用户通过社交媒体和其他链下平台与区块链互动。
在本文中,我们将探讨一个使用 Go 的简单 Blink 应用,专注于铸造 NFTs。虽然本文侧重于 Go,但核心概念适用于任何 Blink 应用。你可以在 GitHub 上找到完整代码。 我们将首先使用 Gin 框架设置一个基本的 Web 服务器,以及按照规范定义的必要 CORS 配置。同时,我们将定义一些在下面详细讨论的端点。
func main() {
var (
corsConfig = cors.DefaultConfig()
router = gin.Default()
port = os.Getenv("PORT")
)
corsConfig.AllowAllOrigins = true
corsConfig.AddAllowHeaders([]string{"Content-Length", "Content-Type", "Access-Control-Allow-Origin"}...)
corsConfig.AddAllowMethods([]string{"GET", "POST", "OPTIONS"}...)
router.Use(cors.New(corsConfig))
router.GET("/actions.json", app.ActionsRulesHandler)
router.GET("/api/actions/mint_nft", app.GetActionsHandler)
router.OPTIONS("/api/actions/mint_nft", app.OptionsHandler)
router.POST("/api/actions/mint_nft", app.PostHandler)
log.Println("StickyLabs Blink Active 🚀")
if port == "" {
port = "8081"
}
log.Println("Server is running")
err := router.Run(fmt.Sprintf(":%v", port))
if err != nil {
log.Fatal(err)
return
}
}
任何 Blinks 应用的核心在于复制 Solana Actions API 规范。以下是 Blinks 工作方式的视觉表示。
Solana 上的 Blinks 使用一个 Action URL 方案来提供元数据丰富的链接,启用各种链上活动。本节概述了处理 /api/actions/mint_nft 铸造 NFT 操作的主要处理程序。
GET 处理程序:返回元数据、支持的操作和所需的参数。
type ActionGetResponse struct {
Title string `json:"title"`
Icon string `json:"icon"`
Description string `json:"description"`
Label string `json:"label"`
Links struct {
Actions []Actions `json:"actions"`
} `json:"links"`
}
type Actions struct {
Label string `json:"label"`
Href string `json:"href"`
Parameters []ActionParameters `json:"parameters,omitempty"`
}
type ActionParameters struct {
Name string `json:"name"`
Label string `json:"label"`
Required bool `json:"required"`
}
func GetActionsHandler(c *gin.Context) {
payload := ActionGetResponse{
Title: "Actions Example - Mint NFT",
Icon: c.Request.URL.Scheme + "://" + c.Request.URL.Host + "/solana_devs.jpg",
Description: "Transfer SOL to another Solana wallet",
Label: "Transfer",
}
payload.Links.Actions = []Actions{
{"Mint NFT", "/api/actions/mint_nft", []ActionParameters{
{"name", "Enter the Name of the NFT", true},
{"symbol", "Enter the Symbol of the NFT", true},
{"uri", "Enter the Uri of the NFT", true},
}},
}
c.JSON(http.StatusOK, payload)
}
OPTIONS 处理程序:OPTIONS 处理程序处理 CORS 要求,确保与浏览器和其他客户端请求机制的兼容性。
```go
var ACTIONS_CORS_HEADERS = map[string]string{
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET,POST,OPTIONS",
"Access-Control-Allow-Headers": "Content-Type",
}
func OptionsHandler(c *gin.Context) {
for key, value := range ACTIONS_CORS_HEADERS {
c.Header(key, value)
}
c.Status(http.StatusOK)
}
POST 处理程序:POST 处理程序接受查询参数,解析 base58 形式的账户信息,返回一个 base64 编码的序列化交易以及供用户签名和执行的消息。
type MintNFTParams struct {
Name string `form:"name" binding:"required"`
Symbol string `form:"symbol" binding:"required"`
URI string `form:"uri" binding:"required"`
}
// { "account": "<account>" } //JSONtype ActionPostRequest struct {
Account string `json:"account"`
}
type ActionPostResponse struct {
Fields ActionPostResponseFields `json:"fields"`
}
type ActionPostResponseFields struct {
Transaction string `json:"transaction"`
Message string `json:"message"`
}
func PostHandler(c *gin.Context) {
var (
qPayload MintNFTParams
request ActionPostRequest
response ActionPostResponse
)
if err := c.ShouldBindQuery(&qPayload); err != nil {
c.JSON(http.StatusBadRequest, ActionError{Message: "Invalid Query Params"})
return
}
if err := c.ShouldBindJSON(&request); err != nil {
log.Println(err)
c.JSON(http.StatusBadRequest, ActionError{Message: "Invalid request"})
return
}
account, err := types.AccountFromBase58(request.Account)
if err != nil {
log.Println(err)
c.JSON(http.StatusBadRequest, ActionError{Message: "Invalid request; Error validating account"})
return
}
response.Fields.Transaction, response.Fields.Message = mintNFT(qPayload, account)
c.JSON(http.StatusOK, response)
}
mintNFT 函数利用 Solana-Go-SDK 进行 NFT 铸造,并进行了一些调整。
unc mintNFT(metadata MintNFTParams, feePayer types.Account) (transaction, message string) {
// 省略其他代码
}
错误处理:操作应返回用户友好的错误,格式如下。
type ActionError struct {
Message string `json:"message"`
}
actions.json:actions.json 文件应存储在域的根目录下。它为客户端提供支持 Solana Actions 的 URL 说明,并提供可用于对 Blink 应用执行 GET 请求的映射。为简单起见,我们会从 URL 路径返回一个 JSON 响应。
func ActionsRulesHandler(c *gin.Context) {
payload := gin.H{
"rules": []gin.H{
{
"pathPattern": "/*",
"apiPath": "/api/actions/*",
},
{
"pathPattern": "/api/actions/",
"apiPath": "/api/actions/",
},
},
}
c.JSON(http.StatusOK, payload)
}
部署应用后,你可以使用 Blinks Inspector 应用进行测试。 Blinks Inspector 示例
希望本文能为在 Solana 上使用 Go 构建 Blinks 应用提供实用的介绍。完整代码可以在此找到。 要深入了解 Solana Actions 框架和详细文档,请查阅 Solana 官方资源。