Here, web.Keypair.generate
only returns a public and keypair corresponding to a system account(which you can think of as sort of the blank slate on which other kinds of accounts are built). You'd have to give instructions to convert this account to a stake account.
The error gives a hint of the issue here, albeit in an unclear way. The delegate instruction expects the account given to it to be a stake account owned by the stake program but instead gets a blank account owned by the system program.
Here's example code to show initialization of a stake account, and delegation:
export const initializeStakeAccount = async (
stakeAccount: Keypair,
lamports: BN
) => {
// Required fields for initialization, we set the authorities for the
// stake account
const authorized = {
staker: client.provider.publicKey,
withdrawer: client.provider.publicKey,
};
const createParams = {
fromPubkey: client.provider.publicKey,
stakePubkey: stakeAccount.publicKey,
authorized,
lamports: lamports.toNumber(),
};
// Actually creating a stake account from our system account
const createIx = StakeProgram.createAccount(createParams);
await client.provider.sendAndConfirm(new Transaction().add(createIx), [
stakeAccount,
]);
// Getting the address of the validator we're delegating to. It's
// derived in this way because this sample is from a localnet test.
const voteKeypair = getKeypair(
".anchor/test-ledger/vote-account-keypair.json"
);
const votePubkey = voteKeypair.publicKey;
const delegateParams = {
stakePubkey: stakeAccount.publicKey,
authorizedPubkey: client.provider.publicKey,
votePubkey,
};
const delegateIx = StakeProgram.delegate(delegateParams);
await client.provider.sendAndConfirm(new Transaction().add(delegateIx), []);
};