todo.js:186 Error adding todo: AnchorError: AnchorError caused by account: todo_account.
Error Code: ConstraintSeeds. Error Number: 2006. Error Message: A seeds constraint was violated.
Program log: Left:
Program log: DXYxVwuSVkUVzBCBnfLLygAE8gueEUMXUFXyez3J94Kx
Program log: Right:
Program log: 7TYqbwfHNTvVpbT9q4QX7iKBEqpL3ojm9144Adpbgfbo
at AnchorError.parse (index.js:1277:20)
at translateError (index.js:1361:37)
at Object.rpc [as addTodo] (index.js:5002:23)
at async addTodo (todo.js:169:24)
at async handleSubmit (index.js:37:13)
addTodo function
const addTodo = async (event, publicKey) => {
event.preventDefault(); // Prevent default form submission behavior
// Check if input is empty
if (!input.trim()) {
console.error("Input cannot be empty");
return; // Prevent adding empty todos
}
// Ensure that the wallet is initialized
if (!initialized || !publicKey) {
console.error("Wallet is not initialized or public key is not available");
return;
}
try {
// Generate PDA for the todo account using the correct seeds
const [todoAccount] = await PublicKey.findProgramAddress(
[Buffer.from("TODO_STATE"), publicKey.toBuffer(), Buffer.from([todos.length])],
program.programId
);
// Check if user profile exists
const [profilePda] = PublicKey.findProgramAddressSync(
[Buffer.from('USER_STATE'), publicKey.toBuffer()],
program.programId
);
const userProfileAccount = await program.account.userProfile.fetchNullable(profilePda);
if (!userProfileAccount) {
toast.error('User profile not found. Please initialize your user first.');
return;
}
// Call the program to add a todo
const tx = await program.rpc.addTodo(
input,
{
accounts: {
todoAccount: todoAccount,
userProfile: profilePda,
authority: publicKey,
systemProgram: SystemProgram.programId,
},
}
);
console.log("Todo added successfully:", tx);
// Reset the input field after a successful submission
setInput('');
} catch (error) {
console.error("Error adding todo:", error);
toast.error(`Error adding todo: ${error.message}`);
}
};
pages/index.js
import { WalletMultiButton } from '@solana/wallet-adapter-react-ui';
import { useTodo } from '../hooks/todo';
import Loading from '../components/Loading';
import TodoSection from '../components/todo/TodoSection';
import styles from '../styles/Home.module.css';
import { useEffect, useState } from 'react';
import { useWallet } from '@solana/wallet-adapter-react';
const Home = () => {
const { connected, publicKey } = useWallet();
const {
initialized,
initializeUser,
loading,
transactionPending,
todos,
input,
setInput,
addTodo,
markTodo,
} = useTodo();
const [clientInitialized, setClientInitialized] = useState(false);
useEffect(() => {
setClientInitialized(true);
}, []);
if (!clientInitialized) {
return null;
}
const handleSubmit = async (event) => {
event.preventDefault();
// Ensure publicKey is available before calling addTodo
if (publicKey) {
await addTodo(event, publicKey); // Pass publicKey directly to addTodo
} else {
console.error("Wallet not connected. Unable to add todo.");
}
};
return (
<div className={styles.container}>
<div className={styles.actionsContainer}>
{initialized ? (
<div className={styles.todoInput}>
<form onSubmit={handleSubmit}>
<input
value={input}
onChange={(e) => setInput(e.target.value)}
id={styles.inputField}
type="text"
placeholder='Create a new todo...'
/>
<button type="submit" disabled={transactionPending}>
Add
</button>
</form>
</div>
) : (
<button type="button" className={styles.button} onClick={initializeUser} disabled={transactionPending}>
Initialize
</button>
)}
<WalletMultiButton />
</div>
<div className={styles.mainContainer}>
<Loading loading={loading}>
<TodoSection
title="Tasks"
todos={todos ? todos.filter(todo => !todo.account.marked) : []}
action={markTodo}
/>
<TodoSection
title="Completed"
todos={todos ? todos.filter(todo => todo.account.marked) : []}
action={markTodo}
/>
</Loading>
</div>
</div>
);
};
export default Home;