文章/教程 使用 Go 打造 Solana Blinks

QIUQIU · 2024年08月30日 · 最后由 daog1 回复于 2024年09月05日 · 291 次阅读

原文链接:https://dev.to/brymes/solana-blinks-with-go-j4i

Blinks 是多元化的链接(metadata-rich links),代表并启用 Solana 生态系统中的链上活动,而无需导航到不同的应用程序或网页。 Blinks 支持 Solana Actions 启用的广泛活动,主要允许用户通过社交媒体和其他链下平台与区块链互动。

使用场景包括:

  • NFT 交易与铸造;
  • 捐赠;
  • 众筹;
  • 代币兑换;
  • 彩票/赌场应用等等

在本文中,我们将探讨一个使用 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)
}

铸造 NFTs

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 官方资源。

噢,这个就是 go 写一个 web 服务器,提供 solana 的合约交互,挺好,学习了。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号