Here is my solana todolist program
#![allow(clippy::result_large_err)]use anchor_lang::prelude::*;declare_id!("6u7Wzgps8X8Qjd5AaqaF5mpKdfZzSfNt2MaPjATf2Z6Y");#[program]pub mod todolist { use super::*; pub fn initialize_list(ctx: Context<InitializeList>, list_name: String) -> Result<()>{ let todolist = &mut ctx.accounts.todolist; todolist.owner = *ctx.accounts.owner.key; todolist.list_name = list_name; todolist.task_count = 0; Ok(()) } pub fn add_task(ctx: Context<AddTasks>, task: String) -> Result<()> { let todolist = &mut ctx.accounts.todolist; let task_state = Task{ description: task, is_completed: false, }; todolist.tasks.push(task_state); todolist.task_count += 1; Ok(()) } pub fn remove_task(ctx: Context<RemoveTask>, task_index: u32) -> Result<()> { let todolist = &mut ctx.accounts.todolist; if(task_index as usize) < todolist.tasks.len() { todolist.tasks.remove(task_index as usize); todolist.task_count -=1; } else { return Err(ErrorCode::TaskNotFound.into()); } Ok(()) } pub fn complete_task(ctx: Context<CompleteTask>, task_index: u32) -> Result<()> { let todolist = &mut ctx.accounts.todolist; if(task_index as usize) < todolist.tasks.len() { let task = &mut todolist.tasks[task_index as usize]; task.is_completed = true; } else { return Err(ErrorCode::TaskNotFound.into()); } Ok(()) }}#[account]pub struct Task{ pub description: String, pub is_completed: bool,}#[account]pub struct List { pub owner: Pubkey, pub list_name: String, pub tasks: Vec<Task>, pub task_count: u32,}impl List { pub const MAX_TASKS: usize = 10; // Adjust this based on your requirements pub const MAX_LEN_LIST_NAME: usize = 100; // Max length of list_name pub fn space() -> usize { 8 + 32 + // Discriminator + Pubkey for owner 4 + Self::MAX_LEN_LIST_NAME + // List name (4 bytes for length + max 100 bytes) 4 + (Self::MAX_TASKS * 285) + // Vec<Task>: 4 bytes for length prefix + 50 tasks of 285 bytes each 4 // u32 task_count }}#[derive(Accounts)]#[instruction(list_name: String)]pub struct InitializeList<'info> { #[account(mut)] pub owner: Signer<'info>, #[account( init, payer = owner, space = List::space(), seeds = [list_name.as_bytes(), owner.key().as_ref()], bump )] pub todolist: Account<'info, List>, pub system_program: Program<'info, System>}#[derive(Accounts)]#[instruction(list_name: String)]pub struct AddTasks<'info> { #[account(mut)] pub owner: Signer<'info>, #[account( mut, seeds = [list_name.as_bytes(), owner.key().as_ref()], bump)] pub todolist: Account<'info, List>, pub system_program: Program<'info, System>,}#[derive(Accounts)]#[instruction(list_name: String)]pub struct RemoveTask<'info> { #[account(mut)] pub owner: Signer<'info>, #[account(mut, seeds = [list_name.as_bytes(), owner.key().as_ref()], bump)] pub todolist: Account<'info, List>, pub system_program: Program<'info, System>,}#[derive(Accounts)]#[instruction(list_name: String)]pub struct CompleteTask<'info> { #[account(mut)] pub owner: Signer<'info>, #[account( mut, seeds = [list_name.as_bytes(), owner.key().as_ref()], bump)] pub todolist: Account<'info, List>, pub system_program: Program<'info, System>,}#[error_code]pub enum ErrorCode { #[msg("Task not found in the ToDoList.")] TaskNotFound,}
Here is my test script:
import { ProgramTestContext, startAnchor } from "solana-bankrun";import { BankrunProvider } from "anchor-bankrun";import * as anchor from '@coral-xyz/anchor';import { Program } from '@coral-xyz/anchor';import { PublicKey, SystemProgram } from '@solana/web3.js';import { Todolist } from '../target/types/todolist';const IDL = require("../target/idl/todolist.json");const todolistAddress = new PublicKey("6u7Wzgps8X8Qjd5AaqaF5mpKdfZzSfNt2MaPjATf2Z6Y");describe('todolist', () => { let context: ProgramTestContext; let provider; let todolistProgram: anchor.Program<Todolist>; beforeAll(async () => { context = await startAnchor("", [{ name: "todolist", programId: todolistAddress }], []); provider = new BankrunProvider(context); todolistProgram = new Program<Todolist>( IDL, provider ); }); it("Initialize ToDo List", async () => { // Initialize the ToDo list await todolistProgram.methods.initializeList("MyToDoList").rpc(); let [listAddress] = PublicKey.findProgramAddressSync( [Buffer.from("MyToDoList"), context.payer.publicKey.toBuffer()], todolistAddress ); let list = await todolistProgram.account.list.fetch(listAddress); console.log(list); // Assertions expect(list.listName).toEqual("MyToDoList"); expect(list.taskCount).toEqual(0); }); it("Add Task", async () => { // Derive the PDA for the ToDoList, ensure it's consistent with InitializeList let [listAddress] = PublicKey.findProgramAddressSync( [Buffer.from("MyToDoList"), context.payer.publicKey.toBuffer()], todolistAddress ); // Call the addTask method and ensure correct accounts are passed await todolistProgram.methods.addTask("Go to gym").rpc(); // Fetch the updated list account to verify the task was added let list = await todolistProgram.account.list.fetch(listAddress); console.log(list); expect(list.taskCount).toEqual(1); expect(list.tasks[0].description).toEqual("Go to gym"); });});
When i run the script I am getting this error:
Found a 'test' script in the Anchor.toml. Running it as a test suite!Running test suite: "/Users/aliceho/Desktop/solana/todolist/anchor/Anchor.toml" console.warn bigint: Failed to load bindings, pure JS will be used (try npm run rebuild?)> 1 | import { ProgramTestContext, startAnchor } from "solana-bankrun"; | ^ 2 | import { BankrunProvider } from "anchor-bankrun"; 3 | import * as anchor from '@coral-xyz/anchor'; 4 | import { Program } from '@coral-xyz/anchor'; at Object.<anonymous> (node_modules/bigint-buffer/dist/node.js:10:17) at Object.<anonymous> (node_modules/@solana/web3.js/lib/index.cjs.js:10:20) at Object.<anonymous> (node_modules/solana-bankrun/solana-bankrun/index.ts:27:1) at Object.<anonymous> (anchor/tests/todolist.spec.ts:1:1) RUNS tests/todolist.spec.ts[2024-10-17T10:12:33.473108000Z INFO solana_program_test] "todolist" SBF program from target/deploy/todolist.so, modified 37 minutes, 26 seconds, 442 ms, 863 µs and 242 ns ago[2024-10-17T10:12:33.473491000Z INFO solana_program_test] "todolist" SBF program from target/deploy/todolist.so, modified 37 minutes, 26 seconds, 443 ms, 490 µs and 242 ns ago[2024-10-17T10:12:33.497450000Z INFO solana_program_test] Overriding account at 6u7Wzgps8X8Qjd5AaqaF5mpKdfZzSfNt2MaPjATf2Z6Y[2024-10-17T10:12:33.563484000Z DEBUG solana_runtime::message_processor::stable_log] Program 6u7Wzgps8X8Qjd5AaqaF5mpKdfZzSfNt2MaPjATf2Z6Y invoke [1][2024-10-17T10:12:33.563855000Z DEBUG solana_runtime::message_processor::stable_log] Program log: Instruction: InitializeList[2024-10-17T10:12:33.564192000Z DEBUG solana_runtime::message_processor::stable_log] Program 11111111111111111111111111111111 invoke [2][2024-10-17T10:12:33.564212000Z DEBUG solana_runtime::message_processor::stable_log] Program 11111111111111111111111111111111 success[2024-10-17T10:12:33.564285000Z DEBUG solana_runtime::message_processor::stable_log] Program 6u7Wzgps8X8Qjd5AaqaF5mpKdfZzSfNt2MaPjATf2Z6Y consumed 10258 of 2 console.log { owner: PublicKey [PublicKey(xPQn2LcfqueKxHhbDmYc9RDz974Cyp7BXZwvmWYx1G3)] { _bn: <BN: e30489310018a723936ea71ffefd32d77f96313de15508f2f428c2bed2ce790> }, listName: 'MyToDoList', tasks: [], taskCount: 0 } at anchor/tests/todolist.spec.ts:42:13 FAIL tests/todolist.spec.ts (8.955 s) todolist✓ Initialize ToDo List (31 ms)✕ Add Task (1 ms)● todolist › Add Task Reached maximum depth for account resolution at AccountsResolver.resolve (node_modules/@coral-xyz/anchor/src/program/accounts-resolver.ts:89:15) at MethodsBuilder.rpc (node_modules/@coral-xyz/anchor/src/program/namespace/methods.ts:285:7)Test Suites: 1 failed, 1 totalTests: 1 failed, 1 passed, 2 totalSnapshots: 0 totalTime: 8.996 s, estimated 9 sRan all test suites.