gagliardetto / solana-go

Go SDK library and RPC client for the Solana Blockchain

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

how to get token owner of a token account

BillInUK opened this issue · comments

I use the following code to get owner of token account, but returned me a program id 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'。

	rpcClient := rpc.New(RpcMainNet)
	tokenMintPubKey := solana.MPK(TokenMainNetAddress)
	tokenAccountPubKey := solana.MustPublicKeyFromBase58("3XRNhFEXkV7itJEJMDBN8iRHBgwhgk83XB5K3s3re3Ew")

	tokenAccountInfo, err := rpcClient.GetAccountInfo(context.Background(), tokenAccountPubKey)
	if err != nil {
		fmt.Printf("get account info error %v\n", err)
	}
	fmt.Printf("get token account owner %v\n", tokenAccountInfo.Value)

how can i get the token owner of this token account? like below:
image

Here is how you do it @BillInUK:

package main

import (
	"context"
	"fmt"
	"github.com/gagliardetto/solana-go"
	"github.com/gagliardetto/solana-go/rpc"
)

func main() {
	rpcClient := rpc.New(rpc.MainNetBeta_RPC)
	tokenAccountPubKey := solana.MustPublicKeyFromBase58("3XRNhFEXkV7itJEJMDBN8iRHBgwhgk83XB5K3s3re3Ew")

	// Fetch account info
	accountInfo, err := rpcClient.GetAccountInfo(context.Background(), tokenAccountPubKey)
	if err != nil {
		fmt.Printf("Error retrieving account info: %v\n", err)
		return
	}

	owner := accountInfo.Value.Owner

	// Output the owner of the token account
	fmt.Printf("Token account owner: %v\n", owner.String())
	// OUTPUT: Token account owner: TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA

	// Ensure that data is available
	if accountInfo.Value == nil || accountInfo.Value.Data.GetBinary() == nil {
		fmt.Println("Account data is not available")
		return
	}

	fmt.Println("Trying the second method...")

	data := accountInfo.Value.Data.GetBinary()

	// Check if data length is sufficient to contain Mint and Owner public keys
	if len(data) < 64 {
		fmt.Println("Account data is too short to contain required information")
		return
	}

	// Owner public key starts at byte 32 and spans 32 bytes
	ownerPubKey := solana.PublicKeyFromBytes(data[32:64])

	// Output the owner of the token account
	fmt.Printf("Token account owner from metadata: %v\n", ownerPubKey)
	// OUTPUT: Token account owner: GmKsGRytiVoeMZGmBVCWPcUzJGHVqcvzhP5K9cstdr3E
}

thanks for your help, i will try it !!!

I implemented this functionality by defining my own structure to parse the results of GetAccountInfoWithOpts. The code is as follows:

const (
	SPLTokenProgramId = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
)

type SPLTokenAccountInfo struct {
	IsNative    bool             `json:"isNative"`
	Mint        solana.PublicKey `json:"mint"`
	Owner       solana.PublicKey `json:"owner"`
	State       string           `json:"state"`
	TokenAmount struct {
		Amount      string  `json:"amount"`
		Decimals    int     `json:"decimals"`
		UIAmount    float64 `json:"uiAmount"`
		UIAmountStr string  `json:"uiAmountString"`
	} `json:"tokenAmount"`
}

type SPLTokenAccountData struct {
	TokenAccountInfo SPLTokenAccountInfo `json:"info"`
	Type             string              `json:"type"`
}

type ParsedData struct {
	Parsed  SPLTokenAccountData `json:"parsed"`
	Program string              `json:"program"`
	Space   int                 `json:"space"`
}
func TestGetTokenAccountOwner(t *testing.T) {
	client := rpc.New(DevRpc)

	pubKey := solana.MustPublicKeyFromBase58("EgyMZLY7DrHpYgmQHCrQ8fXJCv7ekfBepxNNizMST9Dh")
	out, err := client.GetAccountInfoWithOpts(
		context.TODO(),
		pubKey,
		&rpc.GetAccountInfoOpts{
			Encoding: solana.EncodingJSONParsed,
		},
	)
	if err != nil {
		panic(err)
	}
	var parsedData ParsedData
	dataBytes, _ := out.Value.Data.MarshalJSON()
	fmt.Println(string(dataBytes))

	err = json.Unmarshal(dataBytes, &parsedData)
	if err != nil {
		fmt.Println("Error parsing JSON:", err)
		return
	}
	// Access parsed data
	fmt.Println("Type:", parsedData.Parsed.Type)
	fmt.Println("Program:", parsedData.Program)
	fmt.Println("Space:", parsedData.Space)
	fmt.Println("IsNative:", parsedData.Parsed.TokenAccountInfo.IsNative)
	fmt.Println("Mint:", parsedData.Parsed.TokenAccountInfo.Mint)
	fmt.Println("Owner:", parsedData.Parsed.TokenAccountInfo.Owner)
	fmt.Println("State:", parsedData.Parsed.TokenAccountInfo.State)
	fmt.Println("Amount:", parsedData.Parsed.TokenAccountInfo.TokenAmount.Amount)
	fmt.Println("Decimals:", parsedData.Parsed.TokenAccountInfo.TokenAmount.Decimals)
	fmt.Println("UIAmount:", parsedData.Parsed.TokenAccountInfo.TokenAmount.UIAmount)
	fmt.Println("UIAmountString:", parsedData.Parsed.TokenAccountInfo.TokenAmount.UIAmountStr)
}

Overall, the code you provided is simpler, avoiding unnecessary struct definitions and JSON parsing.