blocto / solana-go-sdk

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

Private key dependency #65

Closed rahulanand20 closed 2 years ago

rahulanand20 commented 2 years ago

https://github.com/portto/solana-go-sdk/blob/3379219af14a083038c96118c7d1d7daa7e21232/docs/_examples/nft/mint-a-nft-with-master-edition-v2/main.go#L21

Sir, I'm actually thinking of moving to production with mainnet config. But if I do so when the buyer(aka feePayer) has to mint then he has to provide is private key as per the code.. But no buyer will wish to provide/expose the private key .

My question is how can I mint an NFT without taking/using the private key of feePayer.

But usage of public key is fine

rahulanand20 commented 2 years ago

How to sign a transaction without a private key of the buyer?

yihau commented 2 years ago

a tx = signatures + a message

the main idea is that you compose the message and send to user for signing. when you compose the message, you don't need user's private key. you only need the pubkey.

rahulanand20 commented 2 years ago

Thanks @yihau for the reply .

https://github.com/portto/solana-go-sdk/blob/3379219af14a083038c96118c7d1d7daa7e21232/docs/_examples/nft/mint-a-nft-with-master-edition-v2/main.go#L62

sir in this above line Signer is of type.Account and we will not be able to use feepayer.publickey in the as it belongs to the common

if i try to remove Signer I'm getting this error "2022/07/13 13:40:52 failed to send tx, err: rpc response error: {"code":-32003,"message":"Transaction signature verification failure"}"

Also if i try to use different Singer failed to new a tx, err: add not necessary signatures, 7s6Ro1mBBmmKmP2QDT2zzuCMqS6AVCgBQi1mRnsjX4QG is not a signer as it is not a correct singer

rahulanand20 commented 2 years ago

This is my code can you help me modifying this to make it work with only public key

package main

import ( "context" "fmt" "log"

"github.com/mr-tron/base58"
"github.com/portto/solana-go-sdk/client"
"github.com/portto/solana-go-sdk/common"
"github.com/portto/solana-go-sdk/pkg/pointer"
"github.com/portto/solana-go-sdk/program/assotokenprog"
"github.com/portto/solana-go-sdk/program/metaplex/tokenmeta"
"github.com/portto/solana-go-sdk/program/sysprog"
"github.com/portto/solana-go-sdk/program/tokenprog"
"github.com/portto/solana-go-sdk/rpc"
"github.com/portto/solana-go-sdk/types"

)

func main() { //

func main() {

//var feePayer, _ = types.AccountFromBase58("")
   var feePayer1 = common.PublicKeyFromString("43xqaQkf8N95Af64ZqafbcQsPWdKqy5BRWxH7FFYomqX")

c := client.NewClient(rpc.DevnetRPCEndpoint)

mint := types.NewAccount()
fmt.Printf("NFT: %v\n", mint.PublicKey.ToBase58())
assTokAdrr, _, _ := common.FindAssociatedTokenAddress(**feePayer1**, mint.PublicKey)
fmt.Println("assTokAdrr", assTokAdrr.ToBase58())
collection := types.NewAccount()
fmt.Println(base58.Encode(collection.PrivateKey))
fmt.Printf("collection: %v\n", collection.PublicKey.ToBase58())

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

fmt.Println("ata", ata)

tokenMetadataPubkey, err := tokenmeta.GetTokenMetaPubkey(mint.PublicKey)
fmt.Println("tokenMetadataPubkey", tokenMetadataPubkey.ToBase58())

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

}
tokenMasterEditionPubkey, err := tokenmeta.GetMasterEdition(mint.PublicKey)
fmt.Println("tokenMasterEditionPubkey", tokenMasterEditionPubkey.ToBase58())

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

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

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

fmt.Println("Signers--------------------->", []types.Account{mint})

tx, err := types.NewTransaction(types.NewTransactionParam{
    //Signers: []types.Account{mint, feePayer1},
    Message: types.NewMessage(types.NewMessageParam{
        FeePayer:        feePayer1,
        RecentBlockhash: recentBlockhashResponse.Blockhash,
        Instructions: []types.Instruction{
            sysprog.CreateAccount(sysprog.CreateAccountParam{
                From:     feePayer1,
                New:      mint.PublicKey,
                Owner:    common.TokenProgramID,
                Lamports: mintAccountRent,
                Space:    tokenprog.MintAccountSize,
            }),
            tokenprog.InitializeMint(tokenprog.InitializeMintParam{
                Decimals: 0,
                Mint:     mint.PublicKey,
                MintAuth: feePayer1,
            }),
            tokenmeta.CreateMetadataAccountV2(tokenmeta.CreateMetadataAccountV2Param{
                Metadata:                tokenMetadataPubkey,
                Mint:                    mint.PublicKey,
                MintAuthority:           feePayer1,
                Payer:                   feePayer1,
                UpdateAuthority:         feePayer1,
                UpdateAuthorityIsSigner: true,
                IsMutable:               true,
                Data: tokenmeta.DataV2{
                    Name:                 "test",
                    Symbol:               "tset",
                    Uri:                  "https://ipfs.infura.io/ipfs/QmVyceJtRJVY8E8kCmXUPK3vs2XdwzTtrtWrGpwjWVWhMX",
                    SellerFeeBasisPoints: 100,
                    Creators: &[]tokenmeta.Creator{
                        {
                            Address:  feePayer1,
                            Verified: true,
                            Share:    100,
                        },
                    },
                    Collection: &tokenmeta.Collection{
                        Verified: false,
                        Key:      collection.PublicKey,
                    },
                    Uses: &tokenmeta.Uses{
                        UseMethod: tokenmeta.Burn,
                        Remaining: 10,
                        Total:     10,
                    },
                },
            }),
            assotokenprog.CreateAssociatedTokenAccount(assotokenprog.CreateAssociatedTokenAccountParam{
                Funder:                 feePayer1,
                Owner:                  feePayer1,
                Mint:                   mint.PublicKey,
                AssociatedTokenAccount: ata,
            }),
            tokenprog.MintTo(tokenprog.MintToParam{
                Mint:   mint.PublicKey,
                To:     ata,
                Auth:   feePayer1,
                Amount: 1,
            }),
            tokenmeta.CreateMasterEditionV3(tokenmeta.CreateMasterEditionParam{
                Edition:         tokenMasterEditionPubkey,
                Mint:            mint.PublicKey,
                UpdateAuthority: feePayer1,
                MintAuthority:   feePayer1,
                Metadata:        tokenMetadataPubkey,
                Payer:           feePayer1,
                MaxSupply:       pointer.Uint64(0),
            }),
        },
    }),
})

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

sig, err := c.SendTransaction(context.Background(), tx)
if err != nil {
    log.Fatalf("failed to send tx, err: %v", err)
}

fmt.Println(sig)

}

rahulanand20 commented 2 years ago

Can you please help with the above query

rahulanand20 commented 2 years ago

any suggestion on the above issue?

yihau commented 2 years ago

I think the steps are more like

  1. you build a message
  2. send it to a user
  3. the user signs it
  4. for step 4 I think you can either a. let the user combines the signature and the message to a tx then send it b. ask the user to return the signature. you combine them and send it.
rahulanand20 commented 2 years ago

so it seems private key is mandatory to sign a transaction?

yihau commented 2 years ago

depends on which account you're using. if you are using a PDA, the account's signature doesn't be generated by a private key.

feel free to open another issue to ask something about this sdk.