add support for msrm vault for serum3 discounts (#285)

* add support for msrm vault for serum3 discounts

Signed-off-by: microwavedcola1 <microwavedcola@gmail.com>

* Fix client

Signed-off-by: microwavedcola1 <microwavedcola@gmail.com>

* client support

Signed-off-by: microwavedcola1 <microwavedcola@gmail.com>

* More client code and todos

Signed-off-by: microwavedcola1 <microwavedcola@gmail.com>

* prettoer

Signed-off-by: microwavedcola1 <microwavedcola@gmail.com>

* remove mint, not needed

Signed-off-by: microwavedcola1 <microwavedcola@gmail.com>

Signed-off-by: microwavedcola1 <microwavedcola@gmail.com>
This commit is contained in:
microwavedcola1 2022-11-09 09:59:42 +01:00 committed by GitHub
parent e47e17d79f
commit 0a4f7150d6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 333 additions and 10 deletions

View File

@ -590,6 +590,11 @@ impl MangoClient {
Serum3Side::Ask => s3.base.mint_info,
};
let group = account_fetcher_fetch_anchor_account::<Group>(
&*self.account_fetcher,
&self.context.group,
)?;
self.program()
.request()
.instruction(Instruction {
@ -598,6 +603,7 @@ impl MangoClient {
let mut ams = anchor_lang::ToAccountMetas::to_account_metas(
&mango_v4::accounts::Serum3PlaceOrder {
group: self.group(),
msrm_vault: group.msrm_vault,
account: self.mango_account_address,
open_orders,
payer_bank: payer_mint_info.first_bank(),

View File

@ -30,6 +30,18 @@ pub struct GroupCreate<'info> {
)]
pub insurance_vault: Account<'info, TokenAccount>,
pub msrm_mint: Account<'info, Mint>,
#[account(
init,
seeds = [b"MsrmVault".as_ref(), group.key().as_ref()],
bump,
token::authority = group,
token::mint = msrm_mint,
payer = payer
)]
pub msrm_vault: Account<'info, TokenAccount>,
#[account(mut)]
pub payer: Signer<'info>,
@ -54,5 +66,6 @@ pub fn group_create(
group.bump = *ctx.bumps.get("group").ok_or(MangoError::SomeError)?;
group.testing = testing;
group.version = version;
group.msrm_vault = ctx.accounts.msrm_vault.key();
Ok(())
}

View File

@ -0,0 +1,40 @@
use anchor_lang::prelude::*;
use anchor_spl::token::{Mint, Token, TokenAccount};
use crate::state::*;
#[derive(Accounts)]
pub struct GroupCreateMsrmVault<'info> {
#[account(
mut,
has_one = admin,
)]
pub group: AccountLoader<'info, Group>,
pub admin: Signer<'info>,
pub msrm_mint: Account<'info, Mint>,
#[account(
init,
seeds = [b"MsrmVault".as_ref(), group.key().as_ref()],
bump,
token::authority = group,
token::mint = msrm_mint,
payer = payer
)]
pub msrm_vault: Account<'info, TokenAccount>,
#[account(mut)]
pub payer: Signer<'info>,
pub token_program: Program<'info, Token>,
pub system_program: Program<'info, System>,
pub rent: Sysvar<'info, Rent>,
}
// Ix only exists to add vaults to groups created before msrm vault integration was done
pub fn group_create_msrm_vault(ctx: Context<GroupCreateMsrmVault>) -> Result<()> {
let mut group = ctx.accounts.group.load_mut()?;
group.msrm_vault = ctx.accounts.msrm_vault.key();
Ok(())
}

View File

@ -9,6 +9,7 @@ pub use compute_account_data::*;
pub use flash_loan::*;
pub use group_close::*;
pub use group_create::*;
pub use group_create_msrm_vault::*;
pub use group_edit::*;
pub use health_region::*;
pub use perp_cancel_all_orders::*;
@ -61,6 +62,7 @@ mod compute_account_data;
mod flash_loan;
mod group_close;
mod group_create;
mod group_create_msrm_vault;
mod group_edit;
mod health_region;
mod perp_cancel_all_orders;

View File

@ -133,7 +133,11 @@ pub enum Serum3Side {
#[derive(Accounts)]
pub struct Serum3PlaceOrder<'info> {
#[account(
has_one = msrm_vault
)]
pub group: AccountLoader<'info, Group>,
pub msrm_vault: Account<'info, TokenAccount>,
#[account(
mut,
@ -491,6 +495,7 @@ fn cpi_place_order(ctx: &Serum3PlaceOrder, order: NewOrderInstructionV3) -> Resu
open_orders: ctx.open_orders.to_account_info(),
order_payer_token_account: ctx.payer_vault.to_account_info(),
user_authority: ctx.group.to_account_info(),
msrm_vault: ctx.msrm_vault.to_account_info(),
}
.call(&group, order)
}

View File

@ -40,6 +40,10 @@ pub mod mango_v4 {
instructions::group_create(ctx, group_num, testing, version)
}
pub fn group_create_msrm_vault(ctx: Context<GroupCreateMsrmVault>) -> Result<()> {
instructions::group_create_msrm_vault(ctx)
}
pub fn group_edit(
ctx: Context<GroupEdit>,
admin_opt: Option<Pubkey>,
@ -227,6 +231,10 @@ pub mod mango_v4 {
instructions::token_withdraw(ctx, amount, allow_borrow)
}
// TODO
// pub fn token_deposit_msrm
// pub fn token_withdraw_msrm
pub fn flash_loan_begin<'key, 'accounts, 'remaining, 'info>(
ctx: Context<'key, 'accounts, 'remaining, 'info, FlashLoanBegin<'info>>,
loan_amounts: Vec<u64>,

View File

@ -298,6 +298,8 @@ pub struct PlaceOrder<'info> {
/// must cover the open_orders and the order_payer_token_account
/// CHECK: cpi
pub user_authority: AccountInfo<'info>,
/// CHECK: cpi
pub msrm_vault: AccountInfo<'info>,
}
impl<'a> PlaceOrder<'a> {
@ -323,6 +325,7 @@ impl<'a> PlaceOrder<'a> {
AccountMeta::new(*self.quote_vault.key, false),
AccountMeta::new_readonly(*self.token_program.key, false),
AccountMeta::new_readonly(*self.user_authority.key, false),
AccountMeta::new_readonly(*self.msrm_vault.key, false),
],
};
let account_infos = [
@ -339,6 +342,7 @@ impl<'a> PlaceOrder<'a> {
self.quote_vault,
self.token_program,
self.user_authority,
self.msrm_vault,
];
let seeds = group_seeds!(group);

View File

@ -35,7 +35,9 @@ pub struct Group {
pub address_lookup_tables: [Pubkey; 20],
pub reserved: [u8; 1920],
pub msrm_vault: Pubkey,
pub reserved: [u8; 1888],
}
const_assert_eq!(
size_of::<Group>(),

View File

@ -1119,6 +1119,7 @@ pub struct GroupCreateInstruction {
pub creator: TestKeypair,
pub payer: TestKeypair,
pub insurance_mint: Pubkey,
pub msrm_mint: Pubkey,
}
#[async_trait::async_trait(?Send)]
impl ClientInstruction for GroupCreateInstruction {
@ -1151,11 +1152,16 @@ impl ClientInstruction for GroupCreateInstruction {
)
.0;
let msrm_vault =
Pubkey::find_program_address(&[b"MsrmVault".as_ref(), group.as_ref()], &program_id).0;
let accounts = Self::Accounts {
group,
creator: self.creator.pubkey(),
insurance_mint: self.insurance_mint,
insurance_vault,
msrm_mint: self.msrm_mint,
msrm_vault,
payer: self.payer.pubkey(),
token_program: Token::id(),
system_program: System::id(),
@ -1712,8 +1718,11 @@ impl ClientInstruction for Serum3PlaceOrderInstruction {
Serum3Side::Ask => (base_info.first_bank(), base_info.first_vault()),
};
let group: Group = account_loader.load(&account.fixed.group).await.unwrap();
let accounts = Self::Accounts {
group: account.fixed.group,
msrm_vault: group.msrm_vault,
account: self.account,
open_orders,
payer_bank,

View File

@ -45,6 +45,7 @@ impl<'a> GroupWithTokensConfig {
creator: admin,
payer,
insurance_mint: mints[0].pubkey,
msrm_mint: mints[0].pubkey,
},
)
.await

View File

@ -40,6 +40,7 @@ export class Group {
testing: number;
version: number;
addressLookupTables: PublicKey[];
msrmVault: PublicKey;
},
): Group {
return new Group(
@ -54,6 +55,7 @@ export class Group {
obj.version,
obj.addressLookupTables,
[], // addressLookupTablesList
obj.msrmVault,
new Map(), // banksMapByName
new Map(), // banksMapByMint
new Map(), // banksMapByTokenIndex
@ -81,6 +83,7 @@ export class Group {
public version: number,
public addressLookupTables: PublicKey[],
public addressLookupTablesList: AddressLookupTableAccount[],
public msrmVault: PublicKey,
public banksMapByName: Map<string, Bank[]>,
public banksMapByMint: Map<string, Bank[]>,
public banksMapByTokenIndex: Map<TokenIndex, Bank[]>,

View File

@ -102,6 +102,7 @@ export class MangoClient {
testing: boolean,
version: number,
insuranceMintPk: PublicKey,
msrmMintPk: PublicKey,
): Promise<TransactionSignature> {
const adminPk = (this.program.provider as AnchorProvider).wallet.publicKey;
return await this.program.methods
@ -110,6 +111,23 @@ export class MangoClient {
creator: adminPk,
payer: adminPk,
insuranceMint: insuranceMintPk,
msrmMint: msrmMintPk,
})
.rpc();
}
public async groupCreateMsrmVault(
group: Group,
msrmMintPk: PublicKey,
): Promise<TransactionSignature> {
const adminPk = (this.program.provider as AnchorProvider).wallet.publicKey;
return await this.program.methods
.groupCreateMsrmVault()
.accounts({
group: group.publicKey,
admin: adminPk,
msrmMint: msrmMintPk,
payer: adminPk,
})
.rpc();
}
@ -1188,6 +1206,7 @@ export class MangoClient {
)
.accounts({
group: group.publicKey,
msrmVault: group.msrmVault,
account: mangoAccount.publicKey,
owner: (this.program.provider as AnchorProvider).wallet.publicKey,
openOrders: mangoAccount.getSerum3Account(serum3Market.marketIndex)

View File

@ -11,3 +11,9 @@ export const MANGO_V4_ID = {
devnet: new PublicKey('m43thNJ58XCjL798ZSq6JGAG1BnWskhdq5or6kcnfsD'),
'mainnet-beta': new PublicKey('m43thNJ58XCjL798ZSq6JGAG1BnWskhdq5or6kcnfsD'),
};
export const MSRM_MINTS = {
testnet: new PublicKey('3Ho7PN3bYv9bp1JDErBD2FxsRepPkL88vju3oDX9c3Ez'),
devnet: new PublicKey('8DJBo4bF4mHNxobjdax3BL9RMh5o71Jf8UiKsf5C5eVH'),
'mainnet-beta': new PublicKey('MSRMcoVyrFxnSgo5uXwone5SKcGhT1KEJMFEkMEWf9L'),
};

View File

@ -2,7 +2,7 @@ import { AnchorProvider, Wallet } from '@project-serum/anchor';
import { Connection, Keypair, PublicKey } from '@solana/web3.js';
import fs from 'fs';
import { MangoClient } from '../client';
import { MANGO_V4_ID } from '../constants';
import { MANGO_V4_ID, MSRM_MINTS } from '../constants';
const GROUP_NUM = Number(process.env.GROUP_NUM || 0);
@ -62,6 +62,7 @@ async function createGroup() {
true /* with intention */,
0 /* since spot and perp features are not finished */,
insuranceMint,
MSRM_MINTS['mainnet-beta'],
);
const group = await client.getGroupForCreator(admin.publicKey, GROUP_NUM);
console.log(`...registered group ${group.publicKey}`);

View File

@ -58,6 +58,30 @@ export type MangoV4 = {
]
}
},
{
"name": "msrmMint",
"isMut": false,
"isSigner": false
},
{
"name": "msrmVault",
"isMut": true,
"isSigner": false,
"pda": {
"seeds": [
{
"kind": "const",
"type": "string",
"value": "MsrmVault"
},
{
"kind": "account",
"type": "publicKey",
"path": "group"
}
]
}
},
{
"name": "payer",
"isMut": true,
@ -94,6 +118,66 @@ export type MangoV4 = {
}
]
},
{
"name": "groupCreateMsrmVault",
"accounts": [
{
"name": "group",
"isMut": true,
"isSigner": false
},
{
"name": "admin",
"isMut": false,
"isSigner": true
},
{
"name": "msrmMint",
"isMut": false,
"isSigner": false
},
{
"name": "msrmVault",
"isMut": true,
"isSigner": false,
"pda": {
"seeds": [
{
"kind": "const",
"type": "string",
"value": "MsrmVault"
},
{
"kind": "account",
"type": "publicKey",
"path": "group"
}
]
}
},
{
"name": "payer",
"isMut": true,
"isSigner": true
},
{
"name": "tokenProgram",
"isMut": false,
"isSigner": false
},
{
"name": "systemProgram",
"isMut": false,
"isSigner": false
},
{
"name": "rent",
"isMut": false,
"isSigner": false
}
],
"args": []
},
{
"name": "groupEdit",
"accounts": [
@ -1603,6 +1687,11 @@ export type MangoV4 = {
"isMut": false,
"isSigner": false
},
{
"name": "msrmVault",
"isMut": false,
"isSigner": false
},
{
"name": "account",
"isMut": true,
@ -3593,12 +3682,16 @@ export type MangoV4 = {
]
}
},
{
"name": "msrmVault",
"type": "publicKey"
},
{
"name": "reserved",
"type": {
"array": [
"u8",
1920
1888
]
}
}
@ -6891,6 +6984,30 @@ export const IDL: MangoV4 = {
]
}
},
{
"name": "msrmMint",
"isMut": false,
"isSigner": false
},
{
"name": "msrmVault",
"isMut": true,
"isSigner": false,
"pda": {
"seeds": [
{
"kind": "const",
"type": "string",
"value": "MsrmVault"
},
{
"kind": "account",
"type": "publicKey",
"path": "group"
}
]
}
},
{
"name": "payer",
"isMut": true,
@ -6927,6 +7044,66 @@ export const IDL: MangoV4 = {
}
]
},
{
"name": "groupCreateMsrmVault",
"accounts": [
{
"name": "group",
"isMut": true,
"isSigner": false
},
{
"name": "admin",
"isMut": false,
"isSigner": true
},
{
"name": "msrmMint",
"isMut": false,
"isSigner": false
},
{
"name": "msrmVault",
"isMut": true,
"isSigner": false,
"pda": {
"seeds": [
{
"kind": "const",
"type": "string",
"value": "MsrmVault"
},
{
"kind": "account",
"type": "publicKey",
"path": "group"
}
]
}
},
{
"name": "payer",
"isMut": true,
"isSigner": true
},
{
"name": "tokenProgram",
"isMut": false,
"isSigner": false
},
{
"name": "systemProgram",
"isMut": false,
"isSigner": false
},
{
"name": "rent",
"isMut": false,
"isSigner": false
}
],
"args": []
},
{
"name": "groupEdit",
"accounts": [
@ -8436,6 +8613,11 @@ export const IDL: MangoV4 = {
"isMut": false,
"isSigner": false
},
{
"name": "msrmVault",
"isMut": false,
"isSigner": false
},
{
"name": "account",
"isMut": true,
@ -10426,12 +10608,16 @@ export const IDL: MangoV4 = {
]
}
},
{
"name": "msrmVault",
"type": "publicKey"
},
{
"name": "reserved",
"type": {
"array": [
"u8",
1920
1888
]
}
}

View File

@ -7,7 +7,7 @@ import {
} from '@solana/web3.js';
import fs from 'fs';
import { MangoClient } from '../client';
import { MANGO_V4_ID } from '../constants';
import { MANGO_V4_ID, MSRM_MINTS } from '../constants';
import { buildVersionedTx } from '../utils';
//
@ -74,7 +74,13 @@ async function main() {
console.log(`Creating Group...`);
const insuranceMint = new PublicKey(DEVNET_MINTS.get('USDC')!);
try {
await client.groupCreate(GROUP_NUM, true, 0, insuranceMint);
await client.groupCreate(
GROUP_NUM,
true,
0,
insuranceMint,
MSRM_MINTS['devnet'],
);
} catch (error) {
console.log(error);
}

View File

@ -14,7 +14,7 @@ import {
Serum3Side,
} from '../accounts/serum3';
import { MangoClient } from '../client';
import { MANGO_V4_ID } from '../constants';
import { MANGO_V4_ID, MSRM_MINTS } from '../constants';
import { buildVersionedTx } from '../utils';
const MAINNET_MINTS = new Map([
@ -110,7 +110,13 @@ async function createGroup() {
console.log(`Creating Group...`);
const insuranceMint = new PublicKey(MAINNET_MINTS.get('USDC')!);
await client.groupCreate(2, true, 0, insuranceMint);
await client.groupCreate(
2,
true,
0,
insuranceMint,
MSRM_MINTS['mainnet-beta'],
);
const group = await client.getGroupForCreator(admin.publicKey, 2);
console.log(`...registered group ${group.publicKey}`);
}

View File

@ -2,7 +2,7 @@ import { AnchorProvider, Wallet } from '@project-serum/anchor';
import { Connection, Keypair, PublicKey } from '@solana/web3.js';
import fs from 'fs';
import { MangoClient } from '../client';
import { MANGO_V4_ID } from '../constants';
import { MANGO_V4_ID, MSRM_MINTS } from '../constants';
//
// Script which depoys a new mango group, and registers 3 tokens
@ -60,7 +60,13 @@ async function main() {
console.log(`Creating Group...`);
try {
const insuranceMint = new PublicKey(MAINNET_MINTS.get('USDC')!);
await client.groupCreate(GROUP_NUM, true, 0, insuranceMint);
await client.groupCreate(
GROUP_NUM,
true,
0,
insuranceMint,
MSRM_MINTS['mainnet-beta'],
);
} catch (error) {
console.log(error);
}