2

This is my contract

    account_info::{next_account_info, AccountInfo},
    entrypoint,
    entrypoint::ProgramResult,
    msg,
    program_error::ProgramError,
    pubkey::Pubkey,
};
use std::convert::TryInto;

const PUBKEY_BYTES: usize = 32;

entrypoint!(process_instruction);

fn process_instruction(
    program_id: &Pubkey,
    accounts: &[AccountInfo],
    instruction_data: &[u8],
) -> ProgramResult {
    if instruction_data.is_empty() {
        return Err(ProgramError::InvalidArgument);
    }

    let instruction = instruction_data[0];

    match instruction {
        0 => hello_world(),
        1 => stack_nft(accounts),
        2 => distribute(accounts, &instruction_data[1..]),
        _ => Err(ProgramError::InvalidInstructionData),
    }
}

fn hello_world() -> ProgramResult {
    msg!("Hello, World! v1.0");

    Ok(())
}

fn distribute(accounts: &[AccountInfo], data: &[u8]) -> ProgramResult {
    msg!("Distribute NFT");

    if data.len() != 32 {
        return Err(ProgramError::InvalidInstructionData);
    }

    let recipient_key = Pubkey::new(data);
    let accounts_iter = &mut accounts.iter();
    let nft_account = next_account_info(accounts_iter)?;
    let authority_account = next_account_info(accounts_iter)?;

    if !authority_account.is_signer {
        return Err(ProgramError::MissingRequiredSignature);
    }

    let mut nft_data = nft_account.try_borrow_mut_data()?;
    let nft_owner_key = Pubkey::new(&nft_data[0..32]);

    if nft_owner_key != *authority_account.key {
        return Err(ProgramError::InvalidArgument);
    }

    nft_data[0..32].copy_from_slice(recipient_key.as_ref());

    Ok(())
}

fn stack_nft(accounts: &[AccountInfo]) -> ProgramResult {
    msg!("Stack NFTs");

    let accounts_iter = &mut accounts.iter();

    let nft_account = next_account_info(accounts_iter)?;
    let stack_account = next_account_info(accounts_iter)?;
    let authority_account = next_account_info(accounts_iter)?;

    // Check if the authority account is a signer
    if !authority_account.is_signer {
        return Err(ProgramError::MissingRequiredSignature);
    }

    let mut stack_data = stack_account.try_borrow_mut_data()?;
    let mut stack_count = stack_data[0];
    let mut found = false;

    // Check if NFT is already in stack
    for i in (1..=stack_count).map(|n| n as usize * PUBKEY_BYTES) {
        let key = Pubkey::new(&stack_data[i..i + PUBKEY_BYTES]);

        if key == *nft_account.key {
            found = true;
            break;
        }
    }

    if found {
        return Err(ProgramError::AccountAlreadyInitialized);
    }

    // Check if stack has enough space
    if (stack_count as usize + 1) * PUBKEY_BYTES > stack_data.len() - 1 {
        return Err(ProgramError::AccountDataTooSmall);
    }

    // Add NFT to stack
    let next_position = 1 + stack_count as usize * PUBKEY_BYTES;
    stack_data[next_position..next_position + PUBKEY_BYTES]
        .copy_from_slice(&nft_account.key.to_bytes());
    stack_data[0] = stack_count + 1;

    Ok(())
}

And I am calling it like this (Full code of my class check stack NFT method, Hello world is working fine, and I am able to call it)

import { useConnection, useWallet } from "@solana/wallet-adapter-react";
import {
  PublicKey,
  Keypair,
  SystemProgram,
  Transaction,
  TransactionMessage,
  TransactionSignature,
  VersionedTransaction,
  TransactionInstruction,
} from "@solana/web3.js";
import { FC, useCallback } from "react";
import { transferableAbortController } from "util";
import { notify } from "../utils/notifications";

export const SendTransaction: FC = () => {
  const { connection } = useConnection();
  const { publicKey, sendTransaction } = useWallet();
  const programId = new PublicKey(
    "62e7wjjWpE9Pucj6kWuLhRY6pWtxaR2oFSCfTpH9ecYz"
  );
  const stackAccount = new PublicKey(
    "DPx1PvQLJAYJHGCRDLeUt7s5cFJT993LeEaGyUqPJGkp"
  ); // account address from which contract is deployed
  const nftAccount = new PublicKey(
    "DPx1PvQLJAYJHGCRDLeUt7s5cFJT993LeEaGyUqPJGkp"
  ); // account address from which contract is deployed
  const authorityAccount = publicKey;



  
  const callHello = useCallback(async () => {
    if (!publicKey) {
      notify({ type: "error", message: "Wallet not connected!" });
      console.log("error", "Send Transaction: Wallet not connected!");
      return;
    }

    let signature = "";
    try {
      // Create instruction to call the hello_world method
      const instruction = new TransactionInstruction({
        keys: [
        ],
        programId: programId, // Replace with the program ID of your Solana program
        data: Buffer.from([0]), // 2 is the instruction index for hello_world method
      });

      // Create a new Transaction and add the instruction
      const transaction = new Transaction().add(instruction);

      transaction.serialize()
      // Send the transaction and await the signature
      signature = await sendTransaction(transaction, connection);

      // Confirm the transaction
      await connection.confirmTransaction(signature, "confirmed");

      console.log(signature);
      notify({
        type: "success",
        message: "Transaction successful!",
        txid: signature,
      });
    } catch (error) {
      notify({
        type: "error",
        message: "Transaction failed!",
        description: error?.message,
        txid: signature,
      });
      console.log("error", `Transaction failed! ${error?.message}`, signature);
    }
  }, [publicKey, notify, connection, sendTransaction]);

  const stackNft = useCallback(async () => {
    if (!publicKey) {
      notify({ type: "error", message: "Wallet not connected!" });
      console.log("error", "Send Transaction: Wallet not connected!");
      return;
    }

    let signature = "";
    try {
      const instruction = new TransactionInstruction({
        programId: programId, // Replace with the program ID of your Solana program
        keys: [
          { pubkey: nftAccount, isSigner: false, isWritable: true },
          { pubkey: stackAccount, isSigner: false, isWritable: true },
          { pubkey: authorityAccount, isSigner: true, isWritable: true }, // public key means account addres of the wallet from where we are sending transection
        ],
        data: Buffer.from([1]), // 0 is the instruction index for `stack_nft` function
      });

      // Create a new Transaction and add the instruction
      const transaction = new Transaction().add(instruction);
 
      const serializedTransaction = transaction.serialize();
      // Send the transaction and await the signature
      signature = await sendTransaction(transaction, connection);

      // Confirm the transaction
      await connection.confirmTransaction(signature, "confirmed");

      console.log(signature);
      notify({
        type: "success",
        message: "Transaction successful!",
        txid: signature,
      });
    } catch (error) {
      notify({
        type: "error",
        message: "Transaction failed!",
        description: error?.message,
        txid: signature,
      });
      console.log("error", `Transaction failed! ${error?.message}`, signature);
    }
  }, [publicKey, notify, connection, sendTransaction]);

  return (
    <div className="flex flex-row justify-center">
      <div className="relative group items-center">
        <div
          className="m-1 absolute -inset-0.5 bg-gradient-to-r from-indigo-500 to-fuchsia-500 
                rounded-lg blur opacity-20 group-hover:opacity-100 transition duration-1000 group-hover:duration-200 animate-tilt"
        ></div>

        <button
          className="group w-60 m-2 btn animate-pulse bg-gradient-to-br from-indigo-500 to-fuchsia-500 hover:from-white hover:to-purple-300 text-black"
          onClick={callHello}
          disabled={!publicKey}
        >
          <div className="hidden group-disabled:block ">
            Wallet not connected
          </div>
          <span className="block group-disabled:hidden">Call HEllo</span>
        </button>

        <button
          className="group w-60 m-2 btn animate-pulse bg-gradient-to-br from-indigo-500 to-fuchsia-500 hover:from-white hover:to-purple-300 text-black"
          onClick={stackNft}
          disabled={!publicKey}
        >
          <div className="hidden group-disabled:block ">
            Wallet not connected
          </div>
          <span className="block group-disabled:hidden">Stack NFT</span>
        </button>
      </div>
    </div>
  );
};

and I am getting error saying Error processing Instruction 0: Program failed to complete

8
  • can you please provide more error logs? May 21, 2023 at 17:45
  • Phantom - RPC Error: Requested resource not available. {code: -32002, message: 'Requested resource not available.'}code: -32002message: "Requested resource not available."[[Prototype]]: Object next-dev.js:20 WalletSendTransactionError: Requested resource not available. at StandardWalletAdapter.sendTransaction (adapter.js:237:1) at async eval (WalletProviderBase.js:153:1) w
    – Siddharth
    May 22, 2023 at 6:13
  • Please make sure if you've deployed the latest smart contract and you're using the correct SC address in your dapp May 22, 2023 at 8:27
  • Yes, I am using the latest onc, you can see the contract code above, Also I am deploying the contract using Solana Playground. I am able to call the hello world method of the contract, but no other methods.
    – Siddharth
    May 22, 2023 at 8:31
  • Is your program on devnet right now? If so, what is the program address? May 30, 2023 at 18:48

2 Answers 2

2

try run your transaction with skipPreflight true like this:

      signature = await sendTransaction(transaction, connection, {skipPreflight: true});

Like this you will get an onchain error which is:

> Program logged: "Stack NFTs"

Program logged: "panicked at 'index out of bounds: the len is 0 but the index is 0', 3213d7ce-c863-4115-b4b1-9c292d15c6cd/src/lib.rs:83:27"

So in line 83 you are trying to access an index 0 for an empty array:

let mut stack_data = stack_account.try_borrow_mut_data()?;
let mut stack_count = stack_data[0];
4
  • This did not work. I tried doing the same.
    – Siddharth
    Jun 8, 2023 at 8:39
  • Also can you just point as any active sample for doing same may be that will help us Identifying the issue.
    – Siddharth
    Jun 8, 2023 at 8:40
  • Which part did not work? Its just the flag skipPreflight on the sendTransaction: const transaction = new Transaction().add(instruction); let blockHash = await connection.getRecentBlockhash(); transaction.recentBlockhash = blockHash.blockhash; const txSig = await sendTransaction(transaction, connection, {skipPreflight: true}) results into this hash, where you can see the error: 3zGyNH1idmqEeUotMVU5qM9AC2tHncnW2xinHx9ewXZ2fgd9TbM9yab7dezWU3yEYYj7ageFeqpmyULVkj8kbnFa Not sure what your stackNft function is supposed to do but you are accessing an index in an empty array
    – Jonas H.
    Jun 9, 2023 at 19:45
  • Probably stack account needs to be smth different. Looks like its your programs authority wallet. Its has 0bytes data so cant really be used as an NFT stack account.
    – Jonas H.
    Jun 9, 2023 at 20:00
0

This means that somewhere in your instruction, a panic is being thrown.

Viewing the logs will show you exactly where the problem is. Alternatively, you can use a try..catch to print the error.

5
  • WalletSendTransactionError: Requested resource not available. at StandardWalletAdapter.sendTransaction (adapter.js:237:1) at async eval (WalletProviderBase.js:153:1)
    – Siddharth
    Jun 3, 2023 at 7:52
  • xt-dev.js:20 Phantom - RPC Error: Requested resource not available. code : -32002 message : "Requested resource not available." [[Prototype]] : Object constructor : ƒ Object() assign : ƒ assign() create : ƒ create() defineProperties : ƒ defineProperties() defineProperty : ƒ defineProperty() entries : ƒ entries() freeze : ƒ freeze() fromEntries : ƒ fromEntries() getOwnPropertyDescriptor : ƒ getOwnPropertyDescriptor() getOwnPropertyDescriptors ƒ getOwnPropertyDescriptors() getOwnPropertyNames ƒ getOwnPropertyNames() getOwnPropertySymbols
    – Siddharth
    Jun 3, 2023 at 7:54
  • onst programId = new PublicKey( "62e7wjjWpE9Pucj6kWuLhRY6pWtxaR2oFSCfTpH9ecYz" ); // Smart contract id const stackAccount = new PublicKey( "DPx1PvQLJAYJHGCRDLeUt7s5cFJT993LeEaGyUqPJGkp" ); // account address from which contract is deployed const nftAccount = new PublicKey( "DpupBcJJv1ZnPuevR5CvaYAAb87QrA29462gGQVkNQLb" ); //NFT Address
    – Siddharth
    Jun 3, 2023 at 7:58
  • This looks weird. The error mentioned in your question's title and the recent ones you send should not co-exist. The error in the title implies that your program runs but panics somewhere while this says the transaction isn't being sent at all. Are you getting both errors? Kindly edit your question to be more specific about which error it is, and place the error logs in it, not the comments
    – Ademola
    Jun 3, 2023 at 18:38
  • This is what i get in logs , the title error is shown by phantom wallet.
    – Siddharth
    Jun 5, 2023 at 4:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.