# List Program The **List Program** creates lookup tables for indexing Solana account addresses on-chain. Developers can use these tables to lookup and verify account data relevant to their programs' instructions and state. ## Get Started ```yaml # Cargo.toml [dependencies] index-program = { version = "0.1.0" } ``` ## Instructions #### [`create_index`](https://github.com/faktorfi/workspace/blob/main/programs/index/src/instructions/create_index.rs) - Initializes a new [`Index`](https://github.com/faktorfi/faktor/blob/main/programs/index/src/state/index.rs) account. - Errors if: - The index already exists for the given owner and namespace. #### [`create_pointer`](https://github.com/faktorfi/workspace/blob/main/programs/index/src/instructions/create_pointer.rs) - Initializes a new [`Pointer`](https://github.com/faktorfi/workspace/blob/main/programs/index/src/state/pointer.rs) account. - Initializes a new [`Proof`](https://github.com/faktorfi/workspace/blob/main/programs/index/src/state/proof.rs) account. - Appends accounts to the index's data structure. - Errors if: - The name is already taken in the index. - The pointer value already exists in the index. #### [`delete_index`](https://github.com/faktorfi/workspace/blob/main/programs/index/src/instructions/delete_index.rs) - Closes an [`Index`](https://github.com/faktorfi/faktor/blob/main/programs/index/src/state/index.rs) account. - Returns rent to owner. - Errors if: - The account does not exist. #### [`delete_pointer`](https://github.com/faktorfi/workspace/blob/main/programs/index/src/instructions/delete_pointer.rs) - Closes a [`Pointer`](https://github.com/faktorfi/workspace/blob/main/programs/index/src/state/pointer.rs) account. - Closes a [`Proof`](https://github.com/faktorfi/workspace/blob/main/programs/index/src/state/proof.rs) account. - Removes accounts from the index's data structure. - Returns rent to owner. - Errors if: - The accounts do not exist. ## State #### [`Index`](https://github.com/faktorfi/workspace/blob/main/programs/index/src/state/index.rs) - Metadata for managing a collection of pointers. - PDA is a hash of the owner's address and a custom namespace address. #### [`Pointer`](https://github.com/faktorfi/workspace/blob/main/programs/index/src/state/pointer.rs) - A named public key address value. - PDA is a hash of the index's address and the pointer's name. #### [`Proof`](https://github.com/faktorfi/workspace/blob/main/programs/index/src/state/proof.rs) - A "reverse record" to lookup the name of a public key in an index. - PDA is a hash of the index's address and the pointer's stored address value. ![Frame 40159](https://user-images.githubusercontent.com/8634334/146040947-f246e623-b105-447e-8ab4-bc4a59eabc52.png) ## Examples These examples are for Solana programs that need to create and manage their own on-chain indices. These examples show a program built with Anchor that has a singleton "authority account" for signing instructions on behalf of the program. ### Create an index Here is an example instruction `create_my_index` that creates an index owned by the program. ```rs // create_my_index.rs use { crate::state::*, anchor_lang::{prelude::*, solana_program::system_program}, std::mem::size_of, }; #[derive(Accounts)] #[instruction(index_bump: u8)] pub struct CreateMyIndex<'info> { #[account(mut, seeds = [SEED_AUTHORITY], bump = authority.bump, owner = crate::ID)] pub authority: Account<'info, Authority>, #[account(mut)] pub index: AccountInfo<'info>, #[account(address = index_program::ID)] pub index_program: Program<'info, index_program::program::IndexProgram>, #[account(init, payer = signer, space = 8 + size_of())] pub namespace: Account<'info, Namespace> #[account(mut)] pub signer: Signer<'info>, #[account(address = system_program::ID)] pub system_program: Program<'info, System>, } pub fn handler(ctx: Context, index_bump: u8) -> ProgramResult { // Get accounts. let authority = &ctx.accounts.authority; let index = &ctx.accounts.index; let index_program = &ctx.accounts.index_program; let namespace = &ctx.accounts.namespace; let signer = &ctx.accounts.signer; let system_program = &ctx.accounts.system_program; // Create an index owned by the program authority. index_program::cpi::create_index( CpiContext::new_with_signer( index_program.to_account_info(), index_program::cpi::accounts::CreateIndex { index: index.to_account_info(), namespace: namespace.to_account_info(), owner: authority.to_account_info(), payer: signer.to_account_info(), system_program: system_program.to_account_info(), }, &[&[SEED_AUTHORITY, &[authority.bump]]], ), index_bump, ) } ``` ### Create a pointer Here is an example instruction `create_my_pointer` that adds a pointer to an index owned by the program. ```rs // create_my_pointer.rs use { crate::state::*, anchor_lang::{prelude::*, solana_program::system_program}, std::mem::size_of, }; #[derive(Accounts)] #[instruction(reference: Pubkey, pointer_bump: u8, proof_bump: u8)] pub struct CreateMyPointer<'info> { #[account(mut, seeds = [SEED_AUTHORITY], bump = authority.bump, owner = crate::ID)] pub authority: Account<'info, Authority>, #[account( mut, constraint = index.owner == authority.key(), constraint = index.namespace == namespace.key(), owner = index_program.key() )] pub index: AccountInfo<'info>, #[account(address = index_program::ID)] pub index_program: Program<'info, index_program::program::IndexProgram>, #[account()] pub namespace: Account<'info, Namespace> #[account()] pub pointer: AccountInfo<'info>, #[account()] pub proof: AccountInfo<'info>, #[account(mut)] pub signer: Signer<'info>, #[account(address = system_program::ID)] pub system_program: Program<'info, System>, } pub fn handler( ctx: Context, reference: Pubkey, pointer_bump: u8, proof_bump: u8 ) -> ProgramResult { // Get accounts. let authority = &ctx.accounts.authority; let index = &ctx.accounts.index; let index_program = &ctx.accounts.index_program; let pointer = &ctx.accounts.pointer; let proof = &ctx.accounts.proof; let signer = &ctx.accounts.signer; let system_program = &ctx.accounts.system_program; // Create an index owned by the program authority. index_program::cpi::create_pointer( CpiContext::new_with_signer( index_program.to_account_info(), index_program::cpi::accounts::CreatePointer { index: index.to_account_info(), pointer: pointer.to_account_info(), proof: proof.to_account_info(), owner: authority.to_account_info(), payer: signer.to_account_info(), system_program: system_program.to_account_info(), }, &[&[SEED_AUTHORITY, &[authority.bump]]], ), index.count.to_string(), reference, pointer_bump, proof_bump, ) } ```