Solana Berkelip dengan Pergi

王林
Lepaskan: 2024-08-24 06:37:44
asal
272 orang telah melayarinya

Blinks ialah pautan kaya metadata yang mewakili dan mendayakan aktiviti dalam rantaian di seluruh ekosistem Solana tanpa perlu menavigasi ke apl atau halaman web lain.

Blinks menyokong pelbagai aktiviti yang didayakan oleh Solana Actions
dan terutamanya membenarkan pengguna berinteraksi dengan blockchain melalui media sosial dan platform luar rantaian yang lain.

Kes Penggunaan termasuk:

  • Perdagangan & pencetakan NFT,
  • Derma,
  • Pembiayaan orang ramai,
  • Pertukaran token,
  • Apl Loteri/Kasino dan banyak lagi

Dalam artikel ini, kami akan meneroka apl Blink mudah yang memfokuskan pada mencetak NFT menggunakan Go. Walaupun artikel itu difokuskan kepada Go, konsep teras digunakan pada mana-mana apl Blink. Anda boleh mendapatkan kod lengkap di GitHub.

Kami akan bermula dengan menyediakan pelayan web asas menggunakan rangka kerja Gin, bersama-sama dengan konfigurasi CORS yang diperlukan seperti yang ditakrifkan oleh spesifikasi. Kami juga akan mentakrifkan beberapa titik akhir yang akan dibincangkan secara terperinci di bawah.

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
    }
}

Salin selepas log masuk

Inti bagi mana-mana aplikasi Blinks terletak pada mereplikasi Spesifikasi API Solana Actions. Di bawah ialah gambaran visual tentang cara Blinks berfungsi.

Solana Blinks with Go

Pengendali Tindakan

Blinks on Solana menggunakan skema URL Tindakan untuk menyediakan pautan yang kaya dengan metadata, membolehkan pelbagai aktiviti dalam rantaian. Bahagian ini menggariskan pengendali utama yang bertanggungjawab untuk memproses tindakan NFT pudina pada /api/actions/mint_nft

  • DAPATKAN Pengendali : Mengembalikan Metadata, tindakan yang disokong dan parameter yang diperlukan.
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)
}
Salin selepas log masuk
  • OPTIONS : Pengendali OPTIONS mengendalikan keperluan CORS, memastikan keserasian dengan penyemak imbas dan mekanisme permintaan pelanggan yang lain.
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)
}
Salin selepas log masuk
  • Pengendali POST :Pengendali POST menerima parameter pertanyaan, menghuraikan akaun dalam base58 yang disediakan sebagai JSON, dan mengembalikan transaksi bersiri yang dikodkan base64 bersama-sama dengan mesej untuk ditandatangani dan dilaksanakan oleh pengguna.
type MintNFTParams struct {
    Name   string `form:"name"   binding:"required"`
    Symbol string `form:"symbol" binding:"required"`
    URI    string `form:"uri"    binding:"required"`
}

// {  "account": "<account>" } //JSON
type 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)
}


Salin selepas log masuk
  • Mencetak NFT

Fungsi mintNFT memanfaatkan Solana-Go-SDK untuk mencetak NFT, dengan sedikit pelarasan.

func mintNFT(metadata MintNFTParams, feePayer types.Account) (transaction, message string) {

    message = fmt.Sprintf("Mint NFT %s", metadata.Name)

    c := client.NewClient(rpc.DevnetRPCEndpoint)
    log.Println(metadata)

    mint := types.NewAccount()
    fmt.Printf("NFT: %v\n", mint.PublicKey.ToBase58())

    collection := types.NewAccount()
    fmt.Printf("collection: %v\n", collection.PublicKey.ToBase58())

    ata, _, err := common.FindAssociatedTokenAddress(feePayer.PublicKey, mint.PublicKey)
    if err != nil {
        log.Fatalf("failed to find a valid ata, err: %v", err)
    }

    tokenMetadataPubkey, err := token_metadata.GetTokenMetaPubkey(mint.PublicKey)
    if err != nil {
        log.Fatalf("failed to find a valid token metadata, err: %v", err)

    }
    tokenMasterEditionPubkey, err := token_metadata.GetMasterEdition(mint.PublicKey)
    if err != nil {
        log.Fatalf("failed to find a valid master edition, err: %v", err)
    }

    mintAccountRent, err := c.GetMinimumBalanceForRentExemption(context.Background(), token.MintAccountSize)
    if err != nil {
        log.Fatalf("failed to get mint account rent, err: %v", err)
    }

    recentBlockhashResponse, err := c.GetLatestBlockhash(context.Background())
    if err != nil {
        log.Fatalf("failed to get recent blockhash, err: %v", err)
    }

    tx, err := types.NewTransaction(types.NewTransactionParam{
        Signers: []types.Account{mint, feePayer},
        Message: types.NewMessage(types.NewMessageParam{
            FeePayer:        feePayer.PublicKey,
            RecentBlockhash: recentBlockhashResponse.Blockhash,
            Instructions: []types.Instruction{
                system.CreateAccount(system.CreateAccountParam{
                    From:     feePayer.PublicKey,
                    New:      mint.PublicKey,
                    Owner:    common.TokenProgramID,
                    Lamports: mintAccountRent,
                    Space:    token.MintAccountSize,
                }),
                token.InitializeMint(token.InitializeMintParam{
                    Decimals:   0,
                    Mint:       mint.PublicKey,
                    MintAuth:   feePayer.PublicKey,
                    FreezeAuth: &feePayer.PublicKey,
                }),
                token_metadata.CreateMetadataAccountV3(token_metadata.CreateMetadataAccountV3Param{
                    Metadata:                tokenMetadataPubkey,
                    Mint:                    mint.PublicKey,
                    MintAuthority:           feePayer.PublicKey,
                    Payer:                   feePayer.PublicKey,
                    UpdateAuthority:         feePayer.PublicKey,
                    UpdateAuthorityIsSigner: true,
                    IsMutable:               true,
                    Data: token_metadata.DataV2{
                        Name:                 metadata.Name,
                        Symbol:               metadata.Symbol,
                        Uri:                  metadata.URI,
                        SellerFeeBasisPoints: 100,
                        Creators: &[]token_metadata.Creator{
                            // tODO rede && Minter
                            {
                                Address:  feePayer.PublicKey,
                                Verified: true,
                                Share:    100,
                            },
                        },
                        Collection: &token_metadata.Collection{
                            Verified: false,
                            Key:      collection.PublicKey,
                        },
                        Uses: nil,
                    },
                    CollectionDetails: nil,
                }),
                associated_token_account.Create(associated_token_account.CreateParam{
                    Funder:                 feePayer.PublicKey,
                    Owner:                  feePayer.PublicKey,
                    Mint:                   mint.PublicKey,
                    AssociatedTokenAccount: ata,
                }),
                token.MintTo(token.MintToParam{
                    Mint:   mint.PublicKey,
                    To:     ata,
                    Auth:   feePayer.PublicKey,
                    Amount: 1,
                }),
                token_metadata.CreateMasterEditionV3(token_metadata.CreateMasterEditionParam{
                    Edition:         tokenMasterEditionPubkey,
                    Mint:            mint.PublicKey,
                    UpdateAuthority: feePayer.PublicKey,
                    MintAuthority:   feePayer.PublicKey,
                    Metadata:        tokenMetadataPubkey,
                    Payer:           feePayer.PublicKey,
                    MaxSupply:       pointer.Get[uint64](0),
                }),
            },
        }),
    })
    if err != nil {
        log.Fatalf("failed to new a tx, err: %v", err)
    }

    serialized, err := tx.Serialize()
    if err != nil {
        log.Fatal(err)
    }

    transaction = base64.StdEncoding.EncodeToString(serialized)
    return
}

Salin selepas log masuk
  • Pengendalian Ralat: Tindakan harus mengembalikan ralat mesra pengguna dalam format di bawah.
// { "message" : "Insert Error Message" } //JSON
type ActionError struct {
    Message string `json:"message"`
}

Salin selepas log masuk
  • actions.json: Fail actions.json hendaklah disimpan pada akar domain. Ia memberikan arahan kepada pelanggan tentang URL yang menyokong Solana Actions dan menyediakan pemetaan yang boleh digunakan untuk melaksanakan permintaan GET kepada apl Blink. Untuk kesederhanaan kami akan mengembalikan respons JSON dari laluan url
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)
}
Salin selepas log masuk

Menguji Blink anda

Selepas menggunakan apl anda, anda boleh menggunakan apl Blinks Inspector untuk menguji.

Solana Blinks with Go

Kesimpulan

Saya harap artikel ini memberikan pengenalan praktikal untuk membina aplikasi Blinks pada Solana menggunakan Go. Keseluruhan kod boleh didapati di sini.

Untuk menyelami rangka kerja Solana Actions dan dokumentasi terperinci, lihat sumber rasmi Solana

Atas ialah kandungan terperinci Solana Berkelip dengan Pergi. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:dev.to
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan
Tentang kita Penafian Sitemap
Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!