blocto / solana-go-sdk

Solana Golang SDK
https://blocto.github.io/solana-go-sdk/
MIT License
385 stars 101 forks source link

connect to the blockchain #59

Closed scottywm closed 2 years ago

scottywm commented 2 years ago

Hey guys, in all of the examples they are not actually using real accounts or tokens or even directly connecting to the block chain. i need to know how I can actually connect to the blockchain to send tokens to other sol addresses.

In all the examples they connect to a simulated blockchain doing this; c := client.NewClient(rpc.DevnetRPCEndpoint)

I want to connect to the blockchain so I can do real transactions, how do I do this?

Thanks

yihau commented 2 years ago

Technically, Devnet is a real blockchain. It is not a local cluster. If you would like to send some "real transaction", I think you can just change the endpoint to Mainnet.

scottywm commented 2 years ago
Hey, I'm having difficulty getting the transaction to work and this is the error that I get;
    rpc response error: {"code":-32003,"message":"Transaction signature verification failure"}

    Please tell me what I'm doing wrong, I would appreciate it very much.

   // first I get the private and public keys from my API 
    public_key := user.MainWallet
private_key := data.PrivateKey

    // when I print the private and public keys they are correct
fmt.Println(public_key)
fmt.Println(private_key)

var userMakingTransaction, errAcc = types.AccountFromBase58(private_key)
if errAcc != nil {
    fmt.Println(errAcc, "      line 52")
}

var mintPubkey = common.PublicKeyFromString("Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB")
var from = common.PublicKeyFromString(public_key)
var privateKey = common.PublicKeyFromString(private_key)
var to = common.PublicKeyFromString("Gu1Lo6Ncb31hoRxPXjb98C7fLc3ubcYHUZ2yFBZGYiJ3")

c := client.NewClient(rpc.MainnetRPCEndpoint)

res, errNew := c.GetLatestBlockhash(context.Background())
if errNew != nil {
    log.Fatalf("get recent block hash error, err: %v\n", err)
}

fmt.Println(res.Blockhash)

tx, errTran := types.NewTransaction(types.NewTransactionParam{
    Message: types.NewMessage(types.NewMessageParam{
        FeePayer:        userMakingTransaction.PublicKey,
        RecentBlockhash: res.Blockhash,
        Instructions: []types.Instruction{
            tokenprog.TransferChecked(tokenprog.TransferCheckedParam{
                From:     from,
                To:       to,
                Mint:     mintPubkey,
                Auth:     userMakingTransaction.PublicKey,
                Signers:  []common.PublicKey{privateKey},
                Amount:   1,
                Decimals: 6,
            }),
        },
    }),
    Signers: []types.Account{userMakingTransaction, userMakingTransaction},
})

if errTran != nil {
    log.Fatalf("failed to new tx, err: %v", errTran)
}

txhash, errSend := c.SendTransaction(context.Background(), tx)

if errSend != nil {
    fmt.Println("       ", errSend)
    return
}

log.Println("txhash:", txhash)
yihau commented 2 years ago
  1. tokenprog.TransferChecked Signer field usually uses in multisig wallet. If you're not a multisig wallet, you can pass a empty.
  2. Signers: []types.Account{userMakingTransaction, userMakingTransaction} why you pass two same accounts?
  3. seems you're transferring USDT but your receiver, Gu1Lo6Ncb31hoRxPXjb98C7fLc3ubcYHUZ2yFBZGYiJ3 is not a token account. if you don't familiar with solana account concept, please go through the tour here https://portto.github.io/solana-go-sdk/
scottywm commented 2 years ago

Hey thanks for your replies, however I have some more questions about your last answers.

1) thanks I'll give it a try

2) the reason why I pass two same accounts is because the fee is to be deducted from the account doing the transfer. Doesn't this require two accounts, first is the payer account that is to pay for the transaction fee and the second the account is the one sending the tokens?

3) I have added USDT to that account and I have sent USDT to it and it currently has a USDT balance so I don't understand what you mean when you say that the account is not a token account. This account Gu1Lo6Ncb31hoRxPXjb98C7fLc3ubcYHUZ2yFBZGYiJ3 is the actual Solana address, its not the actual USDT address.

yihau commented 2 years ago

the same signers only need to be passed once.

scottywm commented 2 years ago

OK I still cant get it to work lol.

This is what my code looks like up to this point having made the changes you recommended and it still doesn't work. The accounts don't require more than one person to sign a transaction and you mentioned earlier that the account "Gu1Lo6Ncb31hoRxPXjb98C7fLc3ubcYHUZ2yFBZGYiJ3", is not a token account.

I am currently holding some USDT in this address and have sent USDT tokens to it before without any problems.

What am i doing wrong?

public_key := user.MainWallet private_key := data.PrivateKey

fmt.Println(public_key)
fmt.Println(private_key)

var userMakingTransaction, errAcc = types.AccountFromBase58(private_key)
if errAcc != nil {
    fmt.Println(errAcc, "      line 52")
}

var mintPubkey = common.PublicKeyFromString("Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB")
var from = common.PublicKeyFromString(public_key)
//var privateKey = common.PublicKeyFromString(private_key)
//var to = common.PublicKeyFromString("8s5W5w6JUxTLLVpcEenNbHXAm2REUDgP6vz58F12EAPQ")
var to = common.PublicKeyFromString("Gu1Lo6Ncb31hoRxPXjb98C7fLc3ubcYHUZ2yFBZGYiJ3")

c := client.NewClient(rpc.MainnetRPCEndpoint)

res, errNew := c.GetLatestBlockhash(context.Background())
if errNew != nil {
    log.Fatalf("get recent block hash error, err: %v\n", err)
}

fmt.Println(res.Blockhash)

tx, errTran := types.NewTransaction(types.NewTransactionParam{
    Message: types.NewMessage(types.NewMessageParam{
        FeePayer:        userMakingTransaction.PublicKey,
        RecentBlockhash: res.Blockhash,
        Instructions: []types.Instruction{
            tokenprog.TransferChecked(tokenprog.TransferCheckedParam{
                From:     from,
                To:       to,
                Mint:     mintPubkey,
                Auth:     userMakingTransaction.PublicKey,
                Signers:  []common.PublicKey{},
                Amount:   1,
                Decimals: 6,
            }),
        },
    }),
    Signers: []types.Account{userMakingTransaction},
})

if errTran != nil {
    log.Fatalf("failed to new tx, err: %v", errTran)
}

txhash, errSend := c.SendTransaction(context.Background(), tx)

if errSend != nil {

    fmt.Println("       ", errSend)
    return
    //log.Fatalf("send raw tx error, err: %v\n", errSend)
}

log.Println("txhash:", txhash)
yihau commented 2 years ago

As a valid token transfer instruction, both of your From and To should be token accounts.

you can take a look here https://explorer.solana.com/address/Gu1Lo6Ncb31hoRxPXjb98C7fLc3ubcYHUZ2yFBZGYiJ3/tokens?display=detail

you will find an another account, 8s5W5w6JUxTLLVpcEenNbHXAm2REUDgP6vz58F12EAPQ. it is Gu1Lo6Ncb31hoRxPXjb98C7fLc3ubcYHUZ2yFBZGYiJ3's USDT token account so in your code, your To should be the address 8s5W....

I can't see what's your From in your code but the idea is the same. You should use a USDT token account.

scottywm commented 2 years ago

It worked !!!

Thanks heaps :)

yihau commented 2 years ago

My pleasure