Skip to main content

Entrypoints

CreateState

Entrypoint called when deploying new contract. Creates state and authority pubkey.

#[derive(Accounts)]
#[instruction( nonce: u8)]
pub struct CreateState<'info> {
#[account(init, seeds = [b"statev1".as_ref()], bump, payer = admin, space = State::LEN)]
pub state: AccountLoader<'info, State>,
#[account(mut)]
pub admin: Signer<'info>,
#[account(seeds = [b"Invariant".as_ref()], bump = nonce)]
/// CHECK: Ignore
pub program_authority: AccountInfo<'info>,
pub rent: Sysvar<'info, Rent>,
#[account(address = system_program::ID)]
/// CHECK: Ignore
pub system_program: AccountInfo<'info>,
}

Context Params

NameTypeDescription
nonceu8Authority account nonce.

Accounts

NameTypeDescription
stateStateState account that will be initialized.
adminSignerAdmin account, which is also a signer of the transaction.
program_authorityAccountInfoEmpty account which owns all ATAs and signs transfer transactions.
rentSysvar<'info, Rent>System rent account.
system_programAccountInfoSystem program account.

CreateFeeTier

Admin restricted entrypoint, allows for creation of fee tiers.

#[access_control(admin(&ctx.accounts.state, &ctx.accounts.admin))]
pub fn create_fee_tier(
ctx: Context<CreateFeeTier>,
fee: u128,
tick_spacing: u16,
) -> Result<()> {
ctx.accounts.handler(fee, tick_spacing, ctx.bumps.fee_tier)
}

Entrypoint Params

NameTypeDescription
feeu128Fee that will be converted into fixed point type.
tick_spacingu16Space between valid ticks.

Context

#[derive(Accounts)]
#[instruction(fee: u128, tick_spacing: u16)]
pub struct CreateFeeTier<'info> {
#[account(init,
seeds = [b"feetierv1", __program_id.as_ref(), &fee.to_le_bytes(), &tick_spacing.to_le_bytes()],
bump, payer = admin, space = FeeTier::LEN
)]
pub fee_tier: AccountLoader<'info, FeeTier>,
#[account(seeds = [b"statev1".as_ref()], bump = state.load()?.bump)]
pub state: AccountLoader<'info, State>,
#[account(mut, constraint = &state.load()?.admin == admin.key @ InvalidAdmin)]
pub admin: Signer<'info>,
pub rent: Sysvar<'info, Rent>,
#[account(address = system_program::ID)]
/// CHECK: Ignore
pub system_program: AccountInfo<'info>,
}

Context Params

NameTypeDescription
feeu128Fee that will be converted into fixed point type.
tick_spacingu16Space between valid ticks.

Accounts

NameTypeDescription
fee_tierFeeTierFeeTier to be created.
stateStateState account of the protocol.
adminSignerProtocol admin account.
rentSysvar<'info, Rent>System rent account.
system_programAccountInfoSystem program account.

Errors

CodeDescription
InvalidTickSpacingTick spacing outside of valid range.
InvalidAdminAdmin account is invalid.

CreatePool

Entrypoint used for creating pools. Tickmap account key must be generated off chain. To use pool fully you must initialize reserves with a separate entrypoint.

pub fn create_pool(ctx: Context<CreatePool>, init_tick: i32) -> Result<()> {
ctx.accounts.handler(init_tick, ctx.bumps.pool)
}

Entrypoint Params

NameTypeDescription
init_ticki32Initial price tick for the pool.

Context

#[derive(Accounts)]
pub struct CreatePool<'info> {
#[account(seeds = [b"statev1".as_ref()], bump = state.load()?.bump)]
pub state: AccountLoader<'info, State>,
#[account(init,
seeds = [b"poolv1", token_x.to_account_info().key.as_ref(), token_y.to_account_info().key.as_ref(), &fee_tier.load()?.fee.v.to_le_bytes(), &fee_tier.load()?.tick_spacing.to_le_bytes()],
bump, payer = payer, space = Pool::LEN
)]
pub pool: AccountLoader<'info, Pool>,
#[account(
seeds = [b"feetierv1", __program_id.as_ref(), &fee_tier.load()?.fee.v.to_le_bytes(), &fee_tier.load()?.tick_spacing.to_le_bytes()],
bump = fee_tier.load()?.bump
)]
pub fee_tier: AccountLoader<'info, FeeTier>,
#[account(zero)]
pub tickmap: AccountLoader<'info, Tickmap>,

#[account(
mint::token_program = token_x_program
)]
pub token_x: Box<InterfaceAccount<'info, Mint>>,
#[account(
mint::token_program = token_y_program
)]
pub token_y: Box<InterfaceAccount<'info, Mint>>,

#[account(mut)]
pub payer: Signer<'info>,

#[account(constraint = token_x_program.key() == token::ID || token_x_program.key() == token_2022::ID)]
pub token_x_program: Interface<'info, TokenInterface>,
#[account(constraint = token_y_program.key() == token::ID || token_y_program.key() == token_2022::ID)]
pub token_y_program: Interface<'info, TokenInterface>,
pub rent: Sysvar<'info, Rent>,
#[account(address = system_program::ID)]
/// CHECK: ignore
pub system_program: AccountInfo<'info>,
}

Accounts

NameTypeDescription
stateStateState account of the protocol.
fee_tierFeeTierFeeTier that the tick spacing and fee percentage will be taken from.
tickmapTickmapEmpty account that will be used to store tickmap.
token_xMintToken X Mint account.
token_yMintToken Y Mint account.
payerSignerSigner of the transaction.
token_x_programTokenInterfaceToken X associated program account.
token_y_programTokenInterfaceToken Y associated program account.
rentSysvar<'info, Rent>System rent account.
system_programAccountInfoSystem program account.

Errors

CodeDescription
InvalidTickIndexInitial tick not divisible by spacing or outside of size limit or price limit.

InitReserves

Entrypoint used for initializing reserves on existing pool. It only needs to be called once after creating the pool.

pub fn init_reserves(ctx: Context<InitReserves>) -> Result<()> {
ctx.accounts.handler()
}

Context

#[derive(Accounts)]
pub struct InitReserves<'info> {
#[account(seeds = [b"statev1".as_ref()], bump = state.load()?.bump)]
pub state: AccountLoader<'info, State>,
#[account(mut,
seeds = [b"poolv1", token_x.to_account_info().key.as_ref(), token_y.to_account_info().key.as_ref(), &pool.load()?.fee.v.to_le_bytes(), &pool.load()?.tick_spacing.to_le_bytes()],
bump = pool.load()?.bump
)]
pub pool: AccountLoader<'info, Pool>,

#[account(
mint::token_program = token_x_program
)]
pub token_x: Box<InterfaceAccount<'info, Mint>>,
#[account(
mint::token_program = token_y_program
)]
pub token_y: Box<InterfaceAccount<'info, Mint>>,

#[account(init,
token::mint = token_x,
token::authority = authority,
token::token_program = token_x_program,
payer = payer,
)]
pub token_x_reserve: Box<InterfaceAccount<'info, TokenAccount>>,
#[account(init,
token::mint = token_y,
token::authority = authority,
token::token_program = token_y_program,
payer = payer,
)]
pub token_y_reserve: Box<InterfaceAccount<'info, TokenAccount>>,
#[account(mut)]
pub payer: Signer<'info>,
#[account(constraint = &state.load()?.authority == authority.key @ InvalidAuthority)]
/// CHECK: ignore
pub authority: AccountInfo<'info>,

#[account(constraint = token_x_program.key() == token::ID || token_x_program.key() == token_2022::ID)]
pub token_x_program: Interface<'info, TokenInterface>,
#[account(constraint = token_y_program.key() == token::ID || token_y_program.key() == token_2022::ID)]
pub token_y_program: Interface<'info, TokenInterface>,
#[account(address = system_program::ID)]
/// CHECK: ignore
pub system_program: AccountInfo<'info>,
}

Accounts

NameTypeDescription
stateStateState account of the protocol.
poolPoolPool to initialize the reserves of.
token_xMintToken X Mint account.
token_yMintToken Y Mint account.
token_x_reserveTokenAccountEmpty account for Token X associated token account.
token_y_reserveTokenAccountEmpty account for Token Y associated token account.
payerSignerSigner of the transaction.
authorityAccountInfoAuthority account from the protocol state.
token_x_programTokenInterfaceToken X associated program account.
token_y_programTokenInterfaceToken Y associated program account.
system_programAccountInfoSystem program account.

Errors

CodeDescription
InvalidAuthorityProvided authority is invalid or provided token account doesn't belong to authority.
InvalidPoolTokenAddressesTokens were not sorted correctly or are the same.

CreatePositionList

Creates position list for an account, position list is unique for the entire protocol.

pub fn create_position_list(ctx: Context<CreatePositionList>) -> Result<()> {
ctx.accounts.handler(ctx.bumps.position_list)
}

Context

#[derive(Accounts)]
pub struct CreatePositionList<'info> {
#[account(init,
seeds = [b"positionlistv1", owner.key().as_ref()],
bump,
payer = signer,
space = PositionList::LEN
)]
pub position_list: AccountLoader<'info, PositionList>,
/// CHECK: Ignore
pub owner: AccountInfo<'info>,
#[account(mut)]
pub signer: Signer<'info>,
pub rent: Sysvar<'info, Rent>,
#[account(address = system_program::ID)]
/// CHECK: Ignore
pub system_program: AccountInfo<'info>,
}

Accounts

NameTypeDescription
position_listPositionListAccount of the position list to be created.
ownerAccountInfoAccount of the position list owner.
signerSignerAccount of transaction signer.
rentSysvar<'info, Rent>Rent account.
system_programAccountInfoSystem program account.

CreateTick

Creates tick on a specified pool with specified tick index.

pub fn create_tick(ctx: Context<CreateTick>, index: i32) -> Result<()> {
ctx.accounts.handler(index, ctx.bumps.tick)
}

Entrypoint Params

NameTypeDescription
indexi32Index of the tick.

Context

#[derive(Accounts)]
#[instruction( index: i32)]
pub struct CreateTick<'info> {
#[account(init,
seeds = [b"tickv1", pool.key().as_ref(), &index.to_le_bytes()],
bump, payer = payer, space = Tick::LEN
)]
pub tick: AccountLoader<'info, Tick>,
#[account(
seeds = [b"poolv1", token_x.key().as_ref(), token_y.key().as_ref(), &pool.load()?.fee.v.to_le_bytes(), &pool.load()?.tick_spacing.to_le_bytes()],
bump = pool.load()?.bump
)]
pub pool: AccountLoader<'info, Pool>,
#[account(mut,
constraint = tickmap.key() == pool.load()?.tickmap @ InvalidTickmap,
constraint = tickmap.to_account_info().owner == __program_id @ InvalidTickmapOwner,
)]
pub tickmap: AccountLoader<'info, Tickmap>,
#[account(mut)]
pub payer: Signer<'info>,

#[account(
constraint = token_x.key() == pool.load()?.token_x @ InvalidTokenAccount,
mint::token_program = token_x_program
)]
pub token_x: InterfaceAccount<'info, Mint>,
#[account(
constraint = token_y.key() == pool.load()?.token_y @ InvalidTokenAccount,
mint::token_program = token_y_program
)]
pub token_y: InterfaceAccount<'info, Mint>,
pub rent: Sysvar<'info, Rent>,
#[account(address = system_program::ID)]
/// CHECK: Ignore
pub system_program: AccountInfo<'info>,

#[account(constraint = token_x_program.key() == token::ID || token_x_program.key() == token_2022::ID)]
pub token_x_program: Interface<'info, TokenInterface>,
#[account(constraint = token_y_program.key() == token::ID || token_y_program.key() == token_2022::ID)]
pub token_y_program: Interface<'info, TokenInterface>,
}

Context Params

NameTypeDescription
indexi32Index of the tick.

Accounts

NameTypeDescription
tickTickAccount of the tick to be created.
poolPoolPool on which the tick will be created.
tickmapTickmapAccount of the pools tickmap.
token_xMintToken X mint account.
token_yMintToken Y mint account.
token_x_programTokenInterfaceToken X associated token account.
token_y_programTokenInterfaceToken Y associated token account.
payerSignerAccount of transaction signer.
rentSysvar<'info, Rent>Rent account.
system_programAccountInfoSystem program account.

Errors

CodeDescription
InvalidTickmapTickmap doesn't match pools tickmap.
InvalidTickmapOwnerTickmap owned by wrong account.
InvalidTokenAccountProvided token mint is incorrect.
InvalidTickIndexInitial tick not divisible by spacing or outside of size limit or price limit.

CreatePosition

Creates position on desired pool with liquidity spread on the range specified by the tick indexes range.

pub fn create_position(
ctx: Context<CreatePosition>,
_lower_tick_index: i32,
_upper_tick_index: i32,
liquidity_delta: Liquidity,
slippage_limit_lower: Price,
slippage_limit_upper: Price,
) -> Result<()> {
ctx.accounts.handler(
liquidity_delta,
slippage_limit_lower,
slippage_limit_upper,
ctx.bumps.position,
)
}

Entrypoint Params

NameTypeDescription
lower_tick_indexi32Index of the lower tick for the position.
upper_tick_indexi32Index of the upper tick for the position.
liquidity_deltaLiquidityLiquidity for the new position.
slippage_limit_lowerPriceMin price the pool may have at the moment when position is created.
slippage_limit_upperPriceMax price the pool may have at the moment when position is created.

Context

#[derive(Accounts)]
#[instruction( lower_tick_index: i32, upper_tick_index: i32)]
pub struct CreatePosition<'info> {
#[account(seeds = [b"statev1".as_ref()], bump = state.load()?.bump)]
pub state: AccountLoader<'info, State>,
#[account(init,
seeds = [b"positionv1",
owner.key.as_ref(),
&position_list.load()?.head.to_le_bytes()],
bump, payer = payer, space = Position::LEN
)]
pub position: AccountLoader<'info, Position>,
#[account(mut,
seeds = [b"poolv1", token_x.key().as_ref(), token_y.key().as_ref(), &pool.load()?.fee.v.to_le_bytes(), &pool.load()?.tick_spacing.to_le_bytes()],
bump = pool.load()?.bump
)]
pub pool: AccountLoader<'info, Pool>,
#[account(mut,
seeds = [b"positionlistv1", owner.key.as_ref()],
bump = position_list.load()?.bump
)]
pub position_list: AccountLoader<'info, PositionList>,
#[account(mut)]
pub payer: Signer<'info>,
pub owner: Signer<'info>,
#[account(mut,
seeds = [b"tickv1", pool.key().as_ref(), &lower_tick_index.to_le_bytes()],
bump = lower_tick.load()?.bump
)]
pub lower_tick: AccountLoader<'info, Tick>,
#[account(mut,
seeds = [b"tickv1", pool.key().as_ref(), &upper_tick_index.to_le_bytes()],
bump = upper_tick.load()?.bump
)]
pub upper_tick: AccountLoader<'info, Tick>,
#[account(mut,
constraint = tickmap.key() == pool.load()?.tickmap @ InvalidTickmap,
constraint = tickmap.to_account_info().owner == __program_id @ InvalidTickmapOwner,
)]
pub tickmap: AccountLoader<'info, Tickmap>,
#[account(constraint = token_x.key() == pool.load()?.token_x @ InvalidTokenAccount, mint::token_program = token_x_program)]
pub token_x: InterfaceAccount<'info, Mint>,
#[account(constraint = token_y.key() == pool.load()?.token_y @ InvalidTokenAccount, mint::token_program = token_y_program)]
pub token_y: InterfaceAccount<'info, Mint>,
#[account(mut,
constraint = account_x.mint == token_x.key() @ InvalidMint,
constraint = &account_x.owner == owner.key @ InvalidOwner,
token::token_program = token_x_program,
)]
pub account_x: Box<InterfaceAccount<'info, TokenAccount>>,
#[account(mut,
constraint = account_y.mint == token_y.key() @ InvalidMint,
constraint = &account_y.owner == owner.key @ InvalidOwner,
token::token_program = token_y_program,
)]
pub account_y: Box<InterfaceAccount<'info, TokenAccount>>,
#[account(mut,
constraint = reserve_x.mint == token_x.key() @ InvalidMint,
constraint = &reserve_x.owner == program_authority.key @ InvalidOwner,
constraint = reserve_x.key() == pool.load()?.token_x_reserve @ InvalidTokenAccount,
token::token_program = token_x_program,
)]
pub reserve_x: Box<InterfaceAccount<'info, TokenAccount>>,
#[account(mut,
constraint = reserve_y.mint == token_y.key() @ InvalidMint,
constraint = &reserve_y.owner == program_authority.key @ InvalidOwner,
constraint = reserve_y.key() == pool.load()?.token_y_reserve @ InvalidTokenAccount,
token::token_program = token_y_program,
)]
pub reserve_y: Box<InterfaceAccount<'info, TokenAccount>>,
#[account(constraint = &state.load()?.authority == program_authority.key @ InvalidAuthority)]
/// CHECK: ignore
pub program_authority: AccountInfo<'info>,

#[account(constraint = token_x_program.key() == token::ID || token_x_program.key() == token_2022::ID)]
pub token_x_program: Interface<'info, TokenInterface>,
#[account(constraint = token_y_program.key() == token::ID || token_y_program.key() == token_2022::ID)]
pub token_y_program: Interface<'info, TokenInterface>,
pub rent: Sysvar<'info, Rent>,
#[account(address = system_program::ID)]
/// CHECK: ignore
pub system_program: AccountInfo<'info>,
}

Context Params

NameTypeDescription
lower_tick_indexi32Index of the lower tick for the position.
upper_tick_indexi32Index of the upper tick for the position.

Accounts

NameTypeDescription
stateStateAccount of the protocols state.
position_listPositionListAccount of the position owner's position list.
positionPositionPosition account that will be created.
poolPoolAccount of the pool on which the position should be created.
lower_tickTickAccount of the Tick corresponding to lower tick index of the position.
upper_tickTickAccount of the Tick corresponding to upper tick index of the position.
tickmapTickmapTickmap account for the pool.
ownerSingerAccount of the position list owner.
signerSignerAccount of transaction signer.
token_x_programTokenInterfaceToken X associated program account.
token_y_programTokenInterfaceToken Y associated program account.
reserve_xTokenAccountPool's token X associated token account.
reserve_yTokenAccountPool's token Y associated token account.
account_xTokenAccountUsers's token X associated token account.
account_yTokenAccountUsers's token Y associated token account.
token_xMintToken X mint account.
token_yMintToken Y mint account.
program_authorityAccountInfoProtocol authority account.
rentSysvar<'info, Rent>Rent account.
system_programAccountInfoSystem program account.

Errors

CodeDescription
WrongTickTick account doesn't match the tick index on the position.
InvalidTickmapTickmap doesn't match pools tickmap.
InvalidTickmapOwnerTickmap owned by wrong account.
InvalidTokenAccountProvided token mint is incorrect or reserve account doesn't match pool reserves.
InvalidMintProvided token accounts mint doesn't match provided mint.
InvalidOwnerProvided token account doesn't belong to position owner.
InvalidAuthorityProvided authority is invalid or provided token account doesn't belong to authority.
InvalidTokenProgramInvalid token program for provided token account.
InvalidTickIndexInitial tick not divisible by spacing or outside of size limit or price limit.
PriceLimitReachedSlippage limit reached.

RemovePosition

Removes position specified by the index. Index is based on all user positions.

pub fn remove_position(
ctx: Context<RemovePosition>,
index: u32,
lower_tick_index: i32,
upper_tick_index: i32,
) -> Result<()> {
ctx.accounts
.handler(index, lower_tick_index, upper_tick_index)
}

Entrypoint Params

NameTypeDescription
indexi32Index of the position to remove.
lower_tick_indexi32Index of the lower tick for the position.
upper_tick_indexi32Index of the upper tick for the position.

Context

#[derive(Accounts)]
#[instruction(index: i32, lower_tick_index: i32, upper_tick_index: i32)]
pub struct RemovePosition<'info> {
#[account(seeds = [b"statev1".as_ref()], bump = state.load()?.bump)]
pub state: AccountLoader<'info, State>,
#[account(mut,
seeds = [b"positionv1",
owner.key().as_ref(),
&index.to_le_bytes()],
bump = removed_position.load()?.bump
)]
pub removed_position: AccountLoader<'info, Position>,
#[account(mut,
seeds = [b"positionlistv1", owner.key().as_ref()],
bump = position_list.load()?.bump
)]
pub position_list: AccountLoader<'info, PositionList>,
#[account(mut,
close = payer,
seeds = [b"positionv1",
owner.key().as_ref(),
&(position_list.load()?.head - 1).to_le_bytes()],
bump = last_position.load()?.bump
)]
pub last_position: AccountLoader<'info, Position>,
#[account(mut,
seeds = [b"poolv1", token_x.key().as_ref(), token_y.key().as_ref(), &pool.load()?.fee.v.to_le_bytes(), &pool.load()?.tick_spacing.to_le_bytes()],
bump = pool.load()?.bump
)]
pub pool: AccountLoader<'info, Pool>,
#[account(mut,
constraint = tickmap.key() == pool.load()?.tickmap @ InvalidTickmap,
constraint = tickmap.to_account_info().owner == __program_id @ InvalidTickmapOwner,
)]
pub tickmap: AccountLoader<'info, Tickmap>,
#[account(mut,
seeds = [b"tickv1", pool.key().as_ref(), &lower_tick_index.to_le_bytes()],
bump = lower_tick.load()?.bump,
constraint = lower_tick_index == removed_position.load()?.lower_tick_index @ WrongTick
)]
pub lower_tick: AccountLoader<'info, Tick>,
#[account(mut,
seeds = [b"tickv1", pool.key().as_ref(), &upper_tick_index.to_le_bytes()],
bump = upper_tick.load()?.bump,
constraint = upper_tick_index == removed_position.load()?.upper_tick_index @ WrongTick
)]
pub upper_tick: AccountLoader<'info, Tick>,
#[account(mut)]
pub payer: Signer<'info>,
pub owner: Signer<'info>,
#[account(constraint = token_x.key() == pool.load()?.token_x @ InvalidTokenAccount, mint::token_program = token_x_program)]
pub token_x: InterfaceAccount<'info, Mint>,
#[account(constraint = token_y.key() == pool.load()?.token_y @ InvalidTokenAccount, mint::token_program = token_y_program)]
pub token_y: InterfaceAccount<'info, Mint>,
#[account(mut,
constraint = account_x.mint == token_x.key() @ InvalidMint,
constraint = &account_x.owner == owner.key @ InvalidOwner,
token::token_program = token_x_program
)]
pub account_x: Box<InterfaceAccount<'info, TokenAccount>>,
#[account(mut,
constraint = account_y.mint == token_y.key() @ InvalidMint,
constraint = &account_y.owner == owner.key @ InvalidOwner,
token::token_program = token_y_program
)]
pub account_y: Box<InterfaceAccount<'info, TokenAccount>>,
#[account(mut,
constraint = reserve_x.mint == token_x.key() @ InvalidMint,
constraint = &reserve_x.owner == program_authority.key @ InvalidAuthority,
constraint = reserve_x.key() == pool.load()?.token_x_reserve @ InvalidTokenAccount,
token::token_program = token_x_program
)]
pub reserve_x: Box<InterfaceAccount<'info, TokenAccount>>,
#[account(mut,
constraint = reserve_y.mint == token_y.key() @ InvalidMint,
constraint = &reserve_y.owner == program_authority.key @ InvalidAuthority,
constraint = reserve_y.key() == pool.load()?.token_y_reserve @ InvalidTokenAccount,
token::token_program = token_y_program
)]
pub reserve_y: Box<InterfaceAccount<'info, TokenAccount>>,
#[account(constraint = &state.load()?.authority == program_authority.key @ InvalidAuthority)]
/// CHECK: Ignore
pub program_authority: AccountInfo<'info>,

#[account(constraint = token_x_program.key() == token::ID || token_x_program.key() == token_2022::ID)]
pub token_x_program: Interface<'info, TokenInterface>,
#[account(constraint = token_y_program.key() == token::ID || token_y_program.key() == token_2022::ID)]
pub token_y_program: Interface<'info, TokenInterface>,
}

Context Params

NameTypeDescription
indexi32Index of the removed position on position list.
lower_tick_indexi32Index of the lower tick for the position.
upper_tick_indexi32Index of the upper tick for the position.

Accounts

NameTypeDescription
stateStateAccount of the protocols state.
position_listPositionListAccount of the position owner's position list.
positionPositionPosition account that will be removed.
poolPoolAccount of the pool from which the position should be removed.
lower_tickTickAccount of the Tick corresponding to lower tick index of the position.
upper_tickTickAccount of the Tick corresponding to upper tick index of the position.
tickmapTickmapTickmap account for the pool.
ownerSingerAccount of the position list owner.
signerSignerAccount of transaction signer.
token_x_programTokenInterfaceToken X associated program account.
token_y_programTokenInterfaceToken Y associated program account.
reserve_xTokenAccountPool's token X associated token account.
reserve_yTokenAccountPool's token Y associated token account.
account_xTokenAccountUsers's token X associated token account.
account_yTokenAccountUsers's token Y associated token account.
token_xMintToken X mint account.
token_yMintToken Y mint account.
removed_positionPositionPosition that will be removed.
last_positionPositionLast position of the users list.
program_authorityAccountInfoProtocol authority account.

Errors

CodeDescription
WrongTickTick account doesn't match the tick index on the position.
InvalidTickmapTickmap doesn't match pools tickmap.
InvalidTickmapOwnerTickmap owned by wrong account.
InvalidTokenAccountProvided token mint is incorrect or reserve account doesn't match pool reserves.
InvalidMintProvided token accounts mint doesn't match provided mint.
InvalidOwnerProvided token account doesn't belong to position owner.
InvalidAuthorityProvided authority is invalid or provided token account doesn't belong to authority.
InvalidTokenProgramInvalid token program for provided token account.
InvalidTickIndexInitial tick not divisible by spacing or outside of size limit or price limit.

Swap

Performs a swap w specified parameters.

pub fn swap<'info>(
ctx: Context<'_, '_, 'info, 'info, Swap<'info>>,
x_to_y: bool,
amount: u64,
by_amount_in: bool,
sqrt_price_limit: u128,
) -> Result<()> {
Swap::handler(ctx, x_to_y, amount, by_amount_in, sqrt_price_limit)
}

Entrypoint Params

NameTypeDescription
x_to_yboolSpecifies the direction of the swap.
amountu64Amount of tokens you want to receive or give.
by_amount_inboolIndicates whether the entered amount represents the tokens you wish to receive or give.
sqrt_price_limitPriceIf the swap achieves this square root of the price, it will be canceled.

Context

#[derive(Accounts)]
pub struct Swap<'info> {
#[account(seeds = [b"statev1".as_ref()], bump = state.load()?.bump)]
pub state: AccountLoader<'info, State>,
#[account(mut,
seeds = [b"poolv1", account_x.mint.as_ref(), account_y.mint.as_ref(), &pool.load()?.fee.v.to_le_bytes(), &pool.load()?.tick_spacing.to_le_bytes()],
bump = pool.load()?.bump
)]
pub pool: AccountLoader<'info, Pool>,
#[account(mut,
constraint = tickmap.to_account_info().key == &pool.load()?.tickmap @ InvalidTickmap,
constraint = tickmap.to_account_info().owner == __program_id @ InvalidTickmapOwner
)]
pub tickmap: AccountLoader<'info, Tickmap>,
#[account(constraint = token_x.key() == pool.load()?.token_x @ InvalidTokenAccount, mint::token_program = token_x_program)]
pub token_x: Box<InterfaceAccount<'info, Mint>>,
#[account(constraint = token_y.key() == pool.load()?.token_y @ InvalidTokenAccount, mint::token_program = token_y_program)]
pub token_y: Box<InterfaceAccount<'info, Mint>>,
#[account(mut,
constraint = &account_x.owner == owner.key @ InvalidOwner,
token::token_program = token_x_program,
)]
pub account_x: InterfaceAccount<'info, TokenAccount>,
#[account(mut,
constraint = &account_y.owner == owner.key @ InvalidOwner,
token::token_program = token_y_program
)]
pub account_y: InterfaceAccount<'info, TokenAccount>,
#[account(mut,
constraint = reserve_x.mint == account_x.mint @ InvalidMint,
constraint = &reserve_x.owner == program_authority.key @ InvalidAuthority,
constraint = reserve_x.to_account_info().key == &pool.load()?.token_x_reserve @ InvalidTokenAccount,
token::token_program = token_x_program
)]
pub reserve_x: Box<InterfaceAccount<'info, TokenAccount>>,
#[account(mut,
constraint = reserve_y.mint == account_y.mint @ InvalidMint,
constraint = &reserve_y.owner == program_authority.key @ InvalidAuthority,
constraint = reserve_y.to_account_info().key == &pool.load()?.token_y_reserve @ InvalidTokenAccount,
token::token_program = token_y_program
)]
pub reserve_y: Box<InterfaceAccount<'info, TokenAccount>>,
pub owner: Signer<'info>,
#[account(constraint = &state.load()?.authority == program_authority.key @ InvalidAuthority)]
/// CHECK: Ignore
pub program_authority: AccountInfo<'info>,

#[account(constraint = token_x_program.key() == token::ID || token_x_program.key() == token_2022::ID)]
pub token_x_program: Interface<'info, TokenInterface>,
#[account(constraint = token_y_program.key() == token::ID || token_y_program.key() == token_2022::ID)]
pub token_y_program: Interface<'info, TokenInterface>,
}

Accounts

NameTypeDescription
stateStateAccount of the protocols state.
poolPoolAccount of the pool on which the position should be created.
tickmapTickmapTickmap account for the pool.
ownerSignerAccount of transaction signer.
token_x_programTokenInterfaceToken X associated program account.
token_y_programTokenInterfaceToken Y associated program account.
reserve_xTokenAccountPool's token X associated token account.
reserve_yTokenAccountPool's token Y associated token account.
account_xTokenAccountUsers's token X associated token account.
account_yTokenAccountUsers's token Y associated token account.
token_xMintToken X mint account.
token_yMintToken Y mint account.
program_authorityAccountInfoProtocol authority account.
remaining_accountsVec\<AccountInfo>Tick account addresses that could be used in the swap.

Errors

CodeDescription
InvalidTickmapTickmap doesn't match pools tickmap.
InvalidTickmapOwnerTickmap owned by wrong account.
InvalidTokenAccountProvided token mint is incorrect or reserve account doesn't match pool reserves.
InvalidMintProvided token accounts mint doesn't match provided mint.
InvalidOwnerProvided token account doesn't belong to position owner.
InvalidAuthorityProvided authority is invalid or provided token account doesn't belong to authority.
InvalidTokenProgramInvalid token program for provided token account.
ZeroAmountInput amount is 0.
NoGainSwapOutput amount is 0.
WrongLimitPrice limit is on the wrong side of the current price.
PriceLimitReachedPrice limit reached before acquiring the desired amount.
LimitReachedTick limit reached before acquiring the desired amount.
TickNotFoundTick account is missing from remaining accounts.

*Additionally an error indicating that account wasn't found may appear if the tick accounts that would be used in the swap are missing from remaining accounts.

TransferPositionOwnership

Transfers position from one account to another.

pub fn transfer_position_ownership(
ctx: Context<TransferPositionOwnership>,
index: u32,
) -> Result<()> {
ctx.accounts.handler(index, ctx.bumps.new_position)
}

Entrypoint Params

NameTypeDescription
indexu32Index of the transferred position.

Context

#[derive(Accounts)]
#[instruction( index: u32)]
pub struct TransferPositionOwnership<'info> {
#[account(mut,
seeds = [b"positionlistv1", owner.key().as_ref()],
bump = owner_list.load()?.bump
)]
pub owner_list: AccountLoader<'info, PositionList>,
#[account(mut,
seeds = [b"positionlistv1", recipient.key().as_ref()],
bump = recipient_list.load()?.bump,
constraint = recipient_list.key() != owner_list.key() @ InvalidListOwner
)]
pub recipient_list: AccountLoader<'info, PositionList>,
#[account(init,
seeds = [b"positionv1",
recipient.key().as_ref(),
&recipient_list.load()?.head.to_le_bytes()],
bump, payer = payer,
space = Position::LEN
)]
pub new_position: AccountLoader<'info, Position>,
#[account(mut,
seeds = [b"positionv1",
owner.key().as_ref(),
&index.to_le_bytes()],
bump = removed_position.load()?.bump,
)]
pub removed_position: AccountLoader<'info, Position>,
#[account(mut,
close = payer,
seeds = [b"positionv1",
owner.key().as_ref(),
&(owner_list.load()?.head - 1).to_le_bytes()],
bump = last_position.load()?.bump
)]
pub last_position: AccountLoader<'info, Position>,
#[account(mut)]
pub payer: Signer<'info>,
pub owner: Signer<'info>,
/// CHECK: Ignore
pub recipient: AccountInfo<'info>,
pub rent: Sysvar<'info, Rent>,
#[account(address = system_program::ID)]
/// CHECK: Ignore
pub system_program: AccountInfo<'info>,
}

Accounts

NameTypeDescription
owner_listPositionListAccount of transferred position owners position list.
recipient_listPositionListAccount of position recipients position list.
ownerSignerAccount of transferred position owner.
payerSignerAccount of transaction signer.
removed_positionPositionTransferred position.
new_positionPositionEmpty position account the address which should match new position address for recipients position list.
rentSysvar<'info, Rent>Rent account.
system_programAccountInfoSystem program account.

Errors

CodeDescription
InvalidListOwnerPosition list doesn't belong to the position owner.

UpdateSecondsPerLiquidity

Updates seconds per liquidity parameter for a position (used with farms).

pub fn update_seconds_per_liquidity(
ctx: Context<UpdateSecondsPerLiquidity>,
_lower_tick_index: i32,
_upper_tick_index: i32,
_index: i32,
) -> Result<()> {
ctx.accounts.handler()
}

Entrypoint Params

NameTypeDescription
indexi32Index of the updated position on position list.
lower_tick_indexi32Index of the lower tick for the position.
upper_tick_indexi32Index of the upper tick for the position.

Context

#[derive(Accounts)]
#[instruction(lower_tick_index: i32, upper_tick_index: i32, index: i32)]
pub struct UpdateSecondsPerLiquidity<'info> {
#[account(mut,
seeds = [b"poolv1", token_x.key().as_ref(), token_y.key().as_ref(), &pool.load()?.fee.v.to_le_bytes(), &pool.load()?.tick_spacing.to_le_bytes()],
bump = pool.load()?.bump
)]
pub pool: AccountLoader<'info, Pool>,
#[account(
seeds = [b"tickv1", pool.key().as_ref(), &lower_tick_index.to_le_bytes()],
bump = lower_tick.load()?.bump,
constraint = lower_tick_index == position.load()?.lower_tick_index @ WrongTick
)]
pub lower_tick: AccountLoader<'info, Tick>,
#[account(
seeds = [b"tickv1", pool.key().as_ref(), &upper_tick_index.to_le_bytes()],
bump = upper_tick.load()?.bump,
constraint = upper_tick_index == position.load()?.upper_tick_index @ WrongTick
)]
pub upper_tick: AccountLoader<'info, Tick>,
#[account(mut,
seeds = [b"positionv1",
owner.key().as_ref(),
&index.to_le_bytes()],
bump = position.load()?.bump
)]
pub position: AccountLoader<'info, Position>,
#[account(constraint = token_x.key() == pool.load()?.token_x @ InvalidTokenAccount)]
pub token_x: InterfaceAccount<'info, Mint>,
#[account(constraint = token_y.key() == pool.load()?.token_y @ InvalidTokenAccount)]
pub token_y: InterfaceAccount<'info, Mint>,
/// CHECK: Ignore
pub owner: AccountInfo<'info>,
#[account(mut)]
pub signer: Signer<'info>,
pub rent: Sysvar<'info, Rent>,
#[account(address = system_program::ID)]
/// CHECK: Ignore
pub system_program: AccountInfo<'info>,
}

Context Params

NameTypeDescription
indexi32Index of the updated position on position list.
lower_tick_indexi32Index of the lower tick for the position.
upper_tick_indexi32Index of the upper tick for the position.

Accounts

NameTypeDescription
poolPoolPool on which the position exists.
lower_tickTickLower tick account for the position.
upper_tickTickUpper tick account for the position.
positionPositionPosition to update.
token_xMintToken X's mint account.
token_yMintToken Y's mint account.
ownerAccountInfoAccount of the position owner.
signerSignerAccount of the signer.
rentSysvar<'info, Rent>Rent account.
system_programAccountInfoSystem program account.

Errors

CodeDescription
WrongTickTick account doesn't match the tick index on the position.
InvalidTokenAccountProvided token mint is incorrect or reserve account doesn't match pool reserves.
InvalidTickIndexInitial tick not divisible by spacing or outside of size limit or price limit.
InvalidTokenProgramInvalid token program for provided token account.

WithdrawProtocolFee

#[access_control(receiver(&ctx.accounts.pool, &ctx.accounts.authority))]
pub fn withdraw_protocol_fee(ctx: Context<WithdrawProtocolFee>) -> Result<()> {
ctx.accounts.handler()
}

Context

#[derive(Accounts)]
pub struct WithdrawProtocolFee<'info> {
#[account(seeds = [b"statev1".as_ref()], bump = state.load()?.bump)]
pub state: AccountLoader<'info, State>,
#[account(mut,
seeds = [b"poolv1", token_x.key().as_ref(), token_y.key().as_ref(), &pool.load()?.fee.v.to_le_bytes(), &pool.load()?.tick_spacing.to_le_bytes()],
bump = pool.load()?.bump
)]
pub pool: AccountLoader<'info, Pool>,
#[account(constraint = token_x.key() == pool.load()?.token_x @ InvalidTokenAccount, mint::token_program = token_x_program)]
pub token_x: InterfaceAccount<'info, Mint>,
#[account(constraint = token_y.key() == pool.load()?.token_y @ InvalidTokenAccount, mint::token_program = token_y_program)]
pub token_y: InterfaceAccount<'info, Mint>,
#[account(mut,
constraint = account_x.mint == token_x.key() @ InvalidMint,
token::token_program = token_x_program,
)]
pub account_x: Box<InterfaceAccount<'info, TokenAccount>>,
#[account(mut,
constraint = account_y.mint == token_y.key() @ InvalidMint,
token::token_program = token_y_program,
)]
pub account_y: Box<InterfaceAccount<'info, TokenAccount>>,
#[account(mut,
constraint = reserve_x.mint == token_x.key() @ InvalidMint,
constraint = &reserve_x.owner == program_authority.key @ InvalidAuthority,
constraint = reserve_x.key() == pool.load()?.token_x_reserve @ InvalidTokenAccount,
token::token_program = token_x_program
)]
pub reserve_x: InterfaceAccount<'info, TokenAccount>,
#[account(mut,
constraint = reserve_y.mint == token_y.key() @ InvalidMint,
constraint = &reserve_y.owner == program_authority.key @ InvalidAuthority,
constraint = reserve_y.key() == pool.load()?.token_y_reserve @ InvalidTokenAccount,
token::token_program = token_y_program,
)]
pub reserve_y: InterfaceAccount<'info, TokenAccount>,
#[account(constraint = &pool.load()?.fee_receiver == authority.key @ InvalidAuthority)]
pub authority: Signer<'info>,
#[account(constraint = &state.load()?.authority == program_authority.key @ InvalidAuthority)]
/// CHECK: Ignore
pub program_authority: AccountInfo<'info>,

#[account(constraint = token_x_program.key() == token::ID || token_x_program.key() == token_2022::ID)]
pub token_x_program: Interface<'info, TokenInterface>,
#[account(constraint = token_y_program.key() == token::ID || token_y_program.key() == token_2022::ID)]
pub token_y_program: Interface<'info, TokenInterface>,
}

Accounts

NameTypeDescription
stateStateAccount of the protocols state.
poolPoolAccount of the pool from which the fee will be withdrawn.
token_x_programTokenInterfaceToken X associated program account.
token_y_programTokenInterfaceToken Y associated program account.
reserve_xTokenAccountPool's token X associated token account.
reserve_yTokenAccountPool's token Y associated token account.
account_xTokenAccountUsers's token X associated token account.
account_yTokenAccountUsers's token Y associated token account.
token_xMintToken X mint account.
token_yMintToken Y mint account.
authoritySignerAccount of transaction signer, must be admin.
program_authorityAccountInfoProtocol authority account.

Errors

CodeDescription
InvalidTokenAccountProvided token mint is incorrect or reserve account doesn't match pool reserves.
InvalidMintProvided token accounts mint doesn't match provided mint.
InvalidOwnerProvided token account doesn't belong to position owner.
InvalidAuthorityProvided authority or withdraw authority is invalid or provided token account doesn't belong to authority.
InvalidTickIndexInitial tick not divisible by spacing or outside of size limit or price limit.
InvalidTokenProgramInvalid token program for provided token account.

ClaimFee

Claims fee from the specified position.

pub fn claim_fee(
ctx: Context<ClaimFee>,
_index: u32,
_lower_tick_index: i32,
_upper_tick_index: i32,
) -> Result<()> {
ctx.accounts.handler()
}

Entrypoint Params

NameTypeDescription
indexi32Index of the position from which the fee will be claimed.
lower_tick_indexi32Index of the lower tick for the position.
upper_tick_indexi32Index of the upper tick for the position.

Context

#[derive(Accounts)]
#[instruction(index: u32, lower_tick_index: i32, upper_tick_index: i32)]
pub struct ClaimFee<'info> {
#[account(seeds = [b"statev1".as_ref()], bump = state.load()?.bump)]
pub state: AccountLoader<'info, State>,
#[account(mut,
seeds = [b"poolv1", token_x.key().as_ref(), token_y.key().as_ref(), &pool.load()?.fee.v.to_le_bytes(), &pool.load()?.tick_spacing.to_le_bytes()],
bump = pool.load()?.bump
)]
pub pool: AccountLoader<'info, Pool>,
#[account(mut,
seeds = [b"positionv1",
owner.key().as_ref(),
&index.to_le_bytes()],
bump = position.load()?.bump
)]
pub position: AccountLoader<'info, Position>,
#[account(mut,
seeds = [b"tickv1", pool.key().as_ref(), &lower_tick_index.to_le_bytes()],
bump = lower_tick.load()?.bump,
constraint = lower_tick_index == position.load()?.lower_tick_index @ WrongTick
)]
pub lower_tick: AccountLoader<'info, Tick>,
#[account(mut,
seeds = [b"tickv1", pool.key().as_ref(), &upper_tick_index.to_le_bytes()],
bump = upper_tick.load()?.bump,
constraint = upper_tick_index == position.load()?.upper_tick_index @ WrongTick
)]
pub upper_tick: AccountLoader<'info, Tick>,
pub owner: Signer<'info>,
#[account(constraint = token_x.key() == pool.load()?.token_x @ InvalidTokenAccount, mint::token_program = token_x_program)]
pub token_x: InterfaceAccount<'info, Mint>,
#[account(constraint = token_y.key() == pool.load()?.token_y @ InvalidTokenAccount, mint::token_program = token_y_program)]
pub token_y: InterfaceAccount<'info, Mint>,
#[account(mut,
constraint = account_x.mint == token_x.key() @ InvalidMint,
constraint = &account_x.owner == owner.key @ InvalidOwner,
token::token_program = token_x_program
)]
pub account_x: Box<InterfaceAccount<'info, TokenAccount>>,
#[account(mut,
constraint = account_y.mint == token_y.key() @ InvalidMint,
constraint = &account_y.owner == owner.key @ InvalidOwner,
token::token_program = token_y_program
)]
pub account_y: Box<InterfaceAccount<'info, TokenAccount>>,
#[account(mut,
constraint = reserve_x.mint == token_x.key() @ InvalidMint,
constraint = &reserve_x.owner == program_authority.key @ InvalidAuthority,
constraint = reserve_x.key() == pool.load()?.token_x_reserve @ InvalidTokenAccount,
token::token_program = token_x_program,
)]
pub reserve_x: Box<InterfaceAccount<'info, TokenAccount>>,
#[account(mut,
constraint = reserve_y.mint == token_y.key() @ InvalidMint,
constraint = &reserve_y.owner == program_authority.key @ InvalidAuthority,
constraint = reserve_y.key() == pool.load()?.token_y_reserve @ InvalidTokenAccount,
token::token_program = token_y_program,
)]
pub reserve_y: Box<InterfaceAccount<'info, TokenAccount>>,
#[account(constraint = &state.load()?.authority == program_authority.key @ InvalidAuthority)]
/// CHECK: ignore
pub program_authority: AccountInfo<'info>,

#[account(constraint = token_x_program.key() == token::ID || token_x_program.key() == token_2022::ID)]
pub token_x_program: Interface<'info, TokenInterface>,
#[account(constraint = token_y_program.key() == token::ID || token_y_program.key() == token_2022::ID)]
pub token_y_program: Interface<'info, TokenInterface>,
}

Context Params

NameTypeDescription
indexi32Index of the position from which the fee will be claimed.
lower_tick_indexi32Index of the lower tick for the position.
upper_tick_indexi32Index of the upper tick for the position.

Accounts

NameTypeDescription
stateStateAccount of the protocols state.
poolPoolAccount of the pool on which the position exists.
positionPositionPosition to claim fee from.
lower_tickTickLower tick account for the position.
upper_tickTickUpper tick account for the position.
token_x_programTokenInterfaceToken X associated program account.
token_y_programTokenInterfaceToken Y associated program account.
reserve_xTokenAccountPool's token X associated token account.
reserve_yTokenAccountPool's token Y associated token account.
account_xTokenAccountUsers's token X associated token account.
account_yTokenAccountUsers's token Y associated token account.
token_xMintToken X mint account.
token_yMintToken Y mint account.
ownerSignerAccount of transaction signer, must be the position owner.
program_authorityAccountInfoProtocol authority account.

Errors

CodeDescription
WrongTickTick account doesn't match the tick index on the position.
InvalidTokenAccountProvided token mint is incorrect or reserve account doesn't match pool reserves.
InvalidMintProvided token accounts mint doesn't match provided mint.
InvalidOwnerProvided token account doesn't belong to position owner.
InvalidAuthorityProvided authority is invalid or provided token account doesn't belong to authority.
InvalidTickIndexInitial tick not divisible by spacing or outside of size limit or price limit.
InvalidTokenProgramInvalid token program for provided token account.

ChangeFeeReceiver

Changes the receiver of the protocol fee for a pool. Admin only.

#[access_control(admin(&ctx.accounts.state, &ctx.accounts.admin))]
pub fn change_fee_receiver(ctx: Context<ChangeFeeReceiver>) -> Result<()> {
ctx.accounts.handler()
}

Context

#[derive(Accounts)]
pub struct ChangeFeeReceiver<'info> {
#[account(seeds = [b"statev1".as_ref()], bump = state.load()?.bump)]
pub state: AccountLoader<'info, State>,
#[account(mut,
seeds = [b"poolv1", token_x.to_account_info().key.as_ref(), token_y.to_account_info().key.as_ref(), &pool.load()?.fee.v.to_le_bytes(), &pool.load()?.tick_spacing.to_le_bytes()],
bump = pool.load()?.bump
)]
pub pool: AccountLoader<'info, Pool>,
#[account(constraint = token_x.to_account_info().key == &pool.load()?.token_x @ InvalidTokenAccount) ]
pub token_x: InterfaceAccount<'info, Mint>,
#[account(constraint = token_y.to_account_info().key == &pool.load()?.token_y @ InvalidTokenAccount)]
pub token_y: InterfaceAccount<'info, Mint>,
#[account(constraint = &state.load()?.admin == admin.key @ InvalidAdmin)]
pub admin: Signer<'info>,
/// CHECK: Ignore
pub fee_receiver: AccountInfo<'info>,
}

Accounts

NameTypeDescription
stateStateAccount of the protocols state.
poolPoolAccount of the pool on which the fee receiver will be changed.
token_xMintToken X mint account.
token_yMintToken Y mint account.
adminSignerAccount of transaction signer, must be admin.
fee_receiverAccountInfoAccount that will be authorized to receive the protocol fee from the pool.

Errors

CodeDescription
InvalidTokenAccountProvided token account does not belong to the expected token.
InvalidAdminProvided admin is invalid.

ChangeProtocolFee

Changes the protocol fee for a pool. Admin only.

    #[access_control(receiver(&ctx.accounts.pool, &ctx.accounts.admin))]
pub fn change_protocol_fee(
ctx: Context<ChangeProtocolFee>,
protocol_fee: FixedPoint,
) -> Result<()> {
ctx.accounts.handler(protocol_fee)
}

Entrypoint Params

NameTypeDescription
protocol_feeFixedPointNew value of the protocol fee.

Context

#[derive(Accounts)]
pub struct ChangeProtocolFee<'info> {
#[account(seeds = [b"statev1".as_ref()], bump = state.load()?.bump )]
pub state: AccountLoader<'info, State>,
#[account(mut,
seeds = [b"poolv1", token_x.to_account_info().key.as_ref(), token_y.to_account_info().key.as_ref(), &pool.load()?.fee.v.to_le_bytes(), &pool.load()?.tick_spacing.to_le_bytes()],
bump = pool.load()?.bump
)]
pub pool: AccountLoader<'info, Pool>,
#[account(constraint = token_x.to_account_info().key == &pool.load()?.token_x @ InvalidTokenAccount) ]
pub token_x: InterfaceAccount<'info, Mint>,
#[account(constraint = token_y.to_account_info().key == &pool.load()?.token_y @ InvalidTokenAccount)]
pub token_y: InterfaceAccount<'info, Mint>,
#[account(constraint = &state.load()?.admin == admin.key @ InvalidAdmin)]
pub admin: Signer<'info>,
#[account(constraint = &state.load()?.authority == program_authority.key @ InvalidAuthority)]
/// CHECK: Ignore
pub program_authority: AccountInfo<'info>,
}

Accounts

NameTypeDescription
stateStateAccount of the protocols state.
poolPoolAccount of the pool for which the protocol fee will change.
token_xMintToken X mint account.
token_yMintToken Y mint account.
adminSignerAccount of transaction signer, must be admin.
program_authorityAccountInfoProgram authority account.

Errors

CodeDescription
InvalidTokenAccountProvided token account does not belong to the expected token.
InvalidAuthorityProvided authority is invalid.
InvalidAdminProvided admin is invalid.
InvalidProtocolFeeProtocol fee is outside acceptable range (10^12 - 0).

InitializeOracle

Initialize oracle for the pool. Oracles don't work yet.

pub fn initialize_oracle(ctx: Context<InitializeOracle>) -> Result<()> {
ctx.accounts.handler()
}

Context

#[derive(Accounts)]
pub struct InitializeOracle<'info> {
#[account(mut,
seeds = [b"poolv1", token_x.key().as_ref(), token_y.key().as_ref(), &pool.load()?.fee.v.to_le_bytes(), &pool.load()?.tick_spacing.to_le_bytes()],
bump = pool.load()?.bump
)]
pub pool: AccountLoader<'info, Pool>,
#[account(zero)]
pub oracle: AccountLoader<'info, Oracle>,
#[account(constraint = token_x.key() == pool.load()?.token_x @ InvalidTokenAccount)]
pub token_x: Box<InterfaceAccount<'info, Mint>>,
#[account(constraint = token_y.key() == pool.load()?.token_y @ InvalidTokenAccount)]
pub token_y: Box<InterfaceAccount<'info, Mint>>,
pub payer: Signer<'info>,
pub rent: Sysvar<'info, Rent>,
#[account(address = system_program::ID)]
/// CHECK: Ignore
pub system_program: AccountInfo<'info>,
}

Accounts

NameTypeDescription
poolPoolAccount of the pool for which the oracle will be initialized.
oracleOracleOracle that will be initialized.
token_xMintToken X mint account.
token_yMintToken Y mint account.
payerSignerAccount of transaction signer.
rentSysvar<'info, Rent>System rent account.
system_programAccountInfoSolana system program.

Errors

CodeDescription
OracleAlreadyInitializedOracle was already initialized.
InvalidTokenAccountMint account address doesn't match the pool tokens.