使用锚点时如何解决“TypeError:无法读取未定义的属性(读取“大小”)”?

问题描述 投票:0回答:1

我正在尝试在 Solana 上编写一个基本的智能合约,任何人都可以启动众筹活动。我目前正在与前端合作。我已经成功检查了 Phantom 钱包,连接了钱包,现在正致力于创建具有上述 TypeError 的众筹活动。这是我单击 :

时的完整错误
App.js:84 Error creating campaign account: TypeError: Cannot read properties of undefined (reading 'size')
    at new AccountClient (account.ts:121:1)
    at account.ts:28:1
    at Array.reduce (<anonymous>)
    at AccountFactory.build (account.ts:27:1)
    at NamespaceFactory.build (index.ts:55:1)
    at new Program (index.ts:300:1)
    at createCampaign (App.js:64:1)
    at HTMLUnknownElement.callCallback (react-dom.development.js:4164:1)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:4213:1)
    at invokeGuardedCallback (react-dom.development.js:4277:1)

我以 Anchor 为基础,并以此为基础继续前进。 lib.rs 代码如下:

use anchor_lang::prelude::*;
use anchor_lang::solana_program::entrypoint::ProgramResult;

declare_id!("***Contract address was posted here***");

#[program]
pub mod crowdfunding {
    use super::*;

    pub fn create(ctx: Context<Create>, name:String, description: String) -> ProgramResult {
        let campaign = &mut ctx.accounts.campaign;
        campaign.name = name;
        campaign.description = description;
        campaign.amount_donated = 0;
        campaign.admin = *ctx.accounts.user.key;
        Ok(())
    }

    pub fn withdraw(ctx: Context<Withdraw>, amount: u64) -> ProgramResult {
        let campaign = &mut ctx.accounts.campaign;
        let user = &mut ctx.accounts.user;
        if campaign.admin != *user.key {
            return Err(ProgramError::IncorrectProgramId);
        }
        let rent_balance = Rent::get()?.minimum_balance(campaign.to_account_info().data_len());
        if **campaign.to_account_info().lamports.borrow() - rent_balance < amount {
            return Err(ProgramError::InsufficientFunds);
        }
        **campaign.to_account_info().try_borrow_mut_lamports()? -= amount;
        **user.to_account_info().try_borrow_mut_lamports()?  += amount;
        Ok(())
    }

    pub fn donate(ctx: Context<Donate>, amount: u64) -> ProgramResult {
        let ix = anchor_lang::solana_program::system_instruction::transfer(
            &ctx.accounts.user.key(),
            &ctx.accounts.campaign.key(),
            amount
        );
        anchor_lang::solana_program::program::invoke(
            &ix,
            &[
                ctx.accounts.user.to_account_info(),
                ctx.accounts.campaign.to_account_info()
            ]
        );
        (&mut ctx.accounts.campaign).amount_donated += amount;
        Ok(())
    }
}

#[derive(Accounts)]
pub struct Create<'info> {
    #[account(init, payer=user, space=9000, seeds=[b"CAMPAIGN_DEMO".as_ref(), user.key().as_ref()], bump)]
    pub campaign: Account<'info, Campaign>,
    #[account(mut)]
    pub user: Signer<'info>,
    pub system_program: Program<'info, System>
}

#[derive(Accounts)]
pub struct Withdraw<'info> {
    #[account(mut)]
    pub campaign: Account<'info, Campaign>,
    #[account(mut)]
    pub user: Signer<'info>
}

#[derive(Accounts)]
pub struct Donate<'info> {
    #[account(mut)]
    pub campaign: Account<'info, Campaign>,
    #[account(mut)]
    pub user: Signer<'info>,
    pub system_program: Program<'info, System>
}

#[account]
pub struct Campaign {
    pub admin: Pubkey,
    pub name: String,
    pub description: String,
    pub amount_donated: u64
}

这是前端的App.js文件:

import './App.css';
import idl from "./idl.json";
import { Connection, PublicKey, clusterApiUrl} from "@solana/web3.js";
import { Program, AnchorProvider, web3, utils, BN} from '@coral-xyz/anchor';
import { useEffect, useState } from "react";
import { Buffer} from "buffer"
window.Buffer = Buffer

const programID = new PublicKey(idl.address);
const network = clusterApiUrl("devnet");
const opts = {
  preflightCommitment: "processed", 
};
const {SystemProgram} = web3;

const App = () => {
  const[walletAddress, setWalletAddress] = useState(null);
  const getProvider = () => {
    const connection = new Connection(network, opts.preflightCommitment);
    const provider = new AnchorProvider(
      connection, 
      window.solana, 
      opts.preflightCommitment
    );
    return provider
  }
  const checkIfWalletIsConnected = async() => {
    try {
      const {solana} = window;
      if (solana) {
        if (solana.isPhantom) {
          console.log("Phantom wallet found!");
          const response = await solana.connect({
            onlyIfTrusted: true,
          });
          console.log(
            "Connected with public key:", 
            response.publicKey.toString()
          );
          setWalletAddress(response.publicKey.toString());
        }
      } else {
        alert("Solana object not found! Get a Phantom wallet.");
      }
    } catch(error) {
      console.error(error);
    }
  };
  const connectWallet = async () => {
    const {solana} = window;
    if (solana) {
      const response = await solana.connect();
      console.log(
        'Connected with public key:',
        response.publicKey.toString()
      );
      setWalletAddress(response.publicKey.toString());
    }
  };

  const createCampaign = async() => {
    try {
      const provider = getProvider()
      const program = new Program(idl, programID, provider)
      const [campaign] = PublicKey.findProgramAddressSync(
        [
        utils.bytes.utf8.encode("CAMPAIGN_DEMO"),
        provider.wallet.publicKey.toBuffer(),
        ],
        program.programId
      );
      program.methods.create('campaign name', 'campaign description',{
        accounts: {
          campaign,
          user: provider.wallet.publicKey,
          systemProgram: SystemProgram.programId,
        },
      });
      console.log(
        'Created a new campaign w/ address:', 
        campaign.toString()
      );
    } catch(error) {
      console.error("Error creating campaign account:", error)
    }
  }

  const renderNotConnectedContainer = () => (
    <button onClick={connectWallet}>Connect to Wallet</button>
  );
  const renderConnectedContainer = () => (
    <button onClick={createCampaign}>Create a campaign...</button>
  );
  useEffect(() => {
    const onLoad = async() => {
      await checkIfWalletIsConnected();
    };
    window.addEventListener('load', onLoad);
    return () => window.removeEventListener('load', onLoad);
  }, []);

  return (
  <div className="App">
    {!walletAddress && renderNotConnectedContainer()}
    {walletAddress && renderConnectedContainer()}
  </div>
  );
};

export default App;

我尝试从锚点浏览 account.ts 文件,但仍然找不到定义大小的方法。在我心里,它已经被定义了。我错过了什么?

typescript smartcontracts solana solana-web3js anchor-solana
1个回答
0
投票

我也面临着同样的问题。您找到解决方案了吗?

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.