Merge pull request #33 from blockworks-foundation/mc/stub-oracle-ext
Mc/stub oracle ext
This commit is contained in:
commit
884d638e36
|
@ -6,15 +6,22 @@ use crate::state::*;
|
|||
|
||||
#[derive(Accounts)]
|
||||
pub struct CreateStubOracle<'info> {
|
||||
#[account(
|
||||
has_one = admin,
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>,
|
||||
|
||||
#[account(
|
||||
init,
|
||||
seeds = [b"StubOracle".as_ref(), token_mint.key().as_ref()],
|
||||
seeds = [group.key().as_ref(), b"StubOracle".as_ref(), token_mint.key().as_ref()],
|
||||
bump,
|
||||
payer = payer,
|
||||
space = 8 + std::mem::size_of::<StubOracle>(),
|
||||
)]
|
||||
pub oracle: AccountLoader<'info, StubOracle>,
|
||||
|
||||
pub admin: Signer<'info>,
|
||||
|
||||
pub token_mint: Account<'info, Mint>,
|
||||
|
||||
#[account(mut)]
|
||||
|
@ -25,6 +32,7 @@ pub struct CreateStubOracle<'info> {
|
|||
|
||||
pub fn create_stub_oracle(ctx: Context<CreateStubOracle>, price: I80F48) -> Result<()> {
|
||||
let mut oracle = ctx.accounts.oracle.load_init()?;
|
||||
oracle.group = ctx.accounts.group.key();
|
||||
oracle.price = price;
|
||||
oracle.last_updated = Clock::get()?.unix_timestamp;
|
||||
|
||||
|
|
|
@ -5,8 +5,21 @@ use crate::state::*;
|
|||
|
||||
#[derive(Accounts)]
|
||||
pub struct SetStubOracle<'info> {
|
||||
#[account(mut)]
|
||||
#[account(
|
||||
has_one = admin,
|
||||
)]
|
||||
pub group: AccountLoader<'info, Group>,
|
||||
|
||||
pub admin: Signer<'info>,
|
||||
|
||||
#[account(
|
||||
mut,
|
||||
has_one = group
|
||||
)]
|
||||
pub oracle: AccountLoader<'info, StubOracle>,
|
||||
|
||||
#[account(mut)]
|
||||
pub payer: Signer<'info>,
|
||||
}
|
||||
|
||||
// TODO: add admin requirement for changing price
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
use std::mem::size_of;
|
||||
|
||||
use anchor_lang::prelude::*;
|
||||
use anchor_lang::Discriminator;
|
||||
use fixed::types::I80F48;
|
||||
use static_assertions::const_assert_eq;
|
||||
|
||||
use crate::error::MangoError;
|
||||
use crate::util::LoadZeroCopy;
|
||||
|
@ -13,9 +16,13 @@ pub enum OracleType {
|
|||
|
||||
#[account(zero_copy)]
|
||||
pub struct StubOracle {
|
||||
pub group: Pubkey,
|
||||
pub price: I80F48,
|
||||
pub last_updated: i64,
|
||||
pub reserved: [u8; 8],
|
||||
}
|
||||
const_assert_eq!(size_of::<StubOracle>(), 32 + 16 + 8 + 8);
|
||||
const_assert_eq!(size_of::<StubOracle>() % 8, 0);
|
||||
|
||||
pub fn determine_oracle_type(data: &[u8]) -> Result<OracleType> {
|
||||
if u32::from_le_bytes(data[0..4].try_into().unwrap()) == pyth_client::MAGIC {
|
||||
|
|
|
@ -503,7 +503,11 @@ impl<'keypair> ClientInstruction for RegisterTokenInstruction<'keypair> {
|
|||
.0;
|
||||
// TODO: remove copy pasta of pda derivation, use reference
|
||||
let oracle = Pubkey::find_program_address(
|
||||
&[b"StubOracle".as_ref(), self.mint.as_ref()],
|
||||
&[
|
||||
self.group.as_ref(),
|
||||
b"StubOracle".as_ref(),
|
||||
self.mint.as_ref(),
|
||||
],
|
||||
&program_id,
|
||||
)
|
||||
.0;
|
||||
|
@ -537,6 +541,8 @@ impl<'keypair> ClientInstruction for RegisterTokenInstruction<'keypair> {
|
|||
|
||||
pub struct SetStubOracle<'keypair> {
|
||||
pub mint: Pubkey,
|
||||
pub group: Pubkey,
|
||||
pub admin: &'keypair Keypair,
|
||||
pub payer: &'keypair Keypair,
|
||||
pub price: &'static str,
|
||||
}
|
||||
|
@ -555,24 +561,35 @@ impl<'keypair> ClientInstruction for SetStubOracle<'keypair> {
|
|||
};
|
||||
// TODO: remove copy pasta of pda derivation, use reference
|
||||
let oracle = Pubkey::find_program_address(
|
||||
&[b"StubOracle".as_ref(), self.mint.as_ref()],
|
||||
&[
|
||||
self.group.as_ref(),
|
||||
b"StubOracle".as_ref(),
|
||||
self.mint.as_ref(),
|
||||
],
|
||||
&program_id,
|
||||
)
|
||||
.0;
|
||||
|
||||
let accounts = Self::Accounts { oracle };
|
||||
let accounts = Self::Accounts {
|
||||
oracle,
|
||||
group: self.group,
|
||||
admin: self.admin.pubkey(),
|
||||
payer: self.payer.pubkey(),
|
||||
};
|
||||
|
||||
let instruction = make_instruction(program_id, &accounts, instruction);
|
||||
(accounts, instruction)
|
||||
}
|
||||
|
||||
fn signers(&self) -> Vec<&Keypair> {
|
||||
vec![]
|
||||
vec![self.payer, self.admin]
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CreateStubOracle<'keypair> {
|
||||
pub group: Pubkey,
|
||||
pub mint: Pubkey,
|
||||
pub admin: &'keypair Keypair,
|
||||
pub payer: &'keypair Keypair,
|
||||
}
|
||||
#[async_trait::async_trait(?Send)]
|
||||
|
@ -590,14 +607,20 @@ impl<'keypair> ClientInstruction for CreateStubOracle<'keypair> {
|
|||
};
|
||||
|
||||
let oracle = Pubkey::find_program_address(
|
||||
&[b"StubOracle".as_ref(), self.mint.as_ref()],
|
||||
&[
|
||||
self.group.as_ref(),
|
||||
b"StubOracle".as_ref(),
|
||||
self.mint.as_ref(),
|
||||
],
|
||||
&program_id,
|
||||
)
|
||||
.0;
|
||||
|
||||
let accounts = Self::Accounts {
|
||||
group: self.group,
|
||||
oracle,
|
||||
token_mint: self.mint,
|
||||
admin: self.admin.pubkey(),
|
||||
payer: self.payer.pubkey(),
|
||||
system_program: System::id(),
|
||||
};
|
||||
|
@ -607,7 +630,7 @@ impl<'keypair> ClientInstruction for CreateStubOracle<'keypair> {
|
|||
}
|
||||
|
||||
fn signers(&self) -> Vec<&Keypair> {
|
||||
vec![self.payer]
|
||||
vec![self.payer, self.admin]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,9 @@ impl<'a> GroupWithTokensConfig<'a> {
|
|||
let create_stub_oracle_accounts = send_tx(
|
||||
solana,
|
||||
CreateStubOracle {
|
||||
group,
|
||||
mint: mint.pubkey,
|
||||
admin,
|
||||
payer,
|
||||
},
|
||||
)
|
||||
|
@ -55,6 +57,8 @@ impl<'a> GroupWithTokensConfig<'a> {
|
|||
send_tx(
|
||||
solana,
|
||||
SetStubOracle {
|
||||
group,
|
||||
admin,
|
||||
mint: mint.pubkey,
|
||||
payer,
|
||||
price: "1.0",
|
||||
|
|
|
@ -67,6 +67,8 @@ async fn test_group_address_lookup_tables() -> Result<()> {
|
|||
send_tx(
|
||||
solana,
|
||||
SetStubOracle {
|
||||
group,
|
||||
admin,
|
||||
mint: mint.pubkey,
|
||||
payer,
|
||||
price: "1.0",
|
||||
|
|
|
@ -160,6 +160,8 @@ async fn test_liq_tokens_force_cancel() -> Result<(), TransportError> {
|
|||
send_tx(
|
||||
solana,
|
||||
SetStubOracle {
|
||||
group,
|
||||
admin,
|
||||
mint: base_token.mint.pubkey,
|
||||
payer,
|
||||
price: "10.0",
|
||||
|
@ -341,6 +343,8 @@ async fn test_liq_tokens_with_token() -> Result<(), TransportError> {
|
|||
send_tx(
|
||||
solana,
|
||||
SetStubOracle {
|
||||
group,
|
||||
admin,
|
||||
mint: borrow_token1.mint.pubkey,
|
||||
payer,
|
||||
price: "2.0",
|
||||
|
|
|
@ -66,10 +66,14 @@ async function main() {
|
|||
const usdcDevnetMint = new PublicKey(
|
||||
'8FRFC6MoGGkMFQwngccyu69VnYbzykGeez7ignHVAFSN',
|
||||
);
|
||||
// TODO: replace with a usdc devnet oracle
|
||||
const usdtDevnetOracle = new PublicKey(
|
||||
'38xoQ4oeJCBrcVvca2cGk7iV1dAfrmTR1kmhSCJQ8Jto',
|
||||
const usdcDevnetStubOracle = await findOrCreate(
|
||||
'stubOracle',
|
||||
getGroupForAdmin,
|
||||
[adminClient, admin.publicKey],
|
||||
createGroup,
|
||||
[adminClient, admin.publicKey, payer],
|
||||
);
|
||||
console.log(`Group ${group.publicKey}`);
|
||||
const btcDevnetMint = new PublicKey(
|
||||
'3UNBZ6o52WTWwjac2kPUb4FyodhU1vFkRJheu1Sh2TvU',
|
||||
);
|
||||
|
@ -103,7 +107,7 @@ async function main() {
|
|||
group.publicKey,
|
||||
admin.publicKey,
|
||||
usdcDevnetMint,
|
||||
usdtDevnetOracle,
|
||||
usdcDevnetStubOracle,
|
||||
payer,
|
||||
0,
|
||||
],
|
||||
|
|
|
@ -510,3 +510,25 @@ export async function setStubOracle(
|
|||
.signers([payer])
|
||||
.rpc();
|
||||
}
|
||||
|
||||
export async function getStubOracleForMint(
|
||||
client: MangoClient,
|
||||
mintPk: PublicKey,
|
||||
): Promise<MangoAccount[]> {
|
||||
return (
|
||||
await client.program.account.mangoAccount.all([
|
||||
{
|
||||
memcmp: {
|
||||
bytes: groupPk.toBase58(),
|
||||
offset: 8,
|
||||
},
|
||||
},
|
||||
{
|
||||
memcmp: {
|
||||
bytes: ownerPk.toBase58(),
|
||||
offset: 40,
|
||||
},
|
||||
},
|
||||
])
|
||||
).map((pa) => MangoAccount.from(pa.publicKey, pa.account));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue