Skip to content
Advertisement

How to get a user’s keypair from their public key only (Solana)?

I’m making a dApp and I want to add a button where a user (the one with their wallet connected) can send exactly 0.01 SOL to another user. I already wrote the function in my Rust program and after testing it with anchor test it seems to be working when I use my own personal wallet’s Keypair to sign the transaction. However, now I am writing the event handler function in my web app’s frontend and I’m not sure what to pass for the signers parameter if I want the user to sign the transaction. What do I pass if I don’t know their secret key? Is there a way that I can generate a user’s Keypair from their public key alone or would I need to use the Solana Wallet Adapter for this? Any help would be appreciated. This is my first time working with Solana!

This is the function:

const tipSol = async (receiverAddress) => {
    try {
      const provider = getProvider();
      const program = new Program(idl, programID, provider);

      const lamportsToSend = LAMPORTS_PER_SOL / 100;
      const amount = new anchor.BN(lamportsToSend);
      await program.rpc.sendSol(amount, {
      accounts: {
        from: walletAddress,
        to: receiverAddress,
        systemProgram: SystemProgram.programId,
      },
      signers: ?
     })
     console.log('Successfully sent 0.01 SOL!')
     window.alert(`You successfully tipped ${receiverAddress} 0.01 SOL!`)
    } catch (error) {
      console.error('Failed to send SOL:', error);
      window.alert('Failed to send SOL:', error);
    }
  }

Advertisement

Answer

Frontends never access private keys. Instead the flow is something like:

  • Frontend creates the transaction
  • Frontend sends the transaction to the wallet
  • Wallet signs the transaction
  • Wallet returns the signed transaction to the frontend
  • Frontend send the transaction

You can use the @solana/wallet-adapter to implement this on your frontend https://github.com/solana-labs/wallet-adapter

In practice it would be something like this in your frontend

export const Component = () => {
  const { connection } = useConnection();
  const { sendTransaction } = useWallet();

  const handle = async () => {
    const ix: TransactionInstruction = await tipSol(receiverKey);
    const tx = new Transaction().add(ix);
    const sig = await sendTransaction(tx, connection);
  };

  // ...
};
User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement