more reorg

Signed-off-by: microwavedcola1 <microwavedcola@gmail.com>
This commit is contained in:
microwavedcola1 2022-04-03 08:57:45 +02:00
parent 2cc8bfbeeb
commit 06a4bb90ba
15 changed files with 3879 additions and 3910 deletions

175
ts/accounts/types/bank.ts Normal file
View File

@ -0,0 +1,175 @@
import { I80F48, I80F48Dto } from './I80F48';
import {
Keypair,
PublicKey,
SYSVAR_RENT_PUBKEY,
Transaction,
TransactionInstruction,
} from '@solana/web3.js';
import { MangoClient } from '../../client';
export class Bank {
public depositIndex: I80F48;
public borrowIndex: I80F48;
static from(
publicKey: PublicKey,
obj: {
group: PublicKey;
mint: PublicKey;
vault: PublicKey;
oracle: PublicKey;
depositIndex: I80F48Dto;
borrowIndex: I80F48Dto;
indexedTotalDeposits: I80F48Dto;
indexedTotalBorrows: I80F48Dto;
maintAssetWeight: I80F48Dto;
initAssetWeight: I80F48Dto;
maintLiabWeight: I80F48Dto;
initLiabWeight: I80F48Dto;
liquidationFee: I80F48Dto;
dust: Object;
tokenIndex: number;
},
) {
return new Bank(
publicKey,
obj.group,
obj.mint,
obj.vault,
obj.oracle,
obj.depositIndex,
obj.borrowIndex,
obj.indexedTotalDeposits,
obj.indexedTotalBorrows,
obj.maintAssetWeight,
obj.initAssetWeight,
obj.maintLiabWeight,
obj.initLiabWeight,
obj.liquidationFee,
obj.dust,
obj.tokenIndex,
);
}
constructor(
public publicKey: PublicKey,
group: PublicKey,
mint: PublicKey,
public vault: PublicKey,
oracle: PublicKey,
depositIndex: I80F48Dto,
borrowIndex: I80F48Dto,
indexedTotalDeposits: I80F48Dto,
indexedTotalBorrows: I80F48Dto,
maintAssetWeight: I80F48Dto,
initAssetWeight: I80F48Dto,
maintLiabWeight: I80F48Dto,
initLiabWeight: I80F48Dto,
liquidationFee: I80F48Dto,
dust: Object,
public tokenIndex: number,
) {
this.depositIndex = I80F48.from(depositIndex);
this.borrowIndex = I80F48.from(borrowIndex);
}
toString(): string {
return `Bank ${
this.tokenIndex
} deposit index - ${this.depositIndex.toNumber()}, borrow index - ${this.borrowIndex.toNumber()}`;
}
}
export async function registerToken(
client: MangoClient,
groupPk: PublicKey,
adminPk: PublicKey,
mintPk: PublicKey,
oraclePk: PublicKey,
payer: Keypair,
tokenIndex: number,
): Promise<void> {
const tx = new Transaction();
const signers = [payer];
const ix = await registerTokenIx(
client,
groupPk,
adminPk,
mintPk,
oraclePk,
payer,
tokenIndex,
);
tx.add(ix);
await client.program.provider.send(tx, signers);
}
export async function registerTokenIx(
client: MangoClient,
groupPk: PublicKey,
adminPk: PublicKey,
mintPk: PublicKey,
oraclePk: PublicKey,
payer: Keypair,
tokenIndex: number,
): Promise<TransactionInstruction> {
return await client.program.methods
.registerToken(tokenIndex, 0.8, 0.6, 1.2, 1.4, 0.02)
.accounts({
group: groupPk,
admin: adminPk,
mint: mintPk,
oracle: oraclePk,
payer: payer.publicKey,
rent: SYSVAR_RENT_PUBKEY,
})
.signers([payer])
.instruction();
}
export async function getBank(
client: MangoClient,
address: PublicKey,
): Promise<Bank> {
return Bank.from(address, await client.program.account.bank.fetch(address));
}
export async function getBanksForGroup(
client: MangoClient,
groupPk: PublicKey,
): Promise<Bank[]> {
return (
await client.program.account.bank.all([
{
memcmp: {
bytes: groupPk.toBase58(),
offset: 8,
},
},
])
).map((tuple) => Bank.from(tuple.publicKey, tuple.account));
}
export async function getBankForGroupAndMint(
client: MangoClient,
groupPk: PublicKey,
mintPk: PublicKey,
): Promise<Bank[]> {
return (
await client.program.account.bank.all([
{
memcmp: {
bytes: groupPk.toBase58(),
offset: 8,
},
},
{
memcmp: {
bytes: mintPk.toBase58(),
offset: 40,
},
},
])
).map((tuple) => Bank.from(tuple.publicKey, tuple.account));
}

View File

@ -0,0 +1,58 @@
import {
Keypair,
PublicKey,
Transaction,
TransactionInstruction,
} from '@solana/web3.js';
import { MangoClient } from '../../client';
export class Group {
static from(publicKey: PublicKey, obj: { admin: PublicKey }): Group {
return new Group(publicKey, obj.admin);
}
constructor(public publicKey: PublicKey, public admin: PublicKey) {}
}
export async function createGroup(
client: MangoClient,
adminPk: PublicKey,
payer: Keypair,
): Promise<void> {
const tx = new Transaction();
const signers = [payer];
const ix = await createGroupIx(client, adminPk, payer);
tx.add(ix);
await client.program.provider.send(tx, signers);
}
export async function createGroupIx(
client: MangoClient,
adminPk: PublicKey,
payer: Keypair,
): Promise<TransactionInstruction> {
return await client.program.methods
.createGroup()
.accounts({
admin: adminPk,
payer: payer.publicKey,
})
.signers([payer])
.instruction();
}
export async function getGroupForAdmin(
client: MangoClient,
adminPk: PublicKey,
): Promise<Group[]> {
return (
await client.program.account.group.all([
{
memcmp: {
bytes: adminPk.toBase58(),
offset: 8,
},
},
])
).map((tuple) => Group.from(tuple.publicKey, tuple.account));
}

View File

@ -0,0 +1,320 @@
import {
Keypair,
PublicKey,
Transaction,
TransactionInstruction,
} from '@solana/web3.js';
import { Bank } from './bank';
import { I80F48, I80F48Dto } from './I80F48';
import { MangoClient } from '../../client';
import { BN } from '@project-serum/anchor';
export class MangoAccount {
public tokens: TokenAccount[];
static from(
publicKey: PublicKey,
obj: {
group: PublicKey;
owner: PublicKey;
delegate: PublicKey;
tokens: unknown;
serum3: Object;
perps: unknown;
beingLiquidated: number;
isBankrupt: number;
accountNum: number;
bump: number;
reserved: number[];
},
) {
return new MangoAccount(
publicKey,
obj.group,
obj.owner,
obj.delegate,
obj.tokens as { values: TokenAccountDto[] },
obj.serum3,
obj.perps,
obj.beingLiquidated,
obj.isBankrupt,
obj.accountNum,
obj.bump,
obj.reserved,
);
}
constructor(
public publicKey: PublicKey,
group: PublicKey,
owner: PublicKey,
delegate: PublicKey,
tokens: { values: TokenAccountDto[] },
serum3: Object,
perps: unknown,
beingLiquidated: number,
isBankrupt: number,
accountNum: number,
bump: number,
reserved: number[],
) {
this.tokens = tokens.values.map((dto) => TokenAccount.from(dto));
}
find(tokenIndex: number): TokenAccount | undefined {
return this.tokens.find((ta) => ta.tokenIndex == tokenIndex);
}
getNativeDeposit(bank: Bank): I80F48 {
const ta = this.find(bank.tokenIndex);
return bank.depositIndex.mul(ta?.indexedValue!);
}
getNativeBorrow(bank: Bank): I80F48 {
const ta = this.find(bank.tokenIndex);
return bank.borrowIndex.mul(ta?.indexedValue!);
}
}
export class TokenAccount {
static from(dto: TokenAccountDto) {
return new TokenAccount(
I80F48.from(dto.indexedValue),
dto.tokenIndex,
dto.inUseCount,
);
}
constructor(
public indexedValue: I80F48,
public tokenIndex: number,
public inUseCount: number,
) {}
}
export class TokenAccountDto {
constructor(
public indexedValue: I80F48Dto,
public tokenIndex: number,
public inUseCount: number,
public reserved: number[],
) {}
}
export async function createMangoAccount(
client: MangoClient,
groupPk: PublicKey,
ownerPk: PublicKey,
payer: Keypair,
): Promise<void> {
const tx = new Transaction();
const signers = [payer];
const ix = await createMangoAccountIx(client, groupPk, ownerPk, payer);
tx.add(ix);
await client.program.provider.send(tx, signers);
}
export async function createMangoAccountIx(
client: MangoClient,
groupPk: PublicKey,
ownerPk: PublicKey,
payer: Keypair,
): Promise<TransactionInstruction> {
return await client.program.methods
.createAccount(11)
.accounts({
group: groupPk,
owner: ownerPk,
payer: payer.publicKey,
})
.signers([payer])
.instruction();
}
export async function closeMangoAccount(
client: MangoClient,
accountPk: PublicKey,
ownerPk: PublicKey,
) {
const tx = new Transaction();
const ix = await closeMangoAccountIx(client, accountPk, ownerPk);
tx.add(ix);
await client.program.provider.send(tx);
}
export async function closeMangoAccountIx(
client: MangoClient,
accountPk: PublicKey,
ownerPk: PublicKey,
): Promise<TransactionInstruction> {
return await client.program.methods
.closeAccount()
.accounts({
account: accountPk,
owner: ownerPk,
solDestination: ownerPk,
})
.instruction();
}
export async function getMangoAccount(
client: MangoClient,
address: PublicKey,
): Promise<MangoAccount> {
return MangoAccount.from(
address,
await client.program.account.mangoAccount.fetch(address),
);
}
export async function getMangoAccountsForGroup(
client: MangoClient,
groupPk: PublicKey,
): Promise<MangoAccount[]> {
return (
await client.program.account.mangoAccount.all([
{
memcmp: {
bytes: groupPk.toBase58(),
offset: 8,
},
},
])
).map((pa) => MangoAccount.from(pa.publicKey, pa.account));
}
export async function getMangoAccountsForGroupAndOwner(
client: MangoClient,
groupPk: PublicKey,
ownerPk: 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));
}
export async function deposit(
client: MangoClient,
groupPk: PublicKey,
mangoAccountPk: PublicKey,
bankPk: PublicKey,
vaultPk: PublicKey,
tokenAccountPk: PublicKey,
oraclePk: PublicKey,
ownerPk: PublicKey,
amount: number,
): Promise<void> {
const tx = new Transaction();
const ix = await depositIx(
client,
groupPk,
mangoAccountPk,
bankPk,
vaultPk,
tokenAccountPk,
oraclePk,
ownerPk,
amount,
);
tx.add(ix);
await client.program.provider.send(tx);
}
export async function depositIx(
client: MangoClient,
groupPk: PublicKey,
mangoAccountPk: PublicKey,
bankPk: PublicKey,
vaultPk: PublicKey,
tokenAccountPk: PublicKey,
oraclePk: PublicKey,
ownerPk: PublicKey,
amount: number,
): Promise<TransactionInstruction> {
return await client.program.methods
.deposit(new BN(amount))
.accounts({
group: groupPk,
account: mangoAccountPk,
bank: bankPk,
vault: vaultPk,
tokenAccount: tokenAccountPk,
tokenAuthority: ownerPk,
})
.remainingAccounts([
{ pubkey: bankPk, isWritable: false, isSigner: false },
{ pubkey: oraclePk, isWritable: false, isSigner: false },
])
.instruction();
}
export async function withdraw(
client: MangoClient,
groupPk: PublicKey,
mangoAccountPk: PublicKey,
bankPk: PublicKey,
vaultPk: PublicKey,
tokenAccountPk: PublicKey,
oraclePk: PublicKey,
ownerPk: PublicKey,
amount: number,
allowBorrow: boolean,
): Promise<void> {
const tx = new Transaction();
const ix = await withdrawIx(
client,
groupPk,
mangoAccountPk,
bankPk,
vaultPk,
tokenAccountPk,
oraclePk,
ownerPk,
amount,
allowBorrow,
);
tx.add(ix);
await client.program.provider.send(tx);
}
export async function withdrawIx(
client: MangoClient,
groupPk: PublicKey,
mangoAccountPk: PublicKey,
bankPk: PublicKey,
vaultPk: PublicKey,
tokenAccountPk: PublicKey,
oraclePk: PublicKey,
ownerPk: PublicKey,
amount: number,
allowBorrow: boolean,
): Promise<TransactionInstruction> {
return await client.program.methods
.withdraw(new BN(amount), allowBorrow)
.accounts({
group: groupPk,
account: mangoAccountPk,
bank: bankPk,
vault: vaultPk,
tokenAccount: tokenAccountPk,
tokenAuthority: ownerPk,
})
.remainingAccounts([
{ pubkey: bankPk, isWritable: false, isSigner: false },
{ pubkey: oraclePk, isWritable: false, isSigner: false },
])
.instruction();
}

102
ts/accounts/types/oracle.ts Normal file
View File

@ -0,0 +1,102 @@
import { I80F48, I80F48Dto } from './I80F48';
import { Keypair, PublicKey } from '@solana/web3.js';
import BN from 'bn.js';
import { MangoClient } from '../../client';
export class StubOracle {
public price: I80F48;
public lastUpdated: number;
static from(
publicKey: PublicKey,
obj: {
group: PublicKey;
mint: PublicKey;
price: I80F48Dto;
lastUpdated: BN;
reserved: unknown;
},
): StubOracle {
return new StubOracle(
publicKey,
obj.group,
obj.mint,
obj.price,
obj.lastUpdated,
);
}
constructor(
public publicKey: PublicKey,
public group: PublicKey,
public mint: PublicKey,
price: I80F48Dto,
lastUpdated: BN,
) {
this.price = I80F48.from(price);
this.lastUpdated = lastUpdated.toNumber();
}
}
export async function createStubOracle(
client: MangoClient,
groupPk: PublicKey,
adminPk: PublicKey,
tokenMintPk: PublicKey,
payer: Keypair,
staticPrice: number,
): Promise<void> {
return await client.program.methods
.createStubOracle({ val: I80F48.fromNumber(staticPrice).getData() })
.accounts({
group: groupPk,
admin: adminPk,
tokenMint: tokenMintPk,
payer: payer.publicKey,
})
.signers([payer])
.rpc();
}
export async function setStubOracle(
client: MangoClient,
groupPk: PublicKey,
adminPk: PublicKey,
tokenMintPk: PublicKey,
payer: Keypair,
staticPrice: number,
): Promise<void> {
return await client.program.methods
.setStubOracle({ val: new BN(staticPrice) })
.accounts({
group: groupPk,
admin: adminPk,
tokenMint: tokenMintPk,
payer: payer.publicKey,
})
.signers([payer])
.rpc();
}
export async function getStubOracleForGroupAndMint(
client: MangoClient,
groupPk: PublicKey,
mintPk: PublicKey,
): Promise<StubOracle[]> {
return (
await client.program.account.stubOracle.all([
{
memcmp: {
bytes: groupPk.toBase58(),
offset: 8,
},
},
{
memcmp: {
bytes: mintPk.toBase58(),
offset: 40,
},
},
])
).map((pa) => StubOracle.from(pa.publicKey, pa.account));
}

135
ts/accounts/types/serum3.ts Normal file
View File

@ -0,0 +1,135 @@
import {
Keypair,
PublicKey,
Transaction,
TransactionInstruction,
} from '@solana/web3.js';
import { MangoClient } from '../../client';
import * as bs58 from 'bs58';
export class Serum3Market {
static from(
publicKey: PublicKey,
obj: {
group: PublicKey;
serumProgram: PublicKey;
serumMarketExternal: PublicKey;
marketIndex: number;
baseTokenIndex: number;
quoteTokenIndex: number;
bump: number;
reserved: unknown;
},
): Serum3Market {
return new Serum3Market(
publicKey,
obj.group,
obj.serumProgram,
obj.serumMarketExternal,
obj.marketIndex,
obj.baseTokenIndex,
obj.quoteTokenIndex,
);
}
constructor(
public publicKey: PublicKey,
public group: PublicKey,
public serumProgram: PublicKey,
public serumMarketExternal: PublicKey,
public marketIndex: number,
public baseTokenIndex: number,
public quoteTokenIndex: number,
) {}
}
export async function serum3RegisterMarket(
client: MangoClient,
groupPk: PublicKey,
adminPk: PublicKey,
serumProgramPk: PublicKey,
serumMarketExternalPk: PublicKey,
quoteBankPk: PublicKey,
baseBankPk: PublicKey,
payer: Keypair,
marketIndex: number,
): Promise<void> {
const tx = new Transaction();
const ix = await serum3RegisterMarketIx(
client,
groupPk,
adminPk,
serumProgramPk,
serumMarketExternalPk,
quoteBankPk,
baseBankPk,
payer,
marketIndex,
);
tx.add(ix);
await client.program.provider.send(tx, [payer]);
}
export async function serum3RegisterMarketIx(
client: MangoClient,
groupPk: PublicKey,
adminPk: PublicKey,
serumProgramPk: PublicKey,
serumMarketExternalPk: PublicKey,
quoteBankPk: PublicKey,
baseBankPk: PublicKey,
payer: Keypair,
marketIndex: number,
): Promise<TransactionInstruction> {
return await client.program.methods
.serum3RegisterMarket(marketIndex)
.accounts({
group: groupPk,
admin: adminPk,
serumProgram: serumProgramPk,
serumMarketExternal: serumMarketExternalPk,
quoteBank: quoteBankPk,
baseBank: baseBankPk,
payer: payer.publicKey,
})
.instruction();
}
export async function getSerum3MarketForBaseAndQuote(
client: MangoClient,
groupPk: PublicKey,
baseTokenIndex: number,
quoteTokenIndex: number,
): Promise<Serum3Market[]> {
const bbuf = Buffer.alloc(2);
bbuf.writeUInt16LE(baseTokenIndex);
const qbuf = Buffer.alloc(2);
qbuf.writeUInt16LE(quoteTokenIndex);
const bumpfbuf = Buffer.alloc(1);
bumpfbuf.writeUInt8(255);
return (
await client.program.account.serum3Market.all([
{
memcmp: {
bytes: groupPk.toBase58(),
offset: 8,
},
},
{
memcmp: {
bytes: bs58.encode(bbuf),
offset: 106,
},
},
{
memcmp: {
bytes: bs58.encode(qbuf),
offset: 108,
},
},
])
).map((tuple) => Serum3Market.from(tuple.publicKey, tuple.account));
}

View File

@ -3,27 +3,31 @@ import { Connection, Keypair, PublicKey } from '@solana/web3.js';
import * as spl from '@solana/spl-token';
import fs from 'fs';
import { MangoClient } from './client';
import { findOrCreate } from './utils';
import {
createGroup,
createMangoAccount,
createStubOracle,
deposit,
Bank,
getBank,
getBankForGroupAndMint,
getGroupForAdmin,
registerToken,
} from './accounts/types/bank';
import {
createMangoAccount,
deposit,
getMangoAccount,
getMangoAccountsForGroupAndOwner,
getSerum3MarketForBaseAndQuote,
getStubOracleForGroupAndMint,
registerToken,
serum3RegisterMarket,
MangoAccount,
withdraw,
} from './instructions';
import { findOrCreate } from './utils';
import { Bank } from './types/bank';
import { MangoAccount } from './types/mangoAccount';
import { Group } from './types/group';
import { Serum3Market } from './types/serum3';
} from './accounts/types/mangoAccount';
import { createGroup, getGroupForAdmin, Group } from './accounts/types/group';
import {
getSerum3MarketForBaseAndQuote,
Serum3Market,
serum3RegisterMarket,
} from './accounts/types/serum3';
import {
createStubOracle,
getStubOracleForGroupAndMint,
} from './accounts/types/oracle';
async function main() {
//

View File

@ -1,11 +1,36 @@
export * from './client';
export * from './instructions';
export * from './types/types';
export * from './types/I80F48';
export { Bank } from './types/bank';
export { MangoAccount } from './types/mangoAccount';
export { Group } from './types/group';
export { TokenAccountDto } from './types/mangoAccount';
export { TokenAccount } from './types/mangoAccount';
export { Serum3Market } from './types/serum3';
export { StubOracle } from './types/oracle';
export * from './accounts/types/types';
export * from './accounts/types/I80F48';
export { Bank } from './accounts/types/bank';
export { MangoAccount } from './accounts/types/mangoAccount';
export { Group } from './accounts/types/group';
export { TokenAccountDto } from './accounts/types/mangoAccount';
export { TokenAccount } from './accounts/types/mangoAccount';
export { Serum3Market } from './accounts/types/serum3';
export { StubOracle } from './accounts/types/oracle';
export { getGroupForAdmin } from './accounts/types/group';
export { createGroupIx } from './accounts/types/group';
export { createGroup } from './accounts/types/group';
export { registerTokenIx } from './accounts/types/bank';
export { registerToken } from './accounts/types/bank';
export { getBankForGroupAndMint } from './accounts/types/bank';
export { getBanksForGroup } from './accounts/types/bank';
export { getBank } from './accounts/types/bank';
export { getMangoAccountsForGroupAndOwner } from './accounts/types/mangoAccount';
export { getMangoAccountsForGroup } from './accounts/types/mangoAccount';
export { getMangoAccount } from './accounts/types/mangoAccount';
export { createMangoAccountIx } from './accounts/types/mangoAccount';
export { createMangoAccount } from './accounts/types/mangoAccount';
export { closeMangoAccountIx } from './accounts/types/mangoAccount';
export { closeMangoAccount } from './accounts/types/mangoAccount';
export { withdrawIx } from './accounts/types/mangoAccount';
export { withdraw } from './accounts/types/mangoAccount';
export { depositIx } from './accounts/types/mangoAccount';
export { deposit } from './accounts/types/mangoAccount';
export { getSerum3MarketForBaseAndQuote } from './accounts/types/serum3';
export { serum3RegisterMarketIx } from './accounts/types/serum3';
export { serum3RegisterMarket } from './accounts/types/serum3';
export { getStubOracleForGroupAndMint } from './accounts/types/oracle';
export { setStubOracle } from './accounts/types/oracle';
export { createStubOracle } from './accounts/types/oracle';

View File

@ -1,389 +1,19 @@
import { BN } from '@project-serum/anchor';
import {
Keypair,
PublicKey,
SYSVAR_RENT_PUBKEY,
Transaction,
TransactionInstruction,
} from '@solana/web3.js';
import * as bs58 from 'bs58';
import { MangoClient } from './client';
import { I80F48 } from './types/I80F48';
import { Bank } from './types/bank';
import { MangoAccount } from './types/mangoAccount';
import { Group } from './types/group';
import { Serum3Market } from './types/serum3';
import { StubOracle } from './types/oracle';
//
// group
//
export async function createGroup(
client: MangoClient,
adminPk: PublicKey,
payer: Keypair,
): Promise<void> {
const tx = new Transaction();
const signers = [payer];
const ix = await createGroupIx(client, adminPk, payer);
tx.add(ix);
await client.program.provider.send(tx, signers);
}
export async function createGroupIx(
client: MangoClient,
adminPk: PublicKey,
payer: Keypair,
): Promise<TransactionInstruction> {
return await client.program.methods
.createGroup()
.accounts({
admin: adminPk,
payer: payer.publicKey,
})
.signers([payer])
.instruction();
}
export async function getGroupForAdmin(
client: MangoClient,
adminPk: PublicKey,
): Promise<Group[]> {
return (
await client.program.account.group.all([
{
memcmp: {
bytes: adminPk.toBase58(),
offset: 8,
},
},
])
).map((tuple) => Group.from(tuple.publicKey, tuple.account));
}
//
// token / bank
//
export async function registerToken(
client: MangoClient,
groupPk: PublicKey,
adminPk: PublicKey,
mintPk: PublicKey,
oraclePk: PublicKey,
payer: Keypair,
tokenIndex: number,
): Promise<void> {
const tx = new Transaction();
const signers = [payer];
const ix = await registerTokenIx(
client,
groupPk,
adminPk,
mintPk,
oraclePk,
payer,
tokenIndex,
);
tx.add(ix);
await client.program.provider.send(tx, signers);
}
export async function registerTokenIx(
client: MangoClient,
groupPk: PublicKey,
adminPk: PublicKey,
mintPk: PublicKey,
oraclePk: PublicKey,
payer: Keypair,
tokenIndex: number,
): Promise<TransactionInstruction> {
return await client.program.methods
.registerToken(tokenIndex, 0.8, 0.6, 1.2, 1.4, 0.02)
.accounts({
group: groupPk,
admin: adminPk,
mint: mintPk,
oracle: oraclePk,
payer: payer.publicKey,
rent: SYSVAR_RENT_PUBKEY,
})
.signers([payer])
.instruction();
}
export async function getBank(
client: MangoClient,
address: PublicKey,
): Promise<Bank> {
return Bank.from(address, await client.program.account.bank.fetch(address));
}
export async function getBanksForGroup(
client: MangoClient,
groupPk: PublicKey,
): Promise<Bank[]> {
return (
await client.program.account.bank.all([
{
memcmp: {
bytes: groupPk.toBase58(),
offset: 8,
},
},
])
).map((tuple) => Bank.from(tuple.publicKey, tuple.account));
}
export async function getBankForGroupAndMint(
client: MangoClient,
groupPk: PublicKey,
mintPk: PublicKey,
): Promise<Bank[]> {
return (
await client.program.account.bank.all([
{
memcmp: {
bytes: groupPk.toBase58(),
offset: 8,
},
},
{
memcmp: {
bytes: mintPk.toBase58(),
offset: 40,
},
},
])
).map((tuple) => Bank.from(tuple.publicKey, tuple.account));
}
//
// mango account
//
export async function closeMangoAccount(
client: MangoClient,
accountPk: PublicKey,
ownerPk: PublicKey,
) {
const tx = new Transaction();
const ix = await closeMangoAccountIx(client, accountPk, ownerPk);
tx.add(ix);
await client.program.provider.send(tx);
}
export async function closeMangoAccountIx(
client: MangoClient,
accountPk: PublicKey,
ownerPk: PublicKey,
): Promise<TransactionInstruction> {
return await client.program.methods
.closeAccount()
.accounts({
account: accountPk,
owner: ownerPk,
solDestination: ownerPk,
})
.instruction();
}
export async function createMangoAccount(
client: MangoClient,
groupPk: PublicKey,
ownerPk: PublicKey,
payer: Keypair,
): Promise<void> {
const tx = new Transaction();
const signers = [payer];
const ix = await createMangoAccountIx(client, groupPk, ownerPk, payer);
tx.add(ix);
await client.program.provider.send(tx, signers);
}
export async function createMangoAccountIx(
client: MangoClient,
groupPk: PublicKey,
ownerPk: PublicKey,
payer: Keypair,
): Promise<TransactionInstruction> {
return await client.program.methods
.createAccount(11)
.accounts({
group: groupPk,
owner: ownerPk,
payer: payer.publicKey,
})
.signers([payer])
.instruction();
}
export async function getMangoAccount(
client: MangoClient,
address: PublicKey,
): Promise<MangoAccount> {
return MangoAccount.from(
address,
await client.program.account.mangoAccount.fetch(address),
);
}
export async function getMangoAccountsForGroup(
client: MangoClient,
groupPk: PublicKey,
): Promise<MangoAccount[]> {
return (
await client.program.account.mangoAccount.all([
{
memcmp: {
bytes: groupPk.toBase58(),
offset: 8,
},
},
])
).map((pa) => MangoAccount.from(pa.publicKey, pa.account));
}
export async function getMangoAccountsForGroupAndOwner(
client: MangoClient,
groupPk: PublicKey,
ownerPk: 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));
}
//
// deposit & withdraw
//
export async function deposit(
client: MangoClient,
groupPk: PublicKey,
mangoAccountPk: PublicKey,
bankPk: PublicKey,
vaultPk: PublicKey,
tokenAccountPk: PublicKey,
oraclePk: PublicKey,
ownerPk: PublicKey,
amount: number,
): Promise<void> {
const tx = new Transaction();
const ix = await depositIx(
client,
groupPk,
mangoAccountPk,
bankPk,
vaultPk,
tokenAccountPk,
oraclePk,
ownerPk,
amount,
);
tx.add(ix);
await client.program.provider.send(tx);
}
export async function depositIx(
client: MangoClient,
groupPk: PublicKey,
mangoAccountPk: PublicKey,
bankPk: PublicKey,
vaultPk: PublicKey,
tokenAccountPk: PublicKey,
oraclePk: PublicKey,
ownerPk: PublicKey,
amount: number,
): Promise<TransactionInstruction> {
return await client.program.methods
.deposit(new BN(amount))
.accounts({
group: groupPk,
account: mangoAccountPk,
bank: bankPk,
vault: vaultPk,
tokenAccount: tokenAccountPk,
tokenAuthority: ownerPk,
})
.remainingAccounts([
{ pubkey: bankPk, isWritable: false, isSigner: false },
{ pubkey: oraclePk, isWritable: false, isSigner: false },
])
.instruction();
}
export async function withdraw(
client: MangoClient,
groupPk: PublicKey,
mangoAccountPk: PublicKey,
bankPk: PublicKey,
vaultPk: PublicKey,
tokenAccountPk: PublicKey,
oraclePk: PublicKey,
ownerPk: PublicKey,
amount: number,
allowBorrow: boolean,
): Promise<void> {
const tx = new Transaction();
const ix = await withdrawIx(
client,
groupPk,
mangoAccountPk,
bankPk,
vaultPk,
tokenAccountPk,
oraclePk,
ownerPk,
amount,
allowBorrow,
);
tx.add(ix);
await client.program.provider.send(tx);
}
export async function withdrawIx(
client: MangoClient,
groupPk: PublicKey,
mangoAccountPk: PublicKey,
bankPk: PublicKey,
vaultPk: PublicKey,
tokenAccountPk: PublicKey,
oraclePk: PublicKey,
ownerPk: PublicKey,
amount: number,
allowBorrow: boolean,
): Promise<TransactionInstruction> {
return await client.program.methods
.withdraw(new BN(amount), allowBorrow)
.accounts({
group: groupPk,
account: mangoAccountPk,
bank: bankPk,
vault: vaultPk,
tokenAccount: tokenAccountPk,
tokenAuthority: ownerPk,
})
.remainingAccounts([
{ pubkey: bankPk, isWritable: false, isSigner: false },
{ pubkey: oraclePk, isWritable: false, isSigner: false },
])
.instruction();
}
//
// Serum3 instructions
//
@ -422,160 +52,6 @@ export async function withdrawIx(
// .rpc();
// }
export async function serum3RegisterMarket(
client: MangoClient,
groupPk: PublicKey,
adminPk: PublicKey,
serumProgramPk: PublicKey,
serumMarketExternalPk: PublicKey,
quoteBankPk: PublicKey,
baseBankPk: PublicKey,
payer: Keypair,
marketIndex: number,
): Promise<void> {
const tx = new Transaction();
const ix = await serum3RegisterMarketIx(
client,
groupPk,
adminPk,
serumProgramPk,
serumMarketExternalPk,
quoteBankPk,
baseBankPk,
payer,
marketIndex,
);
tx.add(ix);
await client.program.provider.send(tx, [payer]);
}
export async function serum3RegisterMarketIx(
client: MangoClient,
groupPk: PublicKey,
adminPk: PublicKey,
serumProgramPk: PublicKey,
serumMarketExternalPk: PublicKey,
quoteBankPk: PublicKey,
baseBankPk: PublicKey,
payer: Keypair,
marketIndex: number,
): Promise<TransactionInstruction> {
return await client.program.methods
.serum3RegisterMarket(marketIndex)
.accounts({
group: groupPk,
admin: adminPk,
serumProgram: serumProgramPk,
serumMarketExternal: serumMarketExternalPk,
quoteBank: quoteBankPk,
baseBank: baseBankPk,
payer: payer.publicKey,
})
.instruction();
}
export async function getSerum3MarketForBaseAndQuote(
client: MangoClient,
groupPk: PublicKey,
baseTokenIndex: number,
quoteTokenIndex: number,
): Promise<Serum3Market[]> {
const bbuf = Buffer.alloc(2);
bbuf.writeUInt16LE(baseTokenIndex);
const qbuf = Buffer.alloc(2);
qbuf.writeUInt16LE(quoteTokenIndex);
const bumpfbuf = Buffer.alloc(1);
bumpfbuf.writeUInt8(255);
return (
await client.program.account.serum3Market.all([
{
memcmp: {
bytes: groupPk.toBase58(),
offset: 8,
},
},
{
memcmp: {
bytes: bs58.encode(bbuf),
offset: 106,
},
},
{
memcmp: {
bytes: bs58.encode(qbuf),
offset: 108,
},
},
])
).map((tuple) => Serum3Market.from(tuple.publicKey, tuple.account));
}
//
// Oracle
//
export async function createStubOracle(
client: MangoClient,
groupPk: PublicKey,
adminPk: PublicKey,
tokenMintPk: PublicKey,
payer: Keypair,
staticPrice: number,
): Promise<void> {
return await client.program.methods
.createStubOracle({ val: I80F48.fromNumber(staticPrice).getData() })
.accounts({
group: groupPk,
admin: adminPk,
tokenMint: tokenMintPk,
payer: payer.publicKey,
})
.signers([payer])
.rpc();
}
export async function setStubOracle(
client: MangoClient,
groupPk: PublicKey,
adminPk: PublicKey,
tokenMintPk: PublicKey,
payer: Keypair,
staticPrice: number,
): Promise<void> {
return await client.program.methods
.setStubOracle({ val: new BN(staticPrice) })
.accounts({
group: groupPk,
admin: adminPk,
tokenMint: tokenMintPk,
payer: payer.publicKey,
})
.signers([payer])
.rpc();
}
export async function getStubOracleForGroupAndMint(
client: MangoClient,
groupPk: PublicKey,
mintPk: PublicKey,
): Promise<StubOracle[]> {
return (
await client.program.account.stubOracle.all([
{
memcmp: {
bytes: groupPk.toBase58(),
offset: 8,
},
},
{
memcmp: {
bytes: mintPk.toBase58(),
offset: 40,
},
},
])
).map((pa) => StubOracle.from(pa.publicKey, pa.account));
}

File diff suppressed because it is too large Load Diff

View File

@ -1,75 +0,0 @@
import { I80F48, I80F48Dto } from './I80F48';
import { PublicKey } from '@solana/web3.js';
export class Bank {
public depositIndex: I80F48;
public borrowIndex: I80F48;
static from(
publicKey: PublicKey,
obj: {
group: PublicKey;
mint: PublicKey;
vault: PublicKey;
oracle: PublicKey;
depositIndex: I80F48Dto;
borrowIndex: I80F48Dto;
indexedTotalDeposits: I80F48Dto;
indexedTotalBorrows: I80F48Dto;
maintAssetWeight: I80F48Dto;
initAssetWeight: I80F48Dto;
maintLiabWeight: I80F48Dto;
initLiabWeight: I80F48Dto;
liquidationFee: I80F48Dto;
dust: Object;
tokenIndex: number;
},
) {
return new Bank(
publicKey,
obj.group,
obj.mint,
obj.vault,
obj.oracle,
obj.depositIndex,
obj.borrowIndex,
obj.indexedTotalDeposits,
obj.indexedTotalBorrows,
obj.maintAssetWeight,
obj.initAssetWeight,
obj.maintLiabWeight,
obj.initLiabWeight,
obj.liquidationFee,
obj.dust,
obj.tokenIndex,
);
}
constructor(
public publicKey: PublicKey,
group: PublicKey,
mint: PublicKey,
public vault: PublicKey,
oracle: PublicKey,
depositIndex: I80F48Dto,
borrowIndex: I80F48Dto,
indexedTotalDeposits: I80F48Dto,
indexedTotalBorrows: I80F48Dto,
maintAssetWeight: I80F48Dto,
initAssetWeight: I80F48Dto,
maintLiabWeight: I80F48Dto,
initLiabWeight: I80F48Dto,
liquidationFee: I80F48Dto,
dust: Object,
public tokenIndex: number,
) {
this.depositIndex = I80F48.from(depositIndex);
this.borrowIndex = I80F48.from(borrowIndex);
}
toString(): string {
return `Bank ${
this.tokenIndex
} deposit index - ${this.depositIndex.toNumber()}, borrow index - ${this.borrowIndex.toNumber()}`;
}
}

View File

@ -1,9 +0,0 @@
import { PublicKey } from '@solana/web3.js';
export class Group {
static from(publicKey: PublicKey, obj: { admin: PublicKey }): Group {
return new Group(publicKey, obj.admin);
}
constructor(public publicKey: PublicKey, public admin: PublicKey) {}
}

View File

@ -1,95 +0,0 @@
import { PublicKey } from '@solana/web3.js';
import { Bank } from './bank';
import { I80F48, I80F48Dto } from './I80F48';
export class TokenAccount {
static from(dto: TokenAccountDto) {
return new TokenAccount(
I80F48.from(dto.indexedValue),
dto.tokenIndex,
dto.inUseCount,
);
}
constructor(
public indexedValue: I80F48,
public tokenIndex: number,
public inUseCount: number,
) {}
}
export class TokenAccountDto {
constructor(
public indexedValue: I80F48Dto,
public tokenIndex: number,
public inUseCount: number,
public reserved: number[],
) {}
}
export class MangoAccount {
public tokens: TokenAccount[];
static from(
publicKey: PublicKey,
obj: {
group: PublicKey;
owner: PublicKey;
delegate: PublicKey;
tokens: unknown;
serum3: Object;
perps: unknown;
beingLiquidated: number;
isBankrupt: number;
accountNum: number;
bump: number;
reserved: number[];
},
) {
return new MangoAccount(
publicKey,
obj.group,
obj.owner,
obj.delegate,
obj.tokens as { values: TokenAccountDto[] },
obj.serum3,
obj.perps,
obj.beingLiquidated,
obj.isBankrupt,
obj.accountNum,
obj.bump,
obj.reserved,
);
}
constructor(
public publicKey: PublicKey,
group: PublicKey,
owner: PublicKey,
delegate: PublicKey,
tokens: { values: TokenAccountDto[] },
serum3: Object,
perps: unknown,
beingLiquidated: number,
isBankrupt: number,
accountNum: number,
bump: number,
reserved: number[],
) {
this.tokens = tokens.values.map((dto) => TokenAccount.from(dto));
}
find(tokenIndex: number): TokenAccount | undefined {
return this.tokens.find((ta) => ta.tokenIndex == tokenIndex);
}
getNativeDeposit(bank: Bank): I80F48 {
const ta = this.find(bank.tokenIndex);
return bank.depositIndex.mul(ta?.indexedValue!);
}
getNativeBorrow(bank: Bank): I80F48 {
const ta = this.find(bank.tokenIndex);
return bank.borrowIndex.mul(ta?.indexedValue!);
}
}

View File

@ -1,38 +0,0 @@
import { I80F48, I80F48Dto } from './I80F48';
import { PublicKey } from '@solana/web3.js';
import BN from 'bn.js';
export class StubOracle {
public price: I80F48;
public lastUpdated: number;
static from(
publicKey: PublicKey,
obj: {
group: PublicKey;
mint: PublicKey;
price: I80F48Dto;
lastUpdated: BN;
reserved: unknown;
},
): StubOracle {
return new StubOracle(
publicKey,
obj.group,
obj.mint,
obj.price,
obj.lastUpdated,
);
}
constructor(
public publicKey: PublicKey,
public group: PublicKey,
public mint: PublicKey,
price: I80F48Dto,
lastUpdated: BN,
) {
this.price = I80F48.from(price);
this.lastUpdated = lastUpdated.toNumber();
}
}

View File

@ -1,37 +0,0 @@
import { PublicKey } from '@solana/web3.js';
export class Serum3Market {
static from(
publicKey: PublicKey,
obj: {
group: PublicKey;
serumProgram: PublicKey;
serumMarketExternal: PublicKey;
marketIndex: number;
baseTokenIndex: number;
quoteTokenIndex: number;
bump: number;
reserved: unknown;
},
): Serum3Market {
return new Serum3Market(
publicKey,
obj.group,
obj.serumProgram,
obj.serumMarketExternal,
obj.marketIndex,
obj.baseTokenIndex,
obj.quoteTokenIndex,
);
}
constructor(
public publicKey: PublicKey,
public group: PublicKey,
public serumProgram: PublicKey,
public serumMarketExternal: PublicKey,
public marketIndex: number,
public baseTokenIndex: number,
public quoteTokenIndex: number,
) {}
}