Added PartialLiquidate and ForceCancelOrders

This commit is contained in:
dd 2021-04-05 16:22:41 -04:00
parent cc73a0c2bc
commit 52ce8a1665
3 changed files with 166 additions and 132 deletions

View File

@ -188,8 +188,6 @@ export class MarginAccount {
return nativeToUi(this.getNativeBorrow(mangoGroup, tokenIndex), mangoGroup.mintDecimals[tokenIndex])
}
async loadOpenOrders(
connection: Connection,
dexProgramId: PublicKey
@ -772,6 +770,92 @@ export class MangoClient {
...tokenAccs.map( (pubkey) => ( { isSigner: false, isWritable: true, pubkey })),
]
const data = encodeMangoInstruction({Liquidate: {depositQuantities: depositsBN}})
const instruction = new TransactionInstruction( { keys, data, programId })
const transaction = new Transaction()
transaction.add(instruction)
const additionalSigners = []
return await this.sendTransaction(connection, transaction, liqor, additionalSigners)
}
async forceCancelOrders(
connection: Connection,
programId: PublicKey,
mangoGroup: MangoGroup,
liqeeMarginAccount: MarginAccount,
liqor: Account,
spotMarket: Market,
): Promise<TransactionSignature> {
const marketIndex = mangoGroup.getMarketIndex(spotMarket)
const dexSigner = await PublicKey.createProgramAddress(
[
spotMarket.publicKey.toBuffer(),
spotMarket['_decoded'].vaultSignerNonce.toArrayLike(Buffer, 'le', 8)
],
spotMarket.programId
)
const keys = [
{ isSigner: false, isWritable: true, pubkey: mangoGroup.publicKey},
{ isSigner: true, isWritable: false, pubkey: liqor.publicKey },
{ isSigner: false, isWritable: true, pubkey: liqeeMarginAccount.publicKey },
{ isSigner: false, isWritable: true, pubkey: mangoGroup.vaults[marketIndex] },
{ isSigner: false, isWritable: true, pubkey: mangoGroup.vaults[NUM_TOKENS-1] },
{ isSigner: false, isWritable: true, pubkey: spotMarket.publicKey },
{ isSigner: false, isWritable: true, pubkey: spotMarket.bidsAddress },
{ isSigner: false, isWritable: true, pubkey: spotMarket.asksAddress },
{ isSigner: false, isWritable: false, pubkey: mangoGroup.signerKey },
{ isSigner: false, isWritable: true, pubkey: spotMarket['_decoded'].eventQueue },
{ isSigner: false, isWritable: true, pubkey: spotMarket['_decoded'].baseVault },
{ isSigner: false, isWritable: true, pubkey: spotMarket['_decoded'].quoteVault },
{ isSigner: false, isWritable: false, pubkey: dexSigner },
{ isSigner: false, isWritable: false, pubkey: TOKEN_PROGRAM_ID },
{ isSigner: false, isWritable: false, pubkey: mangoGroup.dexProgramId },
{ isSigner: false, isWritable: false, pubkey: SYSVAR_CLOCK_PUBKEY },
...liqeeMarginAccount.openOrders.map( (pubkey) => ( { isSigner: false, isWritable: true, pubkey })),
...mangoGroup.oracles.map( (pubkey) => ( { isSigner: false, isWritable: false, pubkey })),
]
const data = encodeMangoInstruction({ForceCancelOrders: {}})
const instruction = new TransactionInstruction( { keys, data, programId })
const transaction = new Transaction()
transaction.add(instruction)
const additionalSigners = []
return await this.sendTransaction(connection, transaction, liqor, additionalSigners)
}
async partialLiquidate(
connection: Connection,
programId: PublicKey,
mangoGroup: MangoGroup,
liqeeMarginAccount: MarginAccount,
liqor: Account,
liqorInTokenWallet: PublicKey,
liqorOutTokenWallet: PublicKey,
inTokenIndex: number,
outTokenIndex: number,
maxDeposit: number
): Promise<TransactionSignature> {
const maxDepositBn: BN = uiToNative(maxDeposit, mangoGroup.mintDecimals[inTokenIndex])
const keys = [
{ isSigner: false, isWritable: true, pubkey: mangoGroup.publicKey},
{ isSigner: true, isWritable: false, pubkey: liqor.publicKey },
{ isSigner: false, isWritable: true, pubkey: liqorInTokenWallet },
{ isSigner: false, isWritable: true, pubkey: liqorOutTokenWallet },
{ isSigner: false, isWritable: true, pubkey: liqeeMarginAccount.publicKey },
{ isSigner: false, isWritable: true, pubkey: mangoGroup.vaults[inTokenIndex] },
{ isSigner: false, isWritable: true, pubkey: mangoGroup.vaults[outTokenIndex] },
{ isSigner: false, isWritable: false, pubkey: mangoGroup.signerKey },
{ isSigner: false, isWritable: false, pubkey: SYSVAR_CLOCK_PUBKEY },
...liqeeMarginAccount.openOrders.map( (pubkey) => ( { isSigner: false, isWritable: false, pubkey })),
...mangoGroup.oracles.map( (pubkey) => ( { isSigner: false, isWritable: false, pubkey })),
]
const data = encodeMangoInstruction({PartialLiquidate: {maxDeposit: maxDepositBn}})
const instruction = new TransactionInstruction( { keys, data, programId })
@ -783,6 +867,7 @@ export class MangoClient {
return await this.sendTransaction(connection, transaction, liqor, additionalSigners)
}
async depositSrm(
connection: Connection,
programId: PublicKey,

View File

@ -1,141 +1,87 @@
import fs from 'fs';
import { homedir } from 'os';
import { MangoClient, MangoGroup } from './client';
import IDS from './ids.json';
import { Connection, PublicKey, Account } from '@solana/web3.js';
import { nativeToUi } from './utils';
import { Account, Connection, PublicKey } from '@solana/web3.js';
export { MangoClient, MangoGroup, MarginAccount, tokenToDecimals } from './client';
export { MangoIndexLayout, MarginAccountLayout, MangoGroupLayout } from './layout';
export * from './layout';
export * from './utils'
export { IDS }
import { homedir } from 'os'
import * as fs from 'fs';
import { Aggregator } from './schema';
import { nativeToUi, sleep, uiToNative } from './utils';
import { NUM_MARKETS, NUM_TOKENS } from './layout';
export {
MangoClient,
MangoGroup,
MarginAccount,
tokenToDecimals,
} from './client';
export {
MangoIndexLayout,
MarginAccountLayout,
MangoGroupLayout,
} from './layout';
export * from './layout';
export * from './utils';
export { IDS };
// async function tests() {
// const cluster = 'devnet';
// const cluster = "mainnet-beta";
// const client = new MangoClient();
// const clusterIds = IDS[cluster];
// const connection = new Connection(IDS.cluster_urls[cluster], 'singleGossip');
// const mangoGroupPk = new PublicKey(
// clusterIds.mango_groups['BTC_ETH_USDT'].mango_group_pk,
// );
// const clusterIds = IDS[cluster]
//
// const connection = new Connection(IDS.cluster_urls[cluster], 'singleGossip')
// const mangoGroupPk = new PublicKey(clusterIds.mango_groups['BTC_ETH_USDT'].mango_group_pk);
// const mangoProgramId = new PublicKey(clusterIds.mango_program_id);
// const keyPairPath =
// process.env.KEYPAIR || homedir() + '/.config/solana/id.json';
// const payer = new Account(JSON.parse(fs.readFileSync(keyPairPath, 'utf-8')));
// async function testSolink() {
// const oraclePk = new PublicKey(IDS[cluster].oracles['ETH/USDT'])
// const agg = await Aggregator.loadWithConnection(oraclePk, connection)
// // const agg = await Aggregator.loadWithConnection(oraclePk, connection)
// console.log(agg.answer.median.toNumber(), agg.answer.updatedAt.toNumber(), agg.round.id.toNumber())
// }
// async function testDepositSrm() {
// const srmVaultPk = new PublicKey(clusterIds['mango_groups']['BTC_ETH_USDT']['srm_vault_pk'])
// const mangoGroup = await client.getMangoGroup(connection, mangoGroupPk, srmVaultPk)
// const srmAccountPk = new PublicKey("6utvndL8EEjpwK5QVtguErncQEPVbkuyABmXu6FeygeV")
// const mangoSrmAccountPk = await client.depositSrm(connection, mangoProgramId, mangoGroup, payer, srmAccountPk, 100)
// console.log(mangoSrmAccountPk.toBase58())
// await sleep(2000)
// const mangoSrmAccount = await client.getMangoSrmAccount(connection, mangoSrmAccountPk)
// const txid = await client.withdrawSrm(connection, mangoProgramId, mangoGroup, mangoSrmAccount, payer, srmAccountPk, 50)
// console.log('success', txid)
// }
// async function getMarginAccountDetails() {
// const mangoGroup = await client.getMangoGroup(connection, mangoGroupPk);
// const marginAccountPk = new PublicKey(
// '5pmKq6D67vdUam6KMoMNa1euaqDCScqCehtcTyhC4Koh',
// );
// console.log('ma:', mangoGroup.dexProgramId.toString());
// const marginAccount = await client.getMarginAccount(
// connection,
// marginAccountPk,
// mangoGroup.dexProgramId,
// );
// const prices = await mangoGroup.getPrices(connection);
// console.log(marginAccount.toPrettyString(mangoGroup, prices));
// for (let i = 0; i < NUM_TOKENS; i++) {
// console.log(
// i,
// marginAccount.getUiDeposit(mangoGroup, i),
// marginAccount.getUiBorrow(mangoGroup, i),
// );
//
// const keyPairPath = process.env.KEYPAIR || homedir() + '/.config/solana/id.json'
// const payer = new Account(JSON.parse(fs.readFileSync(keyPairPath, 'utf-8')))
//
//
// async function testSolink() {
//
// const oraclePk = new PublicKey(IDS[cluster].oracles['ETH/USDT'])
// const agg = await Aggregator.loadWithConnection(oraclePk, connection)
//
// // const agg = await Aggregator.loadWithConnection(oraclePk, connection)
// console.log(agg.answer.median.toNumber(), agg.answer.updatedAt.toNumber(), agg.round.id.toNumber())
//
// }
// for (let i = 0; i < NUM_MARKETS; i++) {
// let openOrdersAccount = marginAccount.openOrdersAccounts[i];
// if (openOrdersAccount === undefined) {
// continue;
//
// async function testDepositSrm() {
// const srmVaultPk = new PublicKey(clusterIds['mango_groups']['BTC_ETH_USDT']['srm_vault_pk'])
// const mangoGroup = await client.getMangoGroup(connection, mangoGroupPk, srmVaultPk)
// const srmAccountPk = new PublicKey("6utvndL8EEjpwK5QVtguErncQEPVbkuyABmXu6FeygeV")
// const mangoSrmAccountPk = await client.depositSrm(connection, mangoProgramId, mangoGroup, payer, srmAccountPk, 100)
// console.log(mangoSrmAccountPk.toBase58())
// await sleep(2000)
// const mangoSrmAccount = await client.getMangoSrmAccount(connection, mangoSrmAccountPk)
// const txid = await client.withdrawSrm(connection, mangoProgramId, mangoGroup, mangoSrmAccount, payer, srmAccountPk, 50)
// console.log('success', txid)
// }
//
// async function getMarginAccountDetails() {
// const mangoGroup = await client.getMangoGroup(connection, mangoGroupPk);
// const marginAccountPk = new PublicKey("BSFaizvArm1dpVGwJvrsqbWTpT8nh3xD7ERrdHuaY1C1")
// const marginAccount = await client.getMarginAccount(connection, marginAccountPk, mangoGroup.dexProgramId)
// const prices = await mangoGroup.getPrices(connection)
//
// console.log(marginAccount.toPrettyString(mangoGroup, prices))
//
// for (let i = 0; i < NUM_MARKETS; i++) {
// let openOrdersAccount = marginAccount.openOrdersAccounts[i]
// if (openOrdersAccount === undefined) {
// continue
// }
//
// for (const oid of openOrdersAccount.orders) {
// console.log(oid.toString())
// }
// console.log(i,
// nativeToUi(openOrdersAccount.quoteTokenTotal.toNumber(), mangoGroup.mintDecimals[NUM_MARKETS]),
// nativeToUi(openOrdersAccount.quoteTokenFree.toNumber(), mangoGroup.mintDecimals[NUM_MARKETS]),
//
// nativeToUi(openOrdersAccount.baseTokenTotal.toNumber(), mangoGroup.mintDecimals[i]),
// nativeToUi(openOrdersAccount.baseTokenFree.toNumber(), mangoGroup.mintDecimals[i])
//
// )
// }
// console.log(
// i,
// nativeToUi(
// openOrdersAccount.quoteTokenTotal.toNumber(),
// mangoGroup.mintDecimals[NUM_MARKETS],
// ),
// nativeToUi(
// openOrdersAccount.baseTokenTotal.toNumber(),
// mangoGroup.mintDecimals[i],
// ),
// );
//
// }
// await getMarginAccountDetails()
// // await testSolink()
// // testDepositSrm()
// }
// async function testDeposit() {
// const mangoGroup = await client.getMangoGroup(connection, mangoGroupPk);
// const marginAccountPk = new PublicKey(
// '5pmKq6D67vdUam6KMoMNa1euaqDCScqCehtcTyhC4Koh',
// );
// const marginAccount = await client.getMarginAccount(
// connection,
// marginAccountPk,
// mangoGroup.dexProgramId,
// );
// console.log('starting deposit');
// try {
// await client.deposit(
// connection,
// mangoProgramId,
// mangoGroup,
// marginAccount,
// payer,
// new PublicKey('7KBVenLz5WNH4PA5MdGkJNpDDyNKnBQTwnz1UqJv9GUm'),
// new PublicKey('FNYRWcdcJn1YjWstQ7SGmSizgmERECfoknwk2cf1sQMe'),
// 1000,
// );
// } catch (e) {
// console.log('deposit error:', e);
// }
// console.log('deposit complete');
// }
// await testDeposit();
// await getMarginAccountDetails();
// await testSolink()
// testDepositSrm()
// }
// tests();
//
// tests()

View File

@ -155,7 +155,8 @@ export const MarginAccountLayout = struct([
seq(U64F64(), NUM_TOKENS, 'deposits'),
seq(U64F64(), NUM_TOKENS, 'borrows'),
seq(publicKeyLayout(), NUM_MARKETS, 'openOrders'),
seq(u8(), 8, 'padding')
u8('beingLiquidated'),
seq(u8(), 7, 'padding')
]);
export const MangoSrmAccountLayout = struct([
@ -260,6 +261,8 @@ MangoInstructionLayout.addVariant(14,
),
'PlaceAndSettle'
)
MangoInstructionLayout.addVariant(15, struct([]), 'ForceCancelOrders')
MangoInstructionLayout.addVariant(16, struct([u64('maxDeposit')]), 'PartialLiquidate')
// @ts-ignore
const instructionMaxSpan = Math.max(...Object.values(MangoInstructionLayout.registry).map((r) => r.span));