RegisterToken: Pass token_index explicitly
This guarantees stability when a gov proposal adds a new token and a new market in one transaction. This way the RegisterMarket instruction knows exactly what index the new token will have. Previously, the new token index was generated automatically, meaning you couldn't be sure what index a new token would get in advance.
This commit is contained in:
parent
2502f0ac1b
commit
1cd0f8d6be
|
@ -19,7 +19,8 @@ pub struct Deposit<'info> {
|
||||||
mut,
|
mut,
|
||||||
has_one = group,
|
has_one = group,
|
||||||
has_one = vault,
|
has_one = vault,
|
||||||
constraint = bank.load()?.mint == token_account.mint,
|
// the mints of bank/vault/token_account are implicitly the same because
|
||||||
|
// spl::token::transfer succeeds between token_account and vault
|
||||||
)]
|
)]
|
||||||
pub bank: AccountLoader<'info, Bank>,
|
pub bank: AccountLoader<'info, Bank>,
|
||||||
|
|
||||||
|
@ -49,10 +50,7 @@ impl<'info> Deposit<'info> {
|
||||||
// That would save a lot of computation that needs to go into finding the
|
// That would save a lot of computation that needs to go into finding the
|
||||||
// right index for the mint.
|
// right index for the mint.
|
||||||
pub fn deposit(ctx: Context<Deposit>, amount: u64) -> Result<()> {
|
pub fn deposit(ctx: Context<Deposit>, amount: u64) -> Result<()> {
|
||||||
// Find the mint's token index
|
let token_index = ctx.accounts.bank.load()?.token_index as usize;
|
||||||
let group = ctx.accounts.group.load()?;
|
|
||||||
let mint = ctx.accounts.token_account.mint;
|
|
||||||
let token_index = group.tokens.index_for_mint(&mint)?;
|
|
||||||
|
|
||||||
// Get the account's position for that token index
|
// Get the account's position for that token index
|
||||||
let mut account = ctx.accounts.account.load_mut()?;
|
let mut account = ctx.accounts.account.load_mut()?;
|
||||||
|
|
|
@ -2,6 +2,7 @@ use anchor_lang::prelude::*;
|
||||||
use anchor_spl::dex;
|
use anchor_spl::dex;
|
||||||
use anchor_spl::token::{Token, TokenAccount};
|
use anchor_spl::token::{Token, TokenAccount};
|
||||||
use dex::serum_dex;
|
use dex::serum_dex;
|
||||||
|
use serum_dex::matching::Side;
|
||||||
|
|
||||||
use crate::error::*;
|
use crate::error::*;
|
||||||
use crate::state::*;
|
use crate::state::*;
|
||||||
|
@ -49,7 +50,8 @@ pub struct PlaceSerumOrder<'info> {
|
||||||
#[account(mut)]
|
#[account(mut)]
|
||||||
pub market_quote_vault: UncheckedAccount<'info>,
|
pub market_quote_vault: UncheckedAccount<'info>,
|
||||||
|
|
||||||
// TODO: everything
|
// TODO: everything; do we need to pass both, or just payer?
|
||||||
|
// these are all potentially mut too, if we settle immediately?
|
||||||
pub quote_bank: AccountLoader<'info, Bank>,
|
pub quote_bank: AccountLoader<'info, Bank>,
|
||||||
pub quote_vault: Account<'info, TokenAccount>,
|
pub quote_vault: Account<'info, TokenAccount>,
|
||||||
pub base_bank: AccountLoader<'info, Bank>,
|
pub base_bank: AccountLoader<'info, Bank>,
|
||||||
|
@ -63,6 +65,11 @@ pub fn place_serum_order(
|
||||||
ctx: Context<PlaceSerumOrder>,
|
ctx: Context<PlaceSerumOrder>,
|
||||||
order: serum_dex::instruction::NewOrderInstructionV3,
|
order: serum_dex::instruction::NewOrderInstructionV3,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
let order_payer_token_account = match order.side {
|
||||||
|
Side::Ask => ctx.accounts.base_vault.to_account_info(),
|
||||||
|
Side::Bid => ctx.accounts.quote_vault.to_account_info(),
|
||||||
|
};
|
||||||
|
|
||||||
let context = CpiContext::new(
|
let context = CpiContext::new(
|
||||||
ctx.accounts.serum_program.to_account_info(),
|
ctx.accounts.serum_program.to_account_info(),
|
||||||
dex::NewOrderV3 {
|
dex::NewOrderV3 {
|
||||||
|
@ -80,8 +87,7 @@ pub fn place_serum_order(
|
||||||
// user accounts
|
// user accounts
|
||||||
open_orders: ctx.accounts.open_orders.to_account_info(),
|
open_orders: ctx.accounts.open_orders.to_account_info(),
|
||||||
open_orders_authority: ctx.accounts.serum_market.to_account_info(),
|
open_orders_authority: ctx.accounts.serum_market.to_account_info(),
|
||||||
// TODO: vary based on bid or ask
|
order_payer_token_account,
|
||||||
order_payer_token_account: ctx.accounts.quote_vault.to_account_info(),
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ use crate::state::*;
|
||||||
const INDEX_START: I80F48 = I80F48!(1_000_000);
|
const INDEX_START: I80F48 = I80F48!(1_000_000);
|
||||||
|
|
||||||
#[derive(Accounts)]
|
#[derive(Accounts)]
|
||||||
|
#[instruction(token_index: TokenIndex)]
|
||||||
pub struct RegisterToken<'info> {
|
pub struct RegisterToken<'info> {
|
||||||
#[account(
|
#[account(
|
||||||
mut,
|
mut,
|
||||||
|
@ -24,7 +25,7 @@ pub struct RegisterToken<'info> {
|
||||||
|
|
||||||
#[account(
|
#[account(
|
||||||
init,
|
init,
|
||||||
seeds = [group.key().as_ref(), b"TokenBank".as_ref(), mint.key().as_ref()],
|
seeds = [group.key().as_ref(), b"TokenBank".as_ref(), &token_index.to_le_bytes()],
|
||||||
bump,
|
bump,
|
||||||
payer = payer,
|
payer = payer,
|
||||||
space = 8 + std::mem::size_of::<Bank>(),
|
space = 8 + std::mem::size_of::<Bank>(),
|
||||||
|
@ -33,7 +34,7 @@ pub struct RegisterToken<'info> {
|
||||||
|
|
||||||
#[account(
|
#[account(
|
||||||
init,
|
init,
|
||||||
seeds = [group.key().as_ref(), b"TokenVault".as_ref(), mint.key().as_ref()],
|
seeds = [group.key().as_ref(), b"TokenVault".as_ref(), &token_index.to_le_bytes()],
|
||||||
bump,
|
bump,
|
||||||
token::authority = group,
|
token::authority = group,
|
||||||
token::mint = mint,
|
token::mint = mint,
|
||||||
|
@ -74,6 +75,7 @@ pub struct RegisterToken<'info> {
|
||||||
// overwriting config as long as the mint account stays the same?
|
// overwriting config as long as the mint account stays the same?
|
||||||
pub fn register_token(
|
pub fn register_token(
|
||||||
ctx: Context<RegisterToken>,
|
ctx: Context<RegisterToken>,
|
||||||
|
token_index: TokenIndex,
|
||||||
decimals: u8,
|
decimals: u8,
|
||||||
maint_asset_weight: f32,
|
maint_asset_weight: f32,
|
||||||
init_asset_weight: f32,
|
init_asset_weight: f32,
|
||||||
|
@ -82,15 +84,7 @@ pub fn register_token(
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let mut group = ctx.accounts.group.load_mut()?;
|
let mut group = ctx.accounts.group.load_mut()?;
|
||||||
// TODO: Error if mint is already configured (techincally, init of vault will fail)
|
// TODO: Error if mint is already configured (techincally, init of vault will fail)
|
||||||
// TOOD: Error type
|
group.tokens.infos[token_index as usize] = TokenInfo {
|
||||||
// TODO: Should be a function: Tokens::add() or so
|
|
||||||
let token_index = group
|
|
||||||
.tokens
|
|
||||||
.infos
|
|
||||||
.iter()
|
|
||||||
.position(|ti| !ti.is_valid())
|
|
||||||
.ok_or(MangoError::SomeError)?;
|
|
||||||
group.tokens.infos[token_index] = TokenInfo {
|
|
||||||
mint: ctx.accounts.mint.key(),
|
mint: ctx.accounts.mint.key(),
|
||||||
decimals,
|
decimals,
|
||||||
bank_bump: *ctx.bumps.get("bank").ok_or(MangoError::SomeError)?, // TODO: error
|
bank_bump: *ctx.bumps.get("bank").ok_or(MangoError::SomeError)?, // TODO: error
|
||||||
|
@ -113,7 +107,7 @@ pub fn register_token(
|
||||||
maint_liab_weight: I80F48::from_num(maint_liab_weight),
|
maint_liab_weight: I80F48::from_num(maint_liab_weight),
|
||||||
init_liab_weight: I80F48::from_num(init_liab_weight),
|
init_liab_weight: I80F48::from_num(init_liab_weight),
|
||||||
dust: I80F48::ZERO,
|
dust: I80F48::ZERO,
|
||||||
token_index: token_index as TokenIndex,
|
token_index,
|
||||||
};
|
};
|
||||||
|
|
||||||
let alt_previous_size =
|
let alt_previous_size =
|
||||||
|
@ -126,6 +120,7 @@ pub fn register_token(
|
||||||
vault: ctx.accounts.vault.key(),
|
vault: ctx.accounts.vault.key(),
|
||||||
oracle: ctx.accounts.oracle.key(),
|
oracle: ctx.accounts.oracle.key(),
|
||||||
bank: ctx.accounts.bank.key(),
|
bank: ctx.accounts.bank.key(),
|
||||||
|
token_index,
|
||||||
address_lookup_table: ctx.accounts.address_lookup_table.key(),
|
address_lookup_table: ctx.accounts.address_lookup_table.key(),
|
||||||
address_lookup_table_bank_index: alt_previous_size as u8,
|
address_lookup_table_bank_index: alt_previous_size as u8,
|
||||||
address_lookup_table_oracle_index: alt_previous_size as u8 + 1,
|
address_lookup_table_oracle_index: alt_previous_size as u8 + 1,
|
||||||
|
|
|
@ -22,7 +22,8 @@ pub struct Withdraw<'info> {
|
||||||
mut,
|
mut,
|
||||||
has_one = group,
|
has_one = group,
|
||||||
has_one = vault,
|
has_one = vault,
|
||||||
constraint = bank.load()?.mint == token_account.mint,
|
// the mints of bank/vault/token_account are implicitly the same because
|
||||||
|
// spl::token::transfer succeeds between token_account and vault
|
||||||
)]
|
)]
|
||||||
pub bank: AccountLoader<'info, Bank>,
|
pub bank: AccountLoader<'info, Bank>,
|
||||||
|
|
||||||
|
@ -51,10 +52,10 @@ impl<'info> Withdraw<'info> {
|
||||||
// That would save a lot of computation that needs to go into finding the
|
// That would save a lot of computation that needs to go into finding the
|
||||||
// right index for the mint.
|
// right index for the mint.
|
||||||
pub fn withdraw(ctx: Context<Withdraw>, amount: u64, allow_borrow: bool) -> Result<()> {
|
pub fn withdraw(ctx: Context<Withdraw>, amount: u64, allow_borrow: bool) -> Result<()> {
|
||||||
// Find the mint's token index
|
|
||||||
let group = ctx.accounts.group.load()?;
|
let group = ctx.accounts.group.load()?;
|
||||||
let mint = ctx.accounts.token_account.mint;
|
|
||||||
let token_index = group.tokens.index_for_mint(&mint)?;
|
// Find the mint's token index
|
||||||
|
let token_index = ctx.accounts.bank.load()?.token_index as usize;
|
||||||
|
|
||||||
// Get the account's position for that token index
|
// Get the account's position for that token index
|
||||||
let mut account = ctx.accounts.account.load_mut()?;
|
let mut account = ctx.accounts.account.load_mut()?;
|
||||||
|
|
|
@ -28,6 +28,7 @@ pub mod mango_v4 {
|
||||||
|
|
||||||
pub fn register_token(
|
pub fn register_token(
|
||||||
ctx: Context<RegisterToken>,
|
ctx: Context<RegisterToken>,
|
||||||
|
token_index: TokenIndex,
|
||||||
decimals: u8,
|
decimals: u8,
|
||||||
maint_asset_weight: f32,
|
maint_asset_weight: f32,
|
||||||
init_asset_weight: f32,
|
init_asset_weight: f32,
|
||||||
|
@ -36,6 +37,7 @@ pub mod mango_v4 {
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
instructions::register_token(
|
instructions::register_token(
|
||||||
ctx,
|
ctx,
|
||||||
|
token_index,
|
||||||
decimals,
|
decimals,
|
||||||
maint_asset_weight,
|
maint_asset_weight,
|
||||||
init_asset_weight,
|
init_asset_weight,
|
||||||
|
|
|
@ -132,12 +132,7 @@ impl SerumOpenOrdersMap {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create(&mut self, market_index: SerumMarketIndex) -> Result<&mut SerumOpenOrders> {
|
pub fn create(&mut self, market_index: SerumMarketIndex) -> Result<&mut SerumOpenOrders> {
|
||||||
if self
|
if self.find(market_index).is_some() {
|
||||||
.values
|
|
||||||
.iter()
|
|
||||||
.find(|p| p.is_active_for_market(market_index))
|
|
||||||
.is_some()
|
|
||||||
{
|
|
||||||
return err!(MangoError::SomeError); // exists already
|
return err!(MangoError::SomeError); // exists already
|
||||||
}
|
}
|
||||||
if let Some(v) = self.values.iter_mut().find(|p| !p.is_active()) {
|
if let Some(v) = self.values.iter_mut().find(|p| !p.is_active()) {
|
||||||
|
@ -158,6 +153,12 @@ impl SerumOpenOrdersMap {
|
||||||
pub fn iter_active(&self) -> impl Iterator<Item = &SerumOpenOrders> {
|
pub fn iter_active(&self) -> impl Iterator<Item = &SerumOpenOrders> {
|
||||||
self.values.iter().filter(|p| p.is_active())
|
self.values.iter().filter(|p| p.is_active())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn find(&self, market_index: SerumMarketIndex) -> Option<&SerumOpenOrders> {
|
||||||
|
self.values
|
||||||
|
.iter()
|
||||||
|
.find(|p| p.is_active_for_market(market_index))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[account(zero_copy)]
|
#[account(zero_copy)]
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
use anchor_lang::prelude::*;
|
use anchor_lang::prelude::*;
|
||||||
|
|
||||||
|
use super::TokenIndex;
|
||||||
|
|
||||||
// This struct describes which address lookup table can be used to pass
|
// This struct describes which address lookup table can be used to pass
|
||||||
// the accounts that are relevant for this mint. The idea is that clients
|
// the accounts that are relevant for this mint. The idea is that clients
|
||||||
// can load this account to figure out which address maps to use when calling
|
// can load this account to figure out which address maps to use when calling
|
||||||
|
@ -11,6 +13,7 @@ pub struct MintInfo {
|
||||||
pub bank: Pubkey,
|
pub bank: Pubkey,
|
||||||
pub vault: Pubkey,
|
pub vault: Pubkey,
|
||||||
pub oracle: Pubkey,
|
pub oracle: Pubkey,
|
||||||
|
pub token_index: TokenIndex,
|
||||||
|
|
||||||
// describe what address map relevant accounts are found on
|
// describe what address map relevant accounts are found on
|
||||||
pub address_lookup_table: Pubkey,
|
pub address_lookup_table: Pubkey,
|
||||||
|
|
|
@ -234,30 +234,21 @@ impl<'keypair> ClientInstruction for WithdrawInstruction<'keypair> {
|
||||||
// load accounts, find PDAs, find remainingAccounts
|
// load accounts, find PDAs, find remainingAccounts
|
||||||
let token_account: TokenAccount = account_loader.load(&self.token_account).await.unwrap();
|
let token_account: TokenAccount = account_loader.load(&self.token_account).await.unwrap();
|
||||||
let account: MangoAccount = account_loader.load(&self.account).await.unwrap();
|
let account: MangoAccount = account_loader.load(&self.account).await.unwrap();
|
||||||
|
let mint_info = Pubkey::find_program_address(
|
||||||
let bank = Pubkey::find_program_address(
|
|
||||||
&[
|
&[
|
||||||
account.group.as_ref(),
|
account.group.as_ref(),
|
||||||
b"TokenBank".as_ref(),
|
b"MintInfo".as_ref(),
|
||||||
token_account.mint.as_ref(),
|
|
||||||
],
|
|
||||||
&program_id,
|
|
||||||
)
|
|
||||||
.0;
|
|
||||||
let vault = Pubkey::find_program_address(
|
|
||||||
&[
|
|
||||||
account.group.as_ref(),
|
|
||||||
b"TokenVault".as_ref(),
|
|
||||||
token_account.mint.as_ref(),
|
token_account.mint.as_ref(),
|
||||||
],
|
],
|
||||||
&program_id,
|
&program_id,
|
||||||
)
|
)
|
||||||
.0;
|
.0;
|
||||||
|
let mint_info: MintInfo = account_loader.load(&mint_info).await.unwrap();
|
||||||
|
|
||||||
let health_check_metas = derive_health_check_remaining_account_metas(
|
let health_check_metas = derive_health_check_remaining_account_metas(
|
||||||
&account_loader,
|
&account_loader,
|
||||||
&account,
|
&account,
|
||||||
Some(bank),
|
Some(mint_info.bank),
|
||||||
false,
|
false,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
@ -266,8 +257,8 @@ impl<'keypair> ClientInstruction for WithdrawInstruction<'keypair> {
|
||||||
group: account.group,
|
group: account.group,
|
||||||
account: self.account,
|
account: self.account,
|
||||||
owner: self.owner.pubkey(),
|
owner: self.owner.pubkey(),
|
||||||
bank,
|
bank: mint_info.bank,
|
||||||
vault,
|
vault: mint_info.vault,
|
||||||
token_account: self.token_account,
|
token_account: self.token_account,
|
||||||
token_program: Token::id(),
|
token_program: Token::id(),
|
||||||
};
|
};
|
||||||
|
@ -306,30 +297,21 @@ impl<'keypair> ClientInstruction for DepositInstruction<'keypair> {
|
||||||
// load account so we know its mint
|
// load account so we know its mint
|
||||||
let token_account: TokenAccount = account_loader.load(&self.token_account).await.unwrap();
|
let token_account: TokenAccount = account_loader.load(&self.token_account).await.unwrap();
|
||||||
let account: MangoAccount = account_loader.load(&self.account).await.unwrap();
|
let account: MangoAccount = account_loader.load(&self.account).await.unwrap();
|
||||||
|
let mint_info = Pubkey::find_program_address(
|
||||||
let bank = Pubkey::find_program_address(
|
|
||||||
&[
|
&[
|
||||||
account.group.as_ref(),
|
account.group.as_ref(),
|
||||||
b"TokenBank".as_ref(),
|
b"MintInfo".as_ref(),
|
||||||
token_account.mint.as_ref(),
|
|
||||||
],
|
|
||||||
&program_id,
|
|
||||||
)
|
|
||||||
.0;
|
|
||||||
let vault = Pubkey::find_program_address(
|
|
||||||
&[
|
|
||||||
account.group.as_ref(),
|
|
||||||
b"TokenVault".as_ref(),
|
|
||||||
token_account.mint.as_ref(),
|
token_account.mint.as_ref(),
|
||||||
],
|
],
|
||||||
&program_id,
|
&program_id,
|
||||||
)
|
)
|
||||||
.0;
|
.0;
|
||||||
|
let mint_info: MintInfo = account_loader.load(&mint_info).await.unwrap();
|
||||||
|
|
||||||
let health_check_metas = derive_health_check_remaining_account_metas(
|
let health_check_metas = derive_health_check_remaining_account_metas(
|
||||||
&account_loader,
|
&account_loader,
|
||||||
&account,
|
&account,
|
||||||
Some(bank),
|
Some(mint_info.bank),
|
||||||
false,
|
false,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
@ -337,8 +319,8 @@ impl<'keypair> ClientInstruction for DepositInstruction<'keypair> {
|
||||||
let accounts = Self::Accounts {
|
let accounts = Self::Accounts {
|
||||||
group: account.group,
|
group: account.group,
|
||||||
account: self.account,
|
account: self.account,
|
||||||
bank,
|
bank: mint_info.bank,
|
||||||
vault,
|
vault: mint_info.vault,
|
||||||
token_account: self.token_account,
|
token_account: self.token_account,
|
||||||
token_authority: self.token_authority.pubkey(),
|
token_authority: self.token_authority.pubkey(),
|
||||||
token_program: Token::id(),
|
token_program: Token::id(),
|
||||||
|
@ -356,6 +338,7 @@ impl<'keypair> ClientInstruction for DepositInstruction<'keypair> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct RegisterTokenInstruction<'keypair> {
|
pub struct RegisterTokenInstruction<'keypair> {
|
||||||
|
pub token_index: TokenIndex,
|
||||||
pub decimals: u8,
|
pub decimals: u8,
|
||||||
pub maint_asset_weight: f32,
|
pub maint_asset_weight: f32,
|
||||||
pub init_asset_weight: f32,
|
pub init_asset_weight: f32,
|
||||||
|
@ -378,6 +361,7 @@ impl<'keypair> ClientInstruction for RegisterTokenInstruction<'keypair> {
|
||||||
) -> (Self::Accounts, instruction::Instruction) {
|
) -> (Self::Accounts, instruction::Instruction) {
|
||||||
let program_id = mango_v4::id();
|
let program_id = mango_v4::id();
|
||||||
let instruction = Self::Instruction {
|
let instruction = Self::Instruction {
|
||||||
|
token_index: self.token_index,
|
||||||
decimals: self.decimals,
|
decimals: self.decimals,
|
||||||
maint_asset_weight: self.maint_asset_weight,
|
maint_asset_weight: self.maint_asset_weight,
|
||||||
init_asset_weight: self.init_asset_weight,
|
init_asset_weight: self.init_asset_weight,
|
||||||
|
@ -389,7 +373,7 @@ impl<'keypair> ClientInstruction for RegisterTokenInstruction<'keypair> {
|
||||||
&[
|
&[
|
||||||
self.group.as_ref(),
|
self.group.as_ref(),
|
||||||
b"TokenBank".as_ref(),
|
b"TokenBank".as_ref(),
|
||||||
self.mint.as_ref(),
|
&self.token_index.to_le_bytes(),
|
||||||
],
|
],
|
||||||
&program_id,
|
&program_id,
|
||||||
)
|
)
|
||||||
|
@ -398,7 +382,7 @@ impl<'keypair> ClientInstruction for RegisterTokenInstruction<'keypair> {
|
||||||
&[
|
&[
|
||||||
self.group.as_ref(),
|
self.group.as_ref(),
|
||||||
b"TokenVault".as_ref(),
|
b"TokenVault".as_ref(),
|
||||||
self.mint.as_ref(),
|
&self.token_index.to_le_bytes(),
|
||||||
],
|
],
|
||||||
&program_id,
|
&program_id,
|
||||||
)
|
)
|
||||||
|
@ -708,3 +692,46 @@ impl<'keypair> ClientInstruction for CreateSerumOpenOrdersInstruction<'keypair>
|
||||||
vec![self.owner, self.payer]
|
vec![self.owner, self.payer]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
pub struct PlaceSerumOrderInstruction<'keypair> {
|
||||||
|
pub account: Pubkey,
|
||||||
|
pub serum_market: Pubkey,
|
||||||
|
pub owner: &'keypair Keypair,
|
||||||
|
}
|
||||||
|
#[async_trait::async_trait(?Send)]
|
||||||
|
impl<'keypair> ClientInstruction for PlaceSerumOrderInstruction<'keypair> {
|
||||||
|
type Accounts = mango_v4::accounts::PlaceSerumOrder;
|
||||||
|
type Instruction = mango_v4::instruction::PlaceSerumOrder;
|
||||||
|
async fn to_instruction(
|
||||||
|
&self,
|
||||||
|
account_loader: impl ClientAccountLoader + 'async_trait,
|
||||||
|
) -> (Self::Accounts, instruction::Instruction) {
|
||||||
|
let program_id = mango_v4::id();
|
||||||
|
let instruction = Self::Instruction {};
|
||||||
|
|
||||||
|
let account: MangoAccount = account_loader.load(&self.account).await.unwrap();
|
||||||
|
let serum_market: SerumMarket = account_loader.load(&self.serum_market).await.unwrap();
|
||||||
|
let open_orders = account.serum_open_orders_map.find(serum_market.market_index).unwrap().open_orders;
|
||||||
|
|
||||||
|
let accounts = Self::Accounts {
|
||||||
|
group: account.group,
|
||||||
|
account: self.account,
|
||||||
|
open_orders,
|
||||||
|
serum_market: self.serum_market,
|
||||||
|
serum_program: serum_market.serum_program,
|
||||||
|
serum_market_external: serum_market.serum_market_external,
|
||||||
|
owner: self.owner.pubkey(),
|
||||||
|
payer: self.payer.pubkey(),
|
||||||
|
system_program: System::id(),
|
||||||
|
rent: sysvar::rent::Rent::id(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let instruction = make_instruction(program_id, &accounts, instruction);
|
||||||
|
(accounts, instruction)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn signers(&self) -> Vec<&Keypair> {
|
||||||
|
vec![self.owner]
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
|
@ -72,6 +72,7 @@ async fn test_basic() -> Result<(), TransportError> {
|
||||||
let register_token_accounts = send_tx(
|
let register_token_accounts = send_tx(
|
||||||
solana,
|
solana,
|
||||||
RegisterTokenInstruction {
|
RegisterTokenInstruction {
|
||||||
|
token_index: 0,
|
||||||
decimals: mint0.decimals,
|
decimals: mint0.decimals,
|
||||||
maint_asset_weight: 0.9,
|
maint_asset_weight: 0.9,
|
||||||
init_asset_weight: 0.8,
|
init_asset_weight: 0.8,
|
||||||
|
|
|
@ -5,6 +5,7 @@ use solana_program_test::*;
|
||||||
use solana_sdk::signature::Keypair;
|
use solana_sdk::signature::Keypair;
|
||||||
|
|
||||||
use mango_v4::address_lookup_table;
|
use mango_v4::address_lookup_table;
|
||||||
|
use mango_v4::state::*;
|
||||||
use program_test::*;
|
use program_test::*;
|
||||||
|
|
||||||
mod program_test;
|
mod program_test;
|
||||||
|
@ -51,7 +52,7 @@ async fn test_group_address_lookup_tables() -> Result<()> {
|
||||||
// SETUP: Register three mints (and make oracles for them)
|
// SETUP: Register three mints (and make oracles for them)
|
||||||
//
|
//
|
||||||
|
|
||||||
let register_mint = |mint: MintCookie, address_lookup_table: Pubkey| async move {
|
let register_mint = |index: TokenIndex, mint: MintCookie, address_lookup_table: Pubkey| async move {
|
||||||
let create_stub_oracle_accounts = send_tx(
|
let create_stub_oracle_accounts = send_tx(
|
||||||
solana,
|
solana,
|
||||||
CreateStubOracle {
|
CreateStubOracle {
|
||||||
|
@ -75,6 +76,7 @@ async fn test_group_address_lookup_tables() -> Result<()> {
|
||||||
let register_token_accounts = send_tx(
|
let register_token_accounts = send_tx(
|
||||||
solana,
|
solana,
|
||||||
RegisterTokenInstruction {
|
RegisterTokenInstruction {
|
||||||
|
token_index: index,
|
||||||
decimals: mint.decimals,
|
decimals: mint.decimals,
|
||||||
maint_asset_weight: 0.9,
|
maint_asset_weight: 0.9,
|
||||||
init_asset_weight: 0.8,
|
init_asset_weight: 0.8,
|
||||||
|
@ -100,9 +102,9 @@ async fn test_group_address_lookup_tables() -> Result<()> {
|
||||||
solana.advance_by_slots(1).await; // to get a different address
|
solana.advance_by_slots(1).await; // to get a different address
|
||||||
let address_lookup_table2 = solana.create_address_lookup_table(admin, payer).await;
|
let address_lookup_table2 = solana.create_address_lookup_table(admin, payer).await;
|
||||||
|
|
||||||
let (oracle0, bank0) = register_mint(mint0.clone(), address_lookup_table1).await;
|
let (oracle0, bank0) = register_mint(0, mint0.clone(), address_lookup_table1).await;
|
||||||
let (oracle1, bank1) = register_mint(mint1.clone(), address_lookup_table1).await;
|
let (oracle1, bank1) = register_mint(1, mint1.clone(), address_lookup_table1).await;
|
||||||
let (oracle2, bank2) = register_mint(mint2.clone(), address_lookup_table2).await;
|
let (oracle2, bank2) = register_mint(2, mint2.clone(), address_lookup_table2).await;
|
||||||
|
|
||||||
// check the resulting address maps
|
// check the resulting address maps
|
||||||
let data = solana
|
let data = solana
|
||||||
|
|
|
@ -87,6 +87,7 @@ async fn test_margin_trade() -> Result<(), TransportError> {
|
||||||
let register_token_accounts = send_tx(
|
let register_token_accounts = send_tx(
|
||||||
solana,
|
solana,
|
||||||
RegisterTokenInstruction {
|
RegisterTokenInstruction {
|
||||||
|
token_index: 0,
|
||||||
decimals: mint0.decimals,
|
decimals: mint0.decimals,
|
||||||
maint_asset_weight: 0.9,
|
maint_asset_weight: 0.9,
|
||||||
init_asset_weight: 0.8,
|
init_asset_weight: 0.8,
|
||||||
|
|
|
@ -65,7 +65,7 @@ async fn test_position_lifetime() -> Result<()> {
|
||||||
|
|
||||||
let address_lookup_table = solana.create_address_lookup_table(admin, payer).await;
|
let address_lookup_table = solana.create_address_lookup_table(admin, payer).await;
|
||||||
|
|
||||||
let register_mint = |mint: MintCookie| async move {
|
let register_mint = |index: TokenIndex, mint: MintCookie| async move {
|
||||||
let create_stub_oracle_accounts = send_tx(
|
let create_stub_oracle_accounts = send_tx(
|
||||||
solana,
|
solana,
|
||||||
CreateStubOracle {
|
CreateStubOracle {
|
||||||
|
@ -89,6 +89,7 @@ async fn test_position_lifetime() -> Result<()> {
|
||||||
let register_token_accounts = send_tx(
|
let register_token_accounts = send_tx(
|
||||||
solana,
|
solana,
|
||||||
RegisterTokenInstruction {
|
RegisterTokenInstruction {
|
||||||
|
token_index: index,
|
||||||
decimals: mint.decimals,
|
decimals: mint.decimals,
|
||||||
maint_asset_weight: 0.9,
|
maint_asset_weight: 0.9,
|
||||||
init_asset_weight: 0.8,
|
init_asset_weight: 0.8,
|
||||||
|
@ -107,9 +108,9 @@ async fn test_position_lifetime() -> Result<()> {
|
||||||
|
|
||||||
(oracle, bank)
|
(oracle, bank)
|
||||||
};
|
};
|
||||||
register_mint(mint0.clone()).await;
|
register_mint(0, mint0.clone()).await;
|
||||||
register_mint(mint1.clone()).await;
|
register_mint(1, mint1.clone()).await;
|
||||||
register_mint(mint2.clone()).await;
|
register_mint(2, mint2.clone()).await;
|
||||||
|
|
||||||
//
|
//
|
||||||
// SETUP: Put some tokens into the funding account to allow borrowing
|
// SETUP: Put some tokens into the funding account to allow borrowing
|
||||||
|
|
|
@ -51,7 +51,7 @@ async fn test_serum() -> Result<(), TransportError> {
|
||||||
// SETUP: Register mints (and make oracles for them)
|
// SETUP: Register mints (and make oracles for them)
|
||||||
//
|
//
|
||||||
|
|
||||||
let register_mint = |mint: MintCookie, address_lookup_table: Pubkey| async move {
|
let register_mint = |index: TokenIndex, mint: MintCookie, address_lookup_table: Pubkey| async move {
|
||||||
let create_stub_oracle_accounts = send_tx(
|
let create_stub_oracle_accounts = send_tx(
|
||||||
solana,
|
solana,
|
||||||
CreateStubOracle {
|
CreateStubOracle {
|
||||||
|
@ -75,6 +75,7 @@ async fn test_serum() -> Result<(), TransportError> {
|
||||||
let register_token_accounts = send_tx(
|
let register_token_accounts = send_tx(
|
||||||
solana,
|
solana,
|
||||||
RegisterTokenInstruction {
|
RegisterTokenInstruction {
|
||||||
|
token_index: index,
|
||||||
decimals: mint.decimals,
|
decimals: mint.decimals,
|
||||||
maint_asset_weight: 0.9,
|
maint_asset_weight: 0.9,
|
||||||
init_asset_weight: 0.8,
|
init_asset_weight: 0.8,
|
||||||
|
@ -95,8 +96,12 @@ async fn test_serum() -> Result<(), TransportError> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let address_lookup_table = solana.create_address_lookup_table(admin, payer).await;
|
let address_lookup_table = solana.create_address_lookup_table(admin, payer).await;
|
||||||
let (_oracle0, _bank0) = register_mint(mint0.clone(), address_lookup_table).await;
|
let base_token_index = 0;
|
||||||
let (_oracle1, _bank1) = register_mint(mint1.clone(), address_lookup_table).await;
|
let (_oracle0, _bank0) =
|
||||||
|
register_mint(base_token_index, mint0.clone(), address_lookup_table).await;
|
||||||
|
let quote_token_index = 1;
|
||||||
|
let (_oracle1, _bank1) =
|
||||||
|
register_mint(quote_token_index, mint1.clone(), address_lookup_table).await;
|
||||||
|
|
||||||
//
|
//
|
||||||
// TEST: Register a serum market
|
// TEST: Register a serum market
|
||||||
|
@ -108,8 +113,8 @@ async fn test_serum() -> Result<(), TransportError> {
|
||||||
admin,
|
admin,
|
||||||
serum_program: context.serum.program_id,
|
serum_program: context.serum.program_id,
|
||||||
serum_market_external: serum_market_cookie.market,
|
serum_market_external: serum_market_cookie.market,
|
||||||
base_token_index: 0, // TODO: better way of getting these numbers
|
base_token_index,
|
||||||
quote_token_index: 1,
|
quote_token_index,
|
||||||
payer,
|
payer,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue