index-program 0.1.12

Virtual namespaces for indexing Solana accounts on-chain
Documentation
# Index Program

The **Index 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<Namespace>())]
    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<CreateMyIndex>, 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<CreateMyPointer>,
  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,
    )
}
```