Merge pull request #33 from blockworks-foundation/mc/stub-oracle-ext

Mc/stub oracle ext
This commit is contained in:
microwavedcola1 2022-04-03 05:36:24 +02:00 committed by GitHub
commit 884d638e36
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 99 additions and 12 deletions

View File

@ -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;

View File

@ -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

View File

@ -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 {

View File

@ -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]
}
}

View File

@ -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",

View File

@ -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",

View File

@ -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",

View File

@ -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,
],

View File

@ -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));
}