Closed Mehrdadgame closed 6 months ago
Don't craft the transaction twice just pass the message and signature on to the server. When you sign the transaction it hashes the transaction message and since the client transaction and server transaction have different memos it would yield different signatures so the client signature would not match the new transaction the server made. They just need to share the same message when signing. Feel free to hop in the discord if you have any other questions
//Client App
TransactionBuilder txBuilder = new TransactionBuilder()
.SetRecentBlockHash(blockHash.Result.Value.Blockhash)
.SetFeePayer(fromAccount)
.AddInstruction(SystemProgram.Transfer(fromAccount.PublicKey, toAccount.PublicKey, 10000000))
.AddInstruction(MemoProgram.NewMemo(fromAccount.PublicKey, "Hello from Sol.Net :)"));
byte[] msgBytes = txBuilder.CompileMessage();
byte[] clientSignature = fromAccount.Sign(msgBytes);
//Server Side handling the signature and message
byte[] serverSignature = fromAccountUser2.Sign(msgBytes);
List<byte[]> signatures = new() { clientSignature, serverSignature };
Transaction tx = Transaction.Populate(Message.Deserialize(msgBytes), signatures);
RequestResult<string> _tx = await rpcClient.SendTransactionAsync(tx.Serialize());
`
//Client App Wallet wallet = new(MnemonicWords); Account fromAccount = wallet.GetAccount(10); Account toAccount = wallet.GetAccount(8);
var blockHash = rpcClient.GetLatestBlockHash();
Console.WriteLine($"BlockHash >> {blockHash.Result.Value.Blockhash}");
TransactionBuilder txBuilder = new TransactionBuilder()
.SetRecentBlockHash(blockHash.Result.Value.Blockhash)
.SetFeePayer(fromAccount)
.AddInstruction(SystemProgram.Transfer(fromAccount.PublicKey, toAccount.PublicKey, 10000000))
.AddInstruction(MemoProgram.NewMemo(fromAccount.PublicKey, "Hello from Sol.Net :)"));
byte[] msgBytes = txBuilder.CompileMessage();
byte[] clientSignature = fromAccount.Sign(msgBytes);
//Server Side handling the signature and message
Wallet walletUser2 = new(MnemonicWordsUser2);
Account fromAccountUser2 = walletUser2.GetAccount(10);
byte[] serverSignature = fromAccountUser2.Sign(msgBytes);
List<byte[]> signatures = new() { clientSignature };
Transaction tx = Transaction.Populate(Message.Deserialize(msgBytes), signatures);
tx.AddSignature(fromAccountUser2, serverSignature);
var Verify = tx.VerifySignatures();
RequestResult<string> SecondSig = rpcClient.SendTransaction(tx.Serialize());
Console.WriteLine($"Secend Tx Signature: {SecondSig.Result}");`
Thank you for answer my question @BifrostTitan But i have an error in Send Transaction Error message : "invalid transaction: Transaction failed to sanitize accounts offsets correctly"
Server doesn't need to sign the transaction for this type of transaction. The client doesn't need authorization or sign-off from the recipient to send SOL. In this case there is no reason to talk to the server at all. Everything can be done by the client.
For instance if its a "round trip" transaction or essentially a p2p trade where one person sends SOL and the other sends USDC then both would be required to sign like a contract.
There is a few instances where you would want to get a transaction message from a server though. For example you have a blockchain game that needs a specifically crafted transaction that interacts with a games solana program this can be crafted by the server then sent to the client for signing. Using a basic HTTP rest API you can request gameserver oriented transactions and sign/send them from the client's end.
`// Set up the RPC client for sending and receiving transactions
// Set up the wallet for the sender account
var mnemonicWordsSender = "your mnemonic words for the sender account";
var walletSender = new Wallet(mnemonicWordsSender);
var accountSender = walletSender.GetAccount(0);
// Set up the wallet for the receiver account
var mnemonicWordsReceiver = "your mnemonic words for the receiver account";
var walletReceiver = new Wallet(mnemonicWordsReceiver);
var accountReceiver = walletReceiver.GetAccount(0);
// Create the transfer transaction
var tx = new TransactionBuilder()
.SetRecentBlockHash(rpcClient.GetLatestBlockHash().Result.Value.Blockhash)
.SetFeePayer(accountSender.PublicKey)
.AddInstruction(SystemProgram.Transfer(accountSender.PublicKey, accountReceiver.PublicKey, 100000000));
// Sign the transaction with the sender's account
tx.Build(accountSender);
// Serialize the transaction and send it to the server
var serializedTx = tx.Serialize();
var request = new JsonRpcRequest("sendTransaction", new List<object> { serializedTx });
var response = rpcClient.SendBatchRequestAsync(request);
// Wait for confirmation from the server
var signature = response.Result.ToString();
var confirmedTx = rpcClient.GetTransaction(signature).Result;
while (confirmedTx == null)
{
confirmedTx = rpcClient.GetTransaction(signature).Result;
}
// Sign the transaction with the server's account
var accountServer = walletReceiver.GetAccount(1);
Base58Encoder base58 = new Base58Encoder();
var signatureBytes = base58.DecodeData(signature);
var txMessageBytes = tx.CompileMessage();
var serverSignature = accountServer.Sign(txMessageBytes);
// Add the server's signature to the transaction
tx.AddSignature(serverSignature);
// Serialize the transaction again and send it to the server
serializedTx = tx.Serialize();
var sendToBlockchine = rpcClient.SendTransaction(serializedTx);
Console.WriteLine(sendToBlockchine.Result);`
@BifrostTitan @tiago18c @nazbrok Hello, is it check to use this method? The next point is that I use
Is this the right solution for what I want to do?
var request = new JsonRpcRequest("sendTransaction", new List<object> { serializedTx });
I have an error, how can I solve it?
I learning block chain for Create game
var rpcClient = ClientFactory.GetClient(Cluster.MainNet);
// Set up the wallet for the sender account
var mnemonicWordsSender = "your mnemonic words for the sender account";
var walletSender = new Wallet(mnemonicWordsSender);
var accountSender = walletSender.GetAccount(0);
PublicKey accountReceiver = new PublicKey("receiver wallet address");
// Create the transfer transaction
var tx = new TransactionBuilder()
.SetRecentBlockHash(rpcClient.GetLatestBlockHash().Result.Value.Blockhash)
.SetFeePayer(accountSender.PublicKey)
.AddInstruction(SystemProgram.Transfer(accountSender.PublicKey, accountReceiver, 100000000));
// Sign the transaction with the sender's account
tx.Build(accountSender);
//Send the transaction to the blockchain. There is no need to sign twice and it will fail if you try
var sentTransaction = rpcClient.SendTransaction(tx);
Describe the bug I created a transaction (Tx) in my client and sent the signature to the server. Then, I created a new transaction in the server and added the client's signature to it. However, I encountered an error when trying to send the transaction to the blockchain. I created account in both Tx with tow different phase secret . Is this Correct?
` string MnemonicWords = "okay because peace inside harsh feature boss hood ranch clock text glide"; string MnemonicWordsUser2 = "faculty history noble mosquito sugar best payment memory visual boss thrive check";
////client Code //// Wallet wallet = new Wallet(MnemonicWords);
Desktop (please complete the following information):