diff --git a/examples/gin/.gitignore b/examples/gin/.gitignore new file mode 100644 index 0000000..f0773c2 --- /dev/null +++ b/examples/gin/.gitignore @@ -0,0 +1,238 @@ +# Created by https://www.toptal.com/developers/gitignore/api/goland,go,macos,linux,windows,git +# Edit at https://www.toptal.com/developers/gitignore?templates=goland,go,macos,linux,windows,git + +### Git ### +# Created by git for backups. To disable backups in Git: +# $ git config --global mergetool.keepBackup false +*.orig + +# Created by git when using merge tools for conflicts +*.BACKUP.* +*.BASE.* +*.LOCAL.* +*.REMOTE.* +*_BACKUP_*.txt +*_BASE_*.txt +*_LOCAL_*.txt +*_REMOTE_*.txt + +### Go ### +# If you prefer the allow list template instead of the deny list, see community template: +# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore +# +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories (remove the comment below to include it) +# vendor/ + +# Go workspace file +go.work + +### Go Patch ### +/vendor/ +/Godeps/ + +### GoLand ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf +.idea/ + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### GoLand Patch ### +# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 + +# *.iml +# modules.xml +# .idea/misc.xml +# *.ipr + +# Sonarlint plugin +# https://plugins.jetbrains.com/plugin/7973-sonarlint +.idea/**/sonarlint/ + +# SonarQube Plugin +# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin +.idea/**/sonarIssues.xml + +# Markdown Navigator plugin +# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced +.idea/**/markdown-navigator.xml +.idea/**/markdown-navigator-enh.xml +.idea/**/markdown-navigator/ + +# Cache file creation bug +# See https://youtrack.jetbrains.com/issue/JBR-2257 +.idea/$CACHE_FILE$ + +# CodeStream plugin +# https://plugins.jetbrains.com/plugin/12206-codestream +.idea/codestream.xml + +# Azure Toolkit for IntelliJ plugin +# https://plugins.jetbrains.com/plugin/8053-azure-toolkit-for-intellij +.idea/**/azureSettings.xml + +### Linux ### +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### macOS Patch ### +# iCloud generated files +*.icloud + +### Windows ### +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# End of https://www.toptal.com/developers/gitignore/api/goland,go,macos,linux,windows,git + +.env +/contract/node_modules/ +/tmp \ No newline at end of file diff --git a/examples/gin/Dockerfile b/examples/gin/Dockerfile new file mode 100644 index 0000000..5c6199a --- /dev/null +++ b/examples/gin/Dockerfile @@ -0,0 +1,22 @@ +FROM golang:1.22.4 as builder + +WORKDIR /app + +COPY go.mod . +COPY go.sum . + +# Install dependencies before build +RUN go mod download + +COPY . . + +RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o blink_app . + +FROM alpine:latest + +RUN apk update && apk add ca-certificates && rm -rf /var/cache/apk/* + + +COPY --from=builder /app/blink_app . + +ENTRYPOINT ["./blink_app"] \ No newline at end of file diff --git a/examples/gin/README.md b/examples/gin/README.md new file mode 100644 index 0000000..36905ee --- /dev/null +++ b/examples/gin/README.md @@ -0,0 +1,16 @@ +# Solana Action: Mint NFT + +This example includes a Solana Action built in Go using the Gin framework and Solana-Go-SDK. It +provides an API endpoint for minting an NFT. + +Navigate to `./examples/gin` and start the application: + +``` go +go run main.go +``` + +The server will start running on . + +The endpoint for the Action is: + +You can test the Action using [Blinks Inspector](https://www.blinks.xyz/inspector) \ No newline at end of file diff --git a/examples/gin/app/handlers.go b/examples/gin/app/handlers.go new file mode 100644 index 0000000..8a6bc8c --- /dev/null +++ b/examples/gin/app/handlers.go @@ -0,0 +1,83 @@ +package app + +import ( + "github.com/blocto/solana-go-sdk/types" + "github.com/gin-gonic/gin" + "log" + "net/http" +) + +const ( + RPC_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) +} + +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) +} + +func OptionsHandler(c *gin.Context) { + for key, value := range ACTIONS_CORS_HEADERS { + c.Header(key, value) + } + c.Status(http.StatusOK) +} + +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) +} diff --git a/examples/gin/app/mint_nft.go b/examples/gin/app/mint_nft.go new file mode 100644 index 0000000..d0fcbcd --- /dev/null +++ b/examples/gin/app/mint_nft.go @@ -0,0 +1,148 @@ +package app + +import ( + "context" + "encoding/base64" + "fmt" + "github.com/blocto/solana-go-sdk/client" + "github.com/blocto/solana-go-sdk/common" + "github.com/blocto/solana-go-sdk/pkg/pointer" + "github.com/blocto/solana-go-sdk/program/associated_token_account" + "github.com/blocto/solana-go-sdk/program/metaplex/token_metadata" + "github.com/blocto/solana-go-sdk/program/system" + "github.com/blocto/solana-go-sdk/program/token" + "github.com/blocto/solana-go-sdk/rpc" + "github.com/blocto/solana-go-sdk/types" + "log" +) + +func mintNFT(metadata MintNFTParams, feePayer types.Account) (transaction, message string) { + // https://github.com/rayzub/solana-go-sdk/blob/v1.18.68/docs/_examples/nft/mint-a-nft-with-master-edition-v2/main.go + // https://github.com/Keleigh123/solana-nft-minting/blob/master/mintNFT/fullCodeToMint.go + + 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) + } + // + //sig, err := c.SendTransaction(context.Background(), tx) + //if err != nil { + // log.Fatalf("failed to send tx, err: %v", err) + //} + // + //fmt.Println("txid:", sig) + transaction = base64.StdEncoding.EncodeToString(serialized) + return +} diff --git a/examples/gin/app/schema.go b/examples/gin/app/schema.go new file mode 100644 index 0000000..c086790 --- /dev/null +++ b/examples/gin/app/schema.go @@ -0,0 +1,51 @@ +package app + +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"` +} + +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"` +} + +type ActionError struct { + Message string `json:"message"` +} + +type MintNFTParams struct { + Name string `form:"name" binding:"required"` + Symbol string `form:"symbol" binding:"required"` + URI string `form:"uri" binding:"required"` +} + +var ACTIONS_CORS_HEADERS = map[string]string{ + "Access-Control-Allow-Origin": "*", + "Access-Control-Allow-Methods": "GET,POST,OPTIONS", + "Access-Control-Allow-Headers": "Content-Type", +} diff --git a/examples/gin/docker-compose.yml b/examples/gin/docker-compose.yml new file mode 100644 index 0000000..57be468 --- /dev/null +++ b/examples/gin/docker-compose.yml @@ -0,0 +1,9 @@ +version: '3.8' + +services: + blinks-app: + build: . + network_mode: host + container_name: blinks-app + restart: always + diff --git a/examples/gin/go.mod b/examples/gin/go.mod new file mode 100644 index 0000000..d5be6c0 --- /dev/null +++ b/examples/gin/go.mod @@ -0,0 +1,42 @@ +module StickyLabsBlinks + +go 1.22.4 + +require ( + github.com/blocto/solana-go-sdk v1.30.0 + github.com/gin-contrib/cors v1.7.2 + github.com/gin-gonic/gin v1.10.0 +) + +require ( + filippo.io/edwards25519 v1.0.0-rc.1 // indirect + 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/json-iterator/go v1.1.12 // indirect + github.com/klauspost/cpuid/v2 v2.2.7 // indirect + github.com/kr/text v0.2.0 // indirect + github.com/leodido/go-urn v1.4.0 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/mr-tron/base58 v1.2.0 // indirect + github.com/near/borsh-go v0.3.2-0.20220516180422-1ff87d108454 // indirect + github.com/pelletier/go-toml/v2 v2.2.2 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/ugorji/go/codec v1.2.12 // indirect + golang.org/x/arch v0.8.0 // indirect + golang.org/x/crypto v0.23.0 // indirect + golang.org/x/net v0.25.0 // indirect + golang.org/x/sys v0.20.0 // indirect + golang.org/x/text v0.15.0 // indirect + google.golang.org/protobuf v1.34.1 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/examples/gin/go.sum b/examples/gin/go.sum new file mode 100644 index 0000000..61b1b5c --- /dev/null +++ b/examples/gin/go.sum @@ -0,0 +1,107 @@ +filippo.io/edwards25519 v1.0.0-rc.1 h1:m0VOOB23frXZvAOK44usCgLWvtsxIoMCTBGJZlpmGfU= +filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= +github.com/blocto/solana-go-sdk v1.30.0 h1:GEh4GDjYk1lMhV/hqJDCyuDeCuc5dianbN33yxL88NU= +github.com/blocto/solana-go-sdk v1.30.0/go.mod h1:Xoyhhb3hrGpEQ5rJps5a3OgMwDpmEhrd9bgzFKkkwMs= +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/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +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/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/cors v1.7.2 h1:oLDHxdg8W/XDoN/8zamqk/Drgt4oVZDvaV0YmvVICQw= +github.com/gin-contrib/cors v1.7.2/go.mod h1:SUJVARKgQ40dmrzgXEVxj2m7Ig1v1qIboQkPDTQ9t2E= +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.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +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/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +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/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/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= +github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/near/borsh-go v0.3.2-0.20220516180422-1ff87d108454 h1:lFN7TVecCMbCHVNfEofDqqaVsuAlkFyDmmO7EF4nXj4= +github.com/near/borsh-go v0.3.2-0.20220516180422-1ff87d108454/go.mod h1:NeMochZp7jN/pYFuxLkrZtmLqbADmnp/y1+/dL+AsyQ= +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/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= +github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= +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/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/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= +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.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +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.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +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/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= diff --git a/examples/gin/main.go b/examples/gin/main.go new file mode 100644 index 0000000..b0c07e9 --- /dev/null +++ b/examples/gin/main.go @@ -0,0 +1,42 @@ +package main + +import ( + "StickyLabsBlinks/app" + "fmt" + "github.com/gin-contrib/cors" + "github.com/gin-gonic/gin" + "log" + "os" +) + +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 + } +}