account, market and bank names

Signed-off-by: microwavedcola1 <microwavedcola@gmail.com>
This commit is contained in:
microwavedcola1 2022-04-12 16:19:58 +02:00
parent 4eee341423
commit 03ae43017c
19 changed files with 156 additions and 42 deletions

View File

@ -2,6 +2,7 @@ use anchor_lang::prelude::*;
use crate::error::*;
use crate::state::*;
use crate::util::fill_from_str;
#[derive(Accounts)]
#[instruction(account_num: u8)]
@ -25,10 +26,11 @@ pub struct CreateAccount<'info> {
pub system_program: Program<'info, System>,
}
pub fn create_account(ctx: Context<CreateAccount>, account_num: u8) -> Result<()> {
pub fn create_account(ctx: Context<CreateAccount>, account_num: u8, name: String) -> Result<()> {
let mut account = ctx.accounts.account.load_init()?;
// TODO: dont init on stack
*account = MangoAccount {
name: fill_from_str(name)?,
group: ctx.accounts.group.key(),
owner: ctx.accounts.owner.key(),
delegate: Pubkey::default(),

View File

@ -8,6 +8,7 @@ use fixed_macro::types::I80F48;
// TODO: ALTs are unavailable
//use crate::address_lookup_table;
use crate::state::*;
use crate::util::fill_from_str;
const INDEX_START: I80F48 = I80F48!(1_000_000);
@ -80,6 +81,7 @@ pub struct RegisterToken<'info> {
pub fn register_token(
ctx: Context<RegisterToken>,
token_index: TokenIndex,
name: String,
util0: f32,
rate0: f32,
util1: f32,
@ -95,6 +97,7 @@ pub fn register_token(
let mut bank = ctx.accounts.bank.load_init()?;
*bank = Bank {
name: fill_from_str(name)?,
group: ctx.accounts.group.key(),
mint: ctx.accounts.mint.key(),
vault: ctx.accounts.vault.key(),

View File

@ -3,6 +3,7 @@ use anchor_lang::prelude::*;
use crate::error::MangoError;
use crate::serum3_cpi::{load_market_state, pubkey_from_u64_array};
use crate::state::*;
use crate::util::fill_from_str;
#[derive(Accounts)]
pub struct Serum3RegisterMarket<'info> {
@ -42,6 +43,7 @@ pub struct Serum3RegisterMarket<'info> {
pub fn serum3_register_market(
ctx: Context<Serum3RegisterMarket>,
market_index: Serum3MarketIndex,
name: String,
) -> Result<()> {
// TODO: must guard against accidentally using the same market_index twice!
@ -62,6 +64,7 @@ pub fn serum3_register_market(
let mut serum_market = ctx.accounts.serum_market.load_init()?;
*serum_market = Serum3Market {
name: fill_from_str(name)?,
group: ctx.accounts.group.key(),
serum_program: ctx.accounts.serum_program.key(),
serum_market_external: ctx.accounts.serum_market_external.key(),

View File

@ -37,6 +37,7 @@ pub mod mango_v4 {
pub fn register_token(
ctx: Context<RegisterToken>,
token_index: TokenIndex,
name: String,
util0: f32,
rate0: f32,
util1: f32,
@ -51,6 +52,7 @@ pub mod mango_v4 {
instructions::register_token(
ctx,
token_index,
name,
util0,
rate0,
util1,
@ -68,8 +70,12 @@ pub mod mango_v4 {
instructions::update_index(ctx)
}
pub fn create_account(ctx: Context<CreateAccount>, account_num: u8) -> Result<()> {
instructions::create_account(ctx, account_num)
pub fn create_account(
ctx: Context<CreateAccount>,
account_num: u8,
name: String,
) -> Result<()> {
instructions::create_account(ctx, account_num, name)
}
pub fn close_account(ctx: Context<CloseAccount>) -> Result<()> {
@ -112,8 +118,9 @@ pub mod mango_v4 {
pub fn serum3_register_market(
ctx: Context<Serum3RegisterMarket>,
market_index: Serum3MarketIndex,
name: String,
) -> Result<()> {
instructions::serum3_register_market(ctx, market_index)
instructions::serum3_register_market(ctx, market_index, name)
}
pub fn serum3_create_open_orders(ctx: Context<Serum3CreateOpenOrders>) -> Result<()> {

View File

@ -10,6 +10,8 @@ pub const YEAR: I80F48 = I80F48!(31536000);
#[account(zero_copy)]
pub struct Bank {
pub name: [u8; 16],
pub group: Pubkey,
pub mint: Pubkey,
pub vault: Pubkey,
@ -52,7 +54,7 @@ pub struct Bank {
pub reserved: [u8; 6],
}
const_assert_eq!(size_of::<Bank>(), 32 * 4 + 8 + 16 * 15 + 2 + 6);
const_assert_eq!(size_of::<Bank>(), 16 + 32 * 4 + 8 + 16 * 15 + 2 + 6);
const_assert_eq!(size_of::<Bank>() % 8, 0);
impl Bank {

View File

@ -512,6 +512,8 @@ impl Default for MangoAccountPerps {
#[account(zero_copy)]
pub struct MangoAccount {
pub name: [u8; 16],
pub group: Pubkey,
pub owner: Pubkey,
@ -542,7 +544,7 @@ pub struct MangoAccount {
}
const_assert_eq!(
size_of::<MangoAccount>(),
3 * 32
16 + 3 * 32
+ size_of::<MangoAccountTokens>()
+ size_of::<MangoAccountSerum3>()
+ size_of::<MangoAccountPerps>()

View File

@ -8,6 +8,7 @@ pub type Serum3MarketIndex = u16;
#[account(zero_copy)]
pub struct Serum3Market {
pub name: [u8; 16],
pub group: Pubkey,
pub serum_program: Pubkey,
pub serum_market_external: Pubkey,
@ -19,7 +20,7 @@ pub struct Serum3Market {
pub bump: u8,
pub reserved: [u8; 1],
}
const_assert_eq!(size_of::<Serum3Market>(), 32 * 3 + 3 * 2 + 1 + 1);
const_assert_eq!(size_of::<Serum3Market>(), 16 + 32 * 3 + 3 * 2 + 1 + 1);
const_assert_eq!(size_of::<Serum3Market>() % 8, 0);
#[macro_export]

View File

@ -1,7 +1,7 @@
use crate::error::MangoError;
use anchor_lang::prelude::*;
use anchor_lang::ZeroCopy;
use arrayref::array_ref;
use fixed::types::I80F48;
use std::cell::RefMut;
use std::{cell::Ref, mem};
@ -90,10 +90,10 @@ impl<'info> LoadZeroCopy for AccountInfo<'info> {
}
}
// Returns asset_weight and liab_weight
pub fn get_leverage_weights(leverage: I80F48) -> (I80F48, I80F48) {
(
(leverage - I80F48::ONE).checked_div(leverage).unwrap(),
(leverage + I80F48::ONE).checked_div(leverage).unwrap(),
)
pub fn fill_from_str(name: String) -> Result<[u8; 16]> {
let name_bytes = name.as_bytes();
require!(name_bytes.len() < 16, MangoError::SomeError);
let mut name_ = [0u8; 16];
name_[..name_bytes.len()].copy_from_slice(name_bytes);
Ok(name_)
}

View File

@ -472,6 +472,7 @@ impl<'keypair> ClientInstruction for RegisterTokenInstruction<'keypair> {
) -> (Self::Accounts, instruction::Instruction) {
let program_id = mango_v4::id();
let instruction = Self::Instruction {
name: "some_ticker".to_string(),
token_index: self.token_index,
util0: self.util0,
rate0: self.rate0,
@ -700,6 +701,7 @@ impl<'keypair> ClientInstruction for CreateAccountInstruction<'keypair> {
let program_id = mango_v4::id();
let instruction = mango_v4::instruction::CreateAccount {
account_num: self.account_num,
name: "my_mango_account".to_string(),
};
let account = Pubkey::find_program_address(
@ -786,6 +788,7 @@ impl<'keypair> ClientInstruction for Serum3RegisterMarketInstruction<'keypair> {
let program_id = mango_v4::id();
let instruction = Self::Instruction {
market_index: self.market_index,
name: "some_ticker/usdc".to_string(),
};
let serum_market = Pubkey::find_program_address(

View File

@ -3,7 +3,6 @@ use std::sync::{Arc, RwLock};
use anchor_lang::AccountDeserialize;
use anchor_spl::token::TokenAccount;
use solana_program::clock::UnixTimestamp;
use solana_program::{program_pack::Pack, rent::*, system_instruction};
use solana_program_test::*;
use solana_sdk::{
@ -15,8 +14,6 @@ use solana_sdk::{
};
use spl_token::*;
use super::mango_client::ClientAccountLoader;
pub struct SolanaCookie {
pub context: RefCell<ProgramTestContext>,
pub rent: Rent,

View File

@ -1,15 +1,18 @@
import { utf8 } from '@project-serum/anchor/dist/cjs/utils/bytes';
import { PublicKey } from '@solana/web3.js';
import bs58 from 'bs58';
import { MangoClient } from '../../client';
import { I80F48, I80F48Dto } from './I80F48';
export class Bank {
public name: string;
public depositIndex: I80F48;
public borrowIndex: I80F48;
static from(
publicKey: PublicKey,
obj: {
name: number[];
group: PublicKey;
mint: PublicKey;
vault: PublicKey;
@ -29,6 +32,7 @@ export class Bank {
) {
return new Bank(
publicKey,
obj.name,
obj.group,
obj.mint,
obj.vault,
@ -49,6 +53,7 @@ export class Bank {
constructor(
public publicKey: PublicKey,
name: number[],
public group: PublicKey,
public mint: PublicKey,
public vault: PublicKey,
@ -65,6 +70,7 @@ export class Bank {
dust: Object,
public tokenIndex: number,
) {
this.name = utf8.decode(new Uint8Array(name)).split('\x00')[0];
this.depositIndex = I80F48.from(depositIndex);
this.borrowIndex = I80F48.from(borrowIndex);
}

View File

@ -1,9 +1,5 @@
import { PublicKey } from '@solana/web3.js';
import { MangoClient } from '../../client';
import {
DEVNET_MINTS_REVERSE,
DEVNET_SERUM3_MARKETS_REVERSE,
} from '../../constants';
import { Bank } from './bank';
import { Serum3Market } from './serum3';
@ -32,20 +28,13 @@ export class Group {
public async reloadBanks(client: MangoClient) {
const banks = await client.getBanksForGroup(this);
this.banksMap = new Map(
banks.map((bank) => [DEVNET_MINTS_REVERSE[bank.mint.toBase58()], bank]),
);
this.banksMap = new Map(banks.map((bank) => [bank.name, bank]));
}
public async reloadSerum3Markets(client: MangoClient) {
const serum3Markets = await client.serum3GetMarket(this);
this.serum3MarketsMap = new Map(
serum3Markets.map((serum3Market) => [
DEVNET_SERUM3_MARKETS_REVERSE[
serum3Market.serumMarketExternal.toBase58()
],
serum3Market,
]),
serum3Markets.map((serum3Market) => [serum3Market.name, serum3Market]),
);
}
}

View File

@ -1,14 +1,16 @@
import { utf8 } from '@project-serum/anchor/dist/cjs/utils/bytes';
import { PublicKey } from '@solana/web3.js';
import { Bank } from './bank';
import { I80F48, I80F48Dto } from './I80F48';
export class MangoAccount {
public tokens: TokenAccount[];
public serum3: Serum3Account[];
public name: string;
static from(
publicKey: PublicKey,
obj: {
name: number[];
group: PublicKey;
owner: PublicKey;
delegate: PublicKey;
@ -24,6 +26,7 @@ export class MangoAccount {
) {
return new MangoAccount(
publicKey,
obj.name,
obj.group,
obj.owner,
obj.delegate,
@ -40,6 +43,7 @@ export class MangoAccount {
constructor(
public publicKey: PublicKey,
name: number[],
public group: PublicKey,
public owner: PublicKey,
public delegate: PublicKey,
@ -52,6 +56,7 @@ export class MangoAccount {
bump: number,
reserved: number[],
) {
this.name = utf8.decode(new Uint8Array(name)).split('\x00')[0];
this.tokens = tokens.values.map((dto) => TokenAccount.from(dto));
this.serum3 = serum3.values.map((dto) => Serum3Account.from(dto));
}

View File

@ -1,9 +1,12 @@
import { utf8 } from '@project-serum/anchor/dist/cjs/utils/bytes';
import { PublicKey } from '@solana/web3.js';
export class Serum3Market {
public name: string;
static from(
publicKey: PublicKey,
obj: {
name: number[];
group: PublicKey;
serumProgram: PublicKey;
serumMarketExternal: PublicKey;
@ -16,6 +19,7 @@ export class Serum3Market {
): Serum3Market {
return new Serum3Market(
publicKey,
obj.name,
obj.group,
obj.serumProgram,
obj.serumMarketExternal,
@ -27,13 +31,16 @@ export class Serum3Market {
constructor(
public publicKey: PublicKey,
name: number[],
public group: PublicKey,
public serumProgram: PublicKey,
public serumMarketExternal: PublicKey,
public marketIndex: number,
public baseTokenIndex: number,
public quoteTokenIndex: number,
) {}
) {
this.name = utf8.decode(new Uint8Array(name)).split('\x00')[0];
}
}
export class Serum3SelfTradeBehavior {

View File

@ -76,6 +76,7 @@ export class MangoClient {
mintPk: PublicKey,
oraclePk: PublicKey,
tokenIndex: number,
name: string,
util0: number,
rate0: number,
util1: number,
@ -90,6 +91,7 @@ export class MangoClient {
return await this.program.methods
.registerToken(
tokenIndex,
name,
util0,
rate0,
util1,
@ -118,7 +120,7 @@ export class MangoClient {
{
memcmp: {
bytes: group.publicKey.toBase58(),
offset: 8,
offset: 24,
},
},
])
@ -188,10 +190,11 @@ export class MangoClient {
group: Group,
ownerPk: PublicKey,
accountNumber?: number,
name?: string,
): Promise<MangoAccount> {
let mangoAccounts = await this.getMangoAccountForOwner(group, ownerPk);
if (mangoAccounts.length === 0) {
await this.createMangoAccount(group, accountNumber ?? 0);
await this.createMangoAccount(group, accountNumber ?? 0, name ?? '');
mangoAccounts = await this.getMangoAccountForOwner(group, ownerPk);
}
return mangoAccounts[0];
@ -200,9 +203,10 @@ export class MangoClient {
public async createMangoAccount(
group: Group,
accountNumber: number,
name?: string,
): Promise<TransactionSignature> {
return await this.program.methods
.createAccount(accountNumber)
.createAccount(accountNumber, name ?? '')
.accounts({
group: group.publicKey,
owner: this.program.provider.wallet.publicKey,
@ -227,13 +231,13 @@ export class MangoClient {
{
memcmp: {
bytes: group.publicKey.toBase58(),
offset: 8,
offset: 24,
},
},
{
memcmp: {
bytes: ownerPk.toBase58(),
offset: 40,
offset: 56,
},
},
])
@ -335,9 +339,10 @@ export class MangoClient {
baseBank: Bank,
quoteBank: Bank,
marketIndex: number,
name: string,
): Promise<TransactionSignature> {
return await this.program.methods
.serum3RegisterMarket(marketIndex)
.serum3RegisterMarket(marketIndex, name)
.accounts({
group: group.publicKey,
admin: this.program.provider.wallet.publicKey,
@ -362,7 +367,7 @@ export class MangoClient {
{
memcmp: {
bytes: group.publicKey.toBase58(),
offset: 8,
offset: 24,
},
},
];
@ -373,7 +378,7 @@ export class MangoClient {
filters.push({
memcmp: {
bytes: bs58.encode(bbuf),
offset: 106,
offset: 122,
},
});
}
@ -384,7 +389,7 @@ export class MangoClient {
filters.push({
memcmp: {
bytes: bs58.encode(qbuf),
offset: 108,
offset: 124,
},
});
}

View File

@ -1,6 +1,6 @@
import { PublicKey } from '@solana/web3.js';
export const DEVNET_GROUP = '882CDTXBMgqvD2ZzDcW2DxzMwEz1kD4eg7bzEBhFYejd';
export const DEVNET_GROUP = 'EjDBeQkKQ1y68ki4YskWjSZc4v5hJ44KWH64uvMNubsg';
export const DEVNET_MINTS = new Map([
['USDC', '8FRFC6MoGGkMFQwngccyu69VnYbzykGeez7ignHVAFSN'],

View File

@ -47,6 +47,7 @@ async function main() {
btcDevnetMint,
btcDevnetOracle,
0,
'btc',
0.4,
0.07,
0.8,
@ -73,6 +74,7 @@ async function main() {
usdcDevnetMint,
usdcDevnetOracle.publicKey,
1,
'usdc',
0.4,
0.07,
0.8,
@ -107,6 +109,7 @@ async function main() {
banks[0],
banks[1],
0,
'btc/usdc',
);
} catch (error) {}
const markets = await client.serum3GetMarket(

View File

@ -42,6 +42,7 @@ async function main() {
group,
user.publicKey,
0,
'my_mango_account',
);
console.log(`MangoAccount ${mangoAccount.publicKey}`);

View File

@ -164,6 +164,10 @@ export type MangoV4 = {
"name": "tokenIndex",
"type": "u16"
},
{
"name": "name",
"type": "string"
},
{
"name": "util0",
"type": "f32"
@ -274,6 +278,10 @@ export type MangoV4 = {
{
"name": "accountNum",
"type": "u8"
},
{
"name": "name",
"type": "string"
}
]
},
@ -599,6 +607,10 @@ export type MangoV4 = {
{
"name": "marketIndex",
"type": "u16"
},
{
"name": "name",
"type": "string"
}
]
},
@ -1346,6 +1358,15 @@ export type MangoV4 = {
"type": {
"kind": "struct",
"fields": [
{
"name": "name",
"type": {
"array": [
"u8",
16
]
}
},
{
"name": "group",
"type": "publicKey"
@ -1557,6 +1578,15 @@ export type MangoV4 = {
"type": {
"kind": "struct",
"fields": [
{
"name": "name",
"type": {
"array": [
"u8",
16
]
}
},
{
"name": "group",
"type": "publicKey"
@ -1867,6 +1897,15 @@ export type MangoV4 = {
"type": {
"kind": "struct",
"fields": [
{
"name": "name",
"type": {
"array": [
"u8",
16
]
}
},
{
"name": "group",
"type": "publicKey"
@ -2627,6 +2666,10 @@ export const IDL: MangoV4 = {
"name": "tokenIndex",
"type": "u16"
},
{
"name": "name",
"type": "string"
},
{
"name": "util0",
"type": "f32"
@ -2737,6 +2780,10 @@ export const IDL: MangoV4 = {
{
"name": "accountNum",
"type": "u8"
},
{
"name": "name",
"type": "string"
}
]
},
@ -3062,6 +3109,10 @@ export const IDL: MangoV4 = {
{
"name": "marketIndex",
"type": "u16"
},
{
"name": "name",
"type": "string"
}
]
},
@ -3809,6 +3860,15 @@ export const IDL: MangoV4 = {
"type": {
"kind": "struct",
"fields": [
{
"name": "name",
"type": {
"array": [
"u8",
16
]
}
},
{
"name": "group",
"type": "publicKey"
@ -4020,6 +4080,15 @@ export const IDL: MangoV4 = {
"type": {
"kind": "struct",
"fields": [
{
"name": "name",
"type": {
"array": [
"u8",
16
]
}
},
{
"name": "group",
"type": "publicKey"
@ -4330,6 +4399,15 @@ export const IDL: MangoV4 = {
"type": {
"kind": "struct",
"fields": [
{
"name": "name",
"type": {
"array": [
"u8",
16
]
}
},
{
"name": "group",
"type": "publicKey"