2023-02-21 23:36:59 -08:00
import { AnchorProvider , BN , Wallet } from '@coral-xyz/anchor' ;
2022-07-05 10:31:47 -07:00
import { Connection , Keypair , PublicKey } from '@solana/web3.js' ;
2022-10-07 04:52:04 -07:00
import { expect } from 'chai' ;
2022-04-07 08:16:46 -07:00
import fs from 'fs' ;
2023-02-21 23:36:59 -08:00
import { Group } from '../src/accounts/group' ;
import { HealthType } from '../src/accounts/mangoAccount' ;
import { PerpOrderSide , PerpOrderType } from '../src/accounts/perp' ;
import { MangoClient } from '../src/client' ;
import { MANGO_V4_ID } from '../src/constants' ;
import { toUiDecimalsForQuote } from '../src/utils' ;
2022-04-07 08:16:46 -07:00
//
2022-04-07 10:52:13 -07:00
// An example for users based on high level api i.e. the client
2022-04-13 00:09:17 -07:00
// Create
// process.env.USER_KEYPAIR - mango account owner keypair path
// process.env.ADMIN_KEYPAIR - group admin keypair path (useful for automatically finding the group)
2022-04-07 08:16:46 -07:00
//
2022-07-04 06:52:32 -07:00
// This script deposits some tokens, places some serum orders, cancels them, places some perp orders
//
2022-08-17 23:48:45 -07:00
const DEVNET_MINTS = new Map ( [
[ 'USDC' , '8FRFC6MoGGkMFQwngccyu69VnYbzykGeez7ignHVAFSN' ] , // use devnet usdc
[ 'BTC' , '3UNBZ6o52WTWwjac2kPUb4FyodhU1vFkRJheu1Sh2TvU' ] ,
[ 'SOL' , 'So11111111111111111111111111111111111111112' ] ,
[ 'ORCA' , 'orcarKHSqC5CDDsGbho8GKvwExejWHxTqGzXgcewB9L' ] ,
[ 'MNGO' , 'Bb9bsTQa1bGEtQ5KagGkvSHyuLqDWumFUcRqFusFNJWC' ] ,
] ) ;
2022-08-31 02:36:44 -07:00
export const DEVNET_SERUM3_MARKETS = new Map ( [
[ 'BTC/USDC' , new PublicKey ( 'DW83EpHFywBxCHmyARxwj3nzxJd7MUdSeznmrdzZKNZB' ) ] ,
[ 'SOL/USDC' , new PublicKey ( '5xWpt56U1NCuHoAEtpLeUrQcxDkEpNfScjfLFaRzLPgR' ) ] ,
] ) ;
2022-08-17 23:48:45 -07:00
2022-07-13 10:17:26 -07:00
const GROUP_NUM = Number ( process . env . GROUP_NUM || 0 ) ;
2022-04-07 08:16:46 -07:00
async function main() {
2022-05-18 08:16:14 -07:00
const options = AnchorProvider . defaultOptions ( ) ;
2022-04-07 08:16:46 -07:00
const connection = new Connection (
'https://mango.devnet.rpcpool.com' ,
options ,
) ;
const user = Keypair . fromSecretKey (
Buffer . from (
JSON . parse ( fs . readFileSync ( process . env . USER_KEYPAIR ! , 'utf-8' ) ) ,
) ,
) ;
const userWallet = new Wallet ( user ) ;
2022-05-18 08:16:14 -07:00
const userProvider = new AnchorProvider ( connection , userWallet , options ) ;
2022-06-11 04:49:45 -07:00
const client = await MangoClient . connect (
userProvider ,
'devnet' ,
MANGO_V4_ID [ 'devnet' ] ,
2022-11-04 07:35:40 -07:00
{
idsSource : 'get-program-accounts' ,
} ,
2022-06-11 04:49:45 -07:00
) ;
2022-04-07 08:16:46 -07:00
console . log ( ` User ${ userWallet . publicKey . toBase58 ( ) } ` ) ;
2022-04-07 10:53:20 -07:00
// fetch group
2022-04-12 23:48:35 -07:00
const admin = Keypair . fromSecretKey (
Buffer . from (
JSON . parse ( fs . readFileSync ( process . env . ADMIN_KEYPAIR ! , 'utf-8' ) ) ,
) ,
) ;
2022-08-17 23:48:45 -07:00
const group = await client . getGroupForCreator ( admin . publicKey , GROUP_NUM ) ;
2022-04-09 12:18:07 -07:00
2022-04-07 10:53:20 -07:00
// create + fetch account
2022-04-13 00:09:17 -07:00
console . log ( ` Creating mangoaccount... ` ) ;
2022-09-30 03:16:24 -07:00
let mangoAccount = ( await client . getOrCreateMangoAccount ( group ) ) ! ;
2022-10-07 04:52:04 -07:00
await mangoAccount . reload ( client ) ;
2022-09-01 00:56:17 -07:00
if ( ! mangoAccount ) {
throw new Error ( ` MangoAccount not found for user ${ user . publicKey } ` ) ;
}
2022-04-13 00:09:17 -07:00
console . log ( ` ...created/found mangoAccount ${ mangoAccount . publicKey } ` ) ;
2022-08-31 02:36:44 -07:00
2022-09-20 03:57:01 -07:00
// set delegate, and change name
2022-09-29 06:51:09 -07:00
if ( true ) {
2022-07-05 10:31:47 -07:00
console . log ( ` ...changing mango account name, and setting a delegate ` ) ;
2022-10-07 04:52:04 -07:00
const newName = 'my_changed_name' ;
2022-07-05 10:31:47 -07:00
const randomKey = new PublicKey (
'4ZkS7ZZkxfsC3GtvvsHP3DFcUeByU9zzZELS4r8HCELo' ,
) ;
2022-08-04 00:53:38 -07:00
2022-10-07 04:52:04 -07:00
await client . editMangoAccount ( group , mangoAccount , newName , randomKey ) ;
2022-09-29 06:51:09 -07:00
await mangoAccount . reload ( client ) ;
2022-10-07 04:52:04 -07:00
expect ( mangoAccount . name ) . deep . equals ( newName ) ;
expect ( mangoAccount . delegate ) . deep . equals ( randomKey ) ;
2022-07-05 10:31:47 -07:00
2022-10-07 04:52:04 -07:00
const oldName = 'my_mango_account' ;
2022-07-05 10:31:47 -07:00
console . log ( ` ...resetting mango account name, and re-setting a delegate ` ) ;
2022-07-13 10:18:55 -07:00
await client . editMangoAccount (
group ,
mangoAccount ,
2022-10-07 04:52:04 -07:00
oldName ,
2022-07-13 10:18:55 -07:00
PublicKey . default ,
) ;
2022-09-29 06:51:09 -07:00
await mangoAccount . reload ( client ) ;
2022-10-07 04:52:04 -07:00
expect ( mangoAccount . name ) . deep . equals ( oldName ) ;
expect ( mangoAccount . delegate ) . deep . equals ( PublicKey . default ) ;
2022-07-05 10:31:47 -07:00
}
2022-07-04 03:29:35 -07:00
2022-09-20 03:57:01 -07:00
// expand account
2022-10-07 04:52:04 -07:00
if (
mangoAccount . tokens . length < 16 ||
mangoAccount . serum3 . length < 8 ||
mangoAccount . perps . length < 8 ||
2022-11-21 10:34:41 -08:00
mangoAccount . perpOpenOrders . length < 8
2022-10-07 04:52:04 -07:00
) {
2022-08-07 05:16:06 -07:00
console . log (
2022-11-21 10:34:41 -08:00
` ...expanding mango account to max 16 token positions, 8 serum3, 8 perp position and 8 perp oo slots, previous (tokens ${ mangoAccount . tokens . length } , serum3 ${ mangoAccount . serum3 . length } , perps ${ mangoAccount . perps . length } , perps oo ${ mangoAccount . perpOpenOrders . length } ) ` ,
2022-08-07 05:16:06 -07:00
) ;
2022-11-21 10:34:41 -08:00
let sig = await client . expandMangoAccount ( group , mangoAccount , 16 , 8 , 8 , 8 ) ;
2022-10-07 04:52:04 -07:00
console . log ( ` sig https://explorer.solana.com/tx/ ${ sig } ?cluster=devnet ` ) ;
2022-09-29 06:51:09 -07:00
await mangoAccount . reload ( client ) ;
2022-10-07 04:52:04 -07:00
expect ( mangoAccount . tokens . length ) . equals ( 16 ) ;
expect ( mangoAccount . serum3 . length ) . equals ( 8 ) ;
expect ( mangoAccount . perps . length ) . equals ( 8 ) ;
2022-11-21 10:34:41 -08:00
expect ( mangoAccount . perpOpenOrders . length ) . equals ( 8 ) ;
2022-08-07 05:16:06 -07:00
}
2022-09-20 03:57:01 -07:00
// deposit and withdraw
2022-09-27 06:13:53 -07:00
if ( true ) {
2022-10-07 04:52:04 -07:00
console . log ( ` ...depositing 50 USDC, 1 SOL, 1 MNGO ` ) ;
2022-08-04 08:35:05 -07:00
2022-10-07 04:52:04 -07:00
// deposit USDC
let oldBalance = mangoAccount . getTokenBalance (
group . getFirstBankByMint ( new PublicKey ( DEVNET_MINTS . get ( 'USDC' ) ! ) ) ,
) ;
await client . tokenDeposit (
group ,
mangoAccount ,
new PublicKey ( DEVNET_MINTS . get ( 'USDC' ) ! ) ,
50 ,
) ;
await mangoAccount . reload ( client ) ;
let newBalance = mangoAccount . getTokenBalance (
group . getFirstBankByMint ( new PublicKey ( DEVNET_MINTS . get ( 'USDC' ) ! ) ) ,
) ;
expect ( toUiDecimalsForQuote ( newBalance . sub ( oldBalance ) ) . toString ( ) ) . equals (
'50' ,
) ;
2022-08-31 02:36:44 -07:00
2022-10-07 04:52:04 -07:00
// deposit SOL
await client . tokenDeposit (
group ,
mangoAccount ,
new PublicKey ( DEVNET_MINTS . get ( 'SOL' ) ! ) ,
1 ,
) ;
await mangoAccount . reload ( client ) ;
2022-08-31 02:36:44 -07:00
2022-10-07 04:52:04 -07:00
// deposit MNGO
await client . tokenDeposit (
group ,
mangoAccount ,
new PublicKey ( DEVNET_MINTS . get ( 'MNGO' ) ! ) ,
1 ,
) ;
await mangoAccount . reload ( client ) ;
2022-07-25 07:07:53 -07:00
2022-10-07 04:52:04 -07:00
// withdraw USDC
console . log ( ` ...withdrawing 1 USDC ` ) ;
oldBalance = mangoAccount . getTokenBalance (
group . getFirstBankByMint ( new PublicKey ( DEVNET_MINTS . get ( 'USDC' ) ! ) ) ,
) ;
await client . tokenWithdraw (
group ,
mangoAccount ,
new PublicKey ( DEVNET_MINTS . get ( 'USDC' ) ! ) ,
1 ,
true ,
) ;
await mangoAccount . reload ( client ) ;
newBalance = mangoAccount . getTokenBalance (
group . getFirstBankByMint ( new PublicKey ( DEVNET_MINTS . get ( 'USDC' ) ! ) ) ,
) ;
expect ( toUiDecimalsForQuote ( oldBalance . sub ( newBalance ) ) . toString ( ) ) . equals (
'1' ,
) ;
2022-08-31 02:36:44 -07:00
2022-10-07 04:52:04 -07:00
console . log ( ` ...depositing 0.0005 BTC ` ) ;
await client . tokenDeposit (
group ,
mangoAccount ,
new PublicKey ( DEVNET_MINTS . get ( 'BTC' ) ! ) ,
0.0005 ,
) ;
await mangoAccount . reload ( client ) ;
2022-08-31 02:36:44 -07:00
}
2022-04-12 12:38:59 -07:00
2022-12-02 06:48:43 -08:00
// Note: Disable for now until we have openbook devnet markets
// if (true) {
// // serum3
// const asks = await group.loadSerum3AsksForMarket(
// client,
// DEVNET_SERUM3_MARKETS.get('BTC/USDC')!,
// );
// const lowestAsk = Array.from(asks!)[0];
// const bids = await group.loadSerum3BidsForMarket(
// client,
// DEVNET_SERUM3_MARKETS.get('BTC/USDC')!,
// );
// const highestBid = Array.from(bids!)![0];
// console.log(`...cancelling all existing serum3 orders`);
// if (
// Array.from(mangoAccount.serum3OosMapByMarketIndex.values()).length > 0
// ) {
// await client.serum3CancelAllOrders(
// group,
// mangoAccount,
// DEVNET_SERUM3_MARKETS.get('BTC/USDC')!,
// 10,
// );
// }
// let price = 20;
// let qty = 0.0001;
// console.log(
// `...placing serum3 bid which would not be settled since its relatively low then midprice at ${price} for ${qty}`,
// );
// await client.serum3PlaceOrder(
// group,
// mangoAccount,
// DEVNET_SERUM3_MARKETS.get('BTC/USDC')!,
// Serum3Side.bid,
// price,
// qty,
// Serum3SelfTradeBehavior.decrementTake,
// Serum3OrderType.limit,
// Date.now(),
// 10,
// );
// await mangoAccount.reload(client);
// let orders = await mangoAccount.loadSerum3OpenOrdersForMarket(
// client,
// group,
// DEVNET_SERUM3_MARKETS.get('BTC/USDC')!,
// );
// expect(orders[0].price).equals(20);
// expect(orders[0].size).equals(qty);
// price = lowestAsk.price + lowestAsk.price / 2;
// qty = 0.0001;
// console.log(
// `...placing serum3 bid way above midprice at ${price} for ${qty}`,
// );
// await client.serum3PlaceOrder(
// group,
// mangoAccount,
// DEVNET_SERUM3_MARKETS.get('BTC/USDC')!,
// Serum3Side.bid,
// price,
// qty,
// Serum3SelfTradeBehavior.decrementTake,
// Serum3OrderType.limit,
// Date.now(),
// 10,
// );
// await mangoAccount.reload(client);
// price = highestBid.price - highestBid.price / 2;
// qty = 0.0001;
// console.log(
// `...placing serum3 ask way below midprice at ${price} for ${qty}`,
// );
// await client.serum3PlaceOrder(
// group,
// mangoAccount,
// DEVNET_SERUM3_MARKETS.get('BTC/USDC')!,
// Serum3Side.ask,
// price,
// qty,
// Serum3SelfTradeBehavior.decrementTake,
// Serum3OrderType.limit,
// Date.now(),
// 10,
// );
// console.log(`...current own orders on OB`);
// orders = await mangoAccount.loadSerum3OpenOrdersForMarket(
// client,
// group,
// DEVNET_SERUM3_MARKETS.get('BTC/USDC')!,
// );
// for (const order of orders) {
// console.log(
// ` - order orderId ${order.orderId}, ${order.side}, ${order.price}, ${order.size}`,
// );
// console.log(` - cancelling order with ${order.orderId}`);
// await client.serum3CancelOrder(
// group,
// mangoAccount,
// DEVNET_SERUM3_MARKETS.get('BTC/USDC')!,
// order.side === 'buy' ? Serum3Side.bid : Serum3Side.ask,
// order.orderId,
// );
// }
// console.log(`...current own orders on OB`);
// orders = await mangoAccount.loadSerum3OpenOrdersForMarket(
// client,
// group,
// DEVNET_SERUM3_MARKETS.get('BTC/USDC')!,
// );
// for (const order of orders) {
// console.log(order);
// }
// console.log(`...settling funds`);
// await client.serum3SettleFunds(
// group,
// mangoAccount,
// DEVNET_SERUM3_MARKETS.get('BTC/USDC')!,
// );
// }
2022-06-11 04:49:45 -07:00
2022-09-27 06:13:53 -07:00
if ( true ) {
2022-09-29 06:51:09 -07:00
await mangoAccount . reload ( client ) ;
2022-07-04 03:29:35 -07:00
console . log (
2022-07-05 10:31:47 -07:00
'...mangoAccount.getEquity() ' +
2022-09-29 06:51:09 -07:00
toUiDecimalsForQuote ( mangoAccount . getEquity ( group ) ! . toNumber ( ) ) ,
2022-07-04 03:29:35 -07:00
) ;
console . log (
2022-07-05 10:31:47 -07:00
'...mangoAccount.getCollateralValue() ' +
2022-08-11 08:44:12 -07:00
toUiDecimalsForQuote (
2022-09-29 06:51:09 -07:00
mangoAccount . getCollateralValue ( group ) ! . toNumber ( ) ,
2022-07-13 10:18:55 -07:00
) ,
) ;
2022-07-04 03:29:35 -07:00
console . log (
2022-07-05 10:31:47 -07:00
'...mangoAccount.getAssetsVal() ' +
2022-08-13 10:36:09 -07:00
toUiDecimalsForQuote (
2022-09-29 06:51:09 -07:00
mangoAccount . getAssetsValue ( group , HealthType . init ) ! . toNumber ( ) ,
2022-08-13 10:36:09 -07:00
) ,
2022-07-04 03:29:35 -07:00
) ;
console . log (
2022-07-05 10:31:47 -07:00
'...mangoAccount.getLiabsVal() ' +
2022-08-13 10:36:09 -07:00
toUiDecimalsForQuote (
2022-09-29 06:51:09 -07:00
mangoAccount . getLiabsValue ( group , HealthType . init ) ! . toNumber ( ) ,
2022-08-13 10:36:09 -07:00
) ,
2022-07-04 03:29:35 -07:00
) ;
console . log (
2022-07-05 10:31:47 -07:00
'...mangoAccount.getMaxWithdrawWithBorrowForToken(group, "SOL") ' +
2022-08-11 08:44:12 -07:00
toUiDecimalsForQuote (
2022-09-20 03:57:01 -07:00
mangoAccount
. getMaxWithdrawWithBorrowForToken (
2022-08-17 23:48:45 -07:00
group ,
new PublicKey ( DEVNET_MINTS . get ( 'SOL' ) ! ) ,
2022-09-20 03:57:01 -07:00
) !
. toNumber ( ) ,
2022-07-04 03:29:35 -07:00
) ,
) ;
2022-08-31 02:36:44 -07:00
}
2022-09-27 06:13:53 -07:00
if ( true ) {
2022-08-31 02:36:44 -07:00
function getMaxSourceForTokenSwapWrapper ( src , tgt ) {
console . log (
` getMaxSourceForTokenSwap ${ src . padEnd ( 4 ) } ${ tgt . padEnd ( 4 ) } ` +
2022-09-23 02:43:26 -07:00
mangoAccount . getMaxSourceUiForTokenSwap (
group ,
group . banksMapByName . get ( src ) ! [ 0 ] . mint ,
group . banksMapByName . get ( tgt ) ! [ 0 ] . mint ,
1 ,
) ! ,
2022-08-31 02:36:44 -07:00
) ;
}
for ( const srcToken of Array . from ( group . banksMapByName . keys ( ) ) ) {
for ( const tgtToken of Array . from ( group . banksMapByName . keys ( ) ) ) {
getMaxSourceForTokenSwapWrapper ( srcToken , tgtToken ) ;
}
}
const maxQuoteForSerum3BidUi = mangoAccount . getMaxQuoteForSerum3BidUi (
group ,
DEVNET_SERUM3_MARKETS . get ( 'BTC/USDC' ) ! ,
) ;
console . log (
"...mangoAccount.getMaxQuoteForSerum3BidUi(group, 'BTC/USDC') " +
maxQuoteForSerum3BidUi ,
) ;
const maxBaseForSerum3AskUi = mangoAccount . getMaxBaseForSerum3AskUi (
group ,
DEVNET_SERUM3_MARKETS . get ( 'BTC/USDC' ) ! ,
) ;
console . log (
"...mangoAccount.getMaxBaseForSerum3AskUi(group, 'BTC/USDC') " +
maxBaseForSerum3AskUi ,
) ;
console . log (
` simHealthRatioWithSerum3BidUiChanges ${ mangoAccount . simHealthRatioWithSerum3BidUiChanges (
group ,
785 ,
DEVNET_SERUM3_MARKETS . get ( 'BTC/USDC' ) ! ,
) } ` ,
2022-07-04 03:29:35 -07:00
) ;
2022-08-31 02:36:44 -07:00
console . log (
` simHealthRatioWithSerum3AskUiChanges ${ mangoAccount . simHealthRatioWithSerum3AskUiChanges (
group ,
0.033 ,
DEVNET_SERUM3_MARKETS . get ( 'BTC/USDC' ) ! ,
) } ` ,
) ;
}
2022-09-20 03:57:01 -07:00
// perps
if ( true ) {
2022-09-23 02:43:26 -07:00
let sig ;
2022-11-21 10:34:41 -08:00
let perpMarket = group . getPerpMarketByName ( 'BTC-PERP' ) ;
2022-09-20 03:57:01 -07:00
const orders = await mangoAccount . loadPerpOpenOrdersForMarket (
client ,
group ,
2022-09-29 06:51:09 -07:00
perpMarket . perpMarketIndex ,
2022-07-04 03:29:35 -07:00
) ;
2022-09-20 03:57:01 -07:00
for ( const order of orders ) {
2022-09-23 02:43:26 -07:00
console . log (
` Current order - ${ order . uiPrice } ${ order . uiSize } ${ order . side } ` ,
) ;
2022-09-20 03:57:01 -07:00
}
console . log ( ` ...cancelling all perp orders ` ) ;
2022-09-29 06:51:09 -07:00
sig = await client . perpCancelAllOrders (
group ,
mangoAccount ,
perpMarket . perpMarketIndex ,
10 ,
) ;
2022-09-20 03:57:01 -07:00
console . log ( ` sig https://explorer.solana.com/tx/ ${ sig } ?cluster=devnet ` ) ;
2022-11-21 10:34:41 -08:00
// oracle pegged
try {
const clientId = Math . floor ( Math . random ( ) * 99999 ) ;
const price = group . banksMapByName . get ( 'BTC' ) ! [ 0 ] . uiPrice ! ;
console . log (
` ...placing perp pegged bid ${ clientId } at oracle price ${ perpMarket . uiPrice } ` ,
) ;
const sig = await client . perpPlaceOrderPegged (
group ,
mangoAccount ,
perpMarket . perpMarketIndex ,
PerpOrderSide . bid ,
- 5 ,
perpMarket . uiPrice + 5 ,
0.01 ,
price * 0.011 ,
clientId ,
PerpOrderType . limit ,
false ,
0 ,
1 ,
) ;
console . log ( ` sig https://explorer.solana.com/tx/ ${ sig } ?cluster=devnet ` ) ;
} catch ( error ) {
console . log ( error ) ;
}
try {
const clientId = Math . floor ( Math . random ( ) * 99999 ) ;
const price = group . banksMapByName . get ( 'BTC' ) ! [ 0 ] . uiPrice ! ;
console . log (
` ...placing perp pegged bid ${ clientId } at oracle price ${ perpMarket . uiPrice } ` ,
) ;
const sig = await client . perpPlaceOrderPegged (
group ,
mangoAccount ,
perpMarket . perpMarketIndex ,
PerpOrderSide . ask ,
5 ,
perpMarket . uiPrice - 5 ,
0.01 ,
price * 0.011 ,
clientId ,
PerpOrderType . limit ,
false ,
0 ,
1 ,
) ;
console . log ( ` sig https://explorer.solana.com/tx/ ${ sig } ?cluster=devnet ` ) ;
} catch ( error ) {
console . log ( error ) ;
}
await logBidsAndAsks ( client , group ) ;
sig = await client . perpCancelAllOrders (
group ,
mangoAccount ,
perpMarket . perpMarketIndex ,
10 ,
) ;
console . log ( ` sig https://explorer.solana.com/tx/ ${ sig } ?cluster=devnet ` ) ;
2022-09-20 10:50:21 -07:00
// scenario 1
2022-09-23 02:43:26 -07:00
// bid max perp
2022-06-02 10:30:39 -07:00
try {
2022-09-20 03:57:01 -07:00
const clientId = Math . floor ( Math . random ( ) * 99999 ) ;
2022-10-07 04:52:04 -07:00
await mangoAccount . reload ( client ) ;
await group . reloadAll ( client ) ;
2022-09-20 10:50:21 -07:00
const price =
group . banksMapByName . get ( 'BTC' ) ! [ 0 ] . uiPrice ! -
Math . floor ( Math . random ( ) * 100 ) ;
2022-09-23 02:43:26 -07:00
const quoteQty = mangoAccount . getMaxQuoteForPerpBidUi (
group ,
2022-09-29 06:51:09 -07:00
perpMarket . perpMarketIndex ,
2022-09-23 02:43:26 -07:00
) ;
const baseQty = quoteQty / price ;
2022-10-07 04:52:04 -07:00
console . log (
` simHealthRatioWithPerpBidUiChanges - ${ mangoAccount . simHealthRatioWithPerpBidUiChanges (
group ,
perpMarket . perpMarketIndex ,
baseQty ,
) } ` ,
) ;
2022-09-23 02:43:26 -07:00
console . log (
` ...placing max qty perp bid clientId ${ clientId } at price ${ price } , base ${ baseQty } , quote ${ quoteQty } ` ,
) ;
2022-09-20 03:57:01 -07:00
const sig = await client . perpPlaceOrder (
2022-06-02 10:30:39 -07:00
group ,
mangoAccount ,
2022-09-29 06:51:09 -07:00
perpMarket . perpMarketIndex ,
2022-09-27 06:13:53 -07:00
PerpOrderSide . bid ,
2022-09-20 03:57:01 -07:00
price ,
2022-09-23 02:43:26 -07:00
baseQty ,
quoteQty ,
2022-09-20 03:57:01 -07:00
clientId ,
PerpOrderType . limit ,
2022-11-09 00:59:34 -08:00
false ,
2022-09-20 03:57:01 -07:00
0 , //Date.now() + 200,
2022-06-02 10:30:39 -07:00
1 ,
) ;
2022-09-20 03:57:01 -07:00
console . log ( ` sig https://explorer.solana.com/tx/ ${ sig } ?cluster=devnet ` ) ;
2022-06-02 10:30:39 -07:00
} catch ( error ) {
console . log ( error ) ;
}
2022-09-23 02:43:26 -07:00
console . log ( ` ...cancelling all perp orders ` ) ;
2022-09-29 06:51:09 -07:00
sig = await client . perpCancelAllOrders (
group ,
mangoAccount ,
perpMarket . perpMarketIndex ,
10 ,
) ;
2022-09-23 02:43:26 -07:00
console . log ( ` sig https://explorer.solana.com/tx/ ${ sig } ?cluster=devnet ` ) ;
// bid max perp + some
2022-09-20 03:57:01 -07:00
try {
const clientId = Math . floor ( Math . random ( ) * 99999 ) ;
2022-09-20 10:50:21 -07:00
const price =
2022-09-23 02:43:26 -07:00
group . banksMapByName . get ( 'BTC' ) ! [ 0 ] . uiPrice ! -
2022-09-20 10:50:21 -07:00
Math . floor ( Math . random ( ) * 100 ) ;
2022-09-23 02:43:26 -07:00
const quoteQty =
2022-09-29 06:51:09 -07:00
mangoAccount . getMaxQuoteForPerpBidUi (
group ,
perpMarket . perpMarketIndex ,
) * 1.02 ;
2022-10-07 04:52:04 -07:00
2022-09-23 02:43:26 -07:00
const baseQty = quoteQty / price ;
console . log (
` ...placing max qty * 1.02 perp bid clientId ${ clientId } at price ${ price } , base ${ baseQty } , quote ${ quoteQty } ` ,
) ;
2022-09-20 03:57:01 -07:00
const sig = await client . perpPlaceOrder (
group ,
mangoAccount ,
2022-09-29 06:51:09 -07:00
perpMarket . perpMarketIndex ,
2022-09-27 06:13:53 -07:00
PerpOrderSide . bid ,
2022-09-20 03:57:01 -07:00
price ,
2022-09-23 02:43:26 -07:00
baseQty ,
quoteQty ,
2022-09-20 03:57:01 -07:00
clientId ,
PerpOrderType . limit ,
2022-11-09 00:59:34 -08:00
false ,
2022-09-20 03:57:01 -07:00
0 , //Date.now() + 200,
1 ,
2022-06-02 10:30:39 -07:00
) ;
2022-09-20 03:57:01 -07:00
console . log ( ` sig https://explorer.solana.com/tx/ ${ sig } ?cluster=devnet ` ) ;
} catch ( error ) {
2022-10-07 04:52:04 -07:00
console . log ( error ) ;
2022-09-23 02:43:26 -07:00
console . log ( 'Errored out as expected' ) ;
2022-06-02 10:30:39 -07:00
}
2022-09-20 03:57:01 -07:00
2022-09-23 02:43:26 -07:00
// bid max ask
2022-09-20 10:50:21 -07:00
try {
const clientId = Math . floor ( Math . random ( ) * 99999 ) ;
2022-09-23 02:43:26 -07:00
const price =
group . banksMapByName . get ( 'BTC' ) ! [ 0 ] . uiPrice ! +
Math . floor ( Math . random ( ) * 100 ) ;
2022-09-29 06:51:09 -07:00
const baseQty = mangoAccount . getMaxBaseForPerpAskUi (
group ,
perpMarket . perpMarketIndex ,
2022-10-07 04:52:04 -07:00
) ;
console . log (
` simHealthRatioWithPerpAskUiChanges - ${ mangoAccount . simHealthRatioWithPerpAskUiChanges (
group ,
perpMarket . perpMarketIndex ,
baseQty ,
) } ` ,
2022-09-29 06:51:09 -07:00
) ;
2022-09-23 02:43:26 -07:00
const quoteQty = baseQty * price ;
console . log (
` ...placing max qty perp ask clientId ${ clientId } at price ${ price } , base ${ baseQty } , quote ${ quoteQty } ` ,
) ;
2022-09-20 10:50:21 -07:00
const sig = await client . perpPlaceOrder (
group ,
mangoAccount ,
2022-09-29 06:51:09 -07:00
perpMarket . perpMarketIndex ,
2022-09-27 06:13:53 -07:00
PerpOrderSide . ask ,
2022-09-20 10:50:21 -07:00
price ,
2022-09-23 02:43:26 -07:00
baseQty ,
quoteQty ,
2022-09-20 10:50:21 -07:00
clientId ,
PerpOrderType . limit ,
2022-11-09 00:59:34 -08:00
false ,
2022-09-20 10:50:21 -07:00
0 , //Date.now() + 200,
1 ,
) ;
console . log ( ` sig https://explorer.solana.com/tx/ ${ sig } ?cluster=devnet ` ) ;
} catch ( error ) {
console . log ( error ) ;
}
2022-09-23 02:43:26 -07:00
// bid max ask + some
2022-09-20 10:50:21 -07:00
try {
const clientId = Math . floor ( Math . random ( ) * 99999 ) ;
2022-09-23 02:43:26 -07:00
const price =
group . banksMapByName . get ( 'BTC' ) ! [ 0 ] . uiPrice ! +
Math . floor ( Math . random ( ) * 100 ) ;
const baseQty =
2022-12-16 07:33:37 -08:00
mangoAccount . getMaxBaseForPerpAskUi ( group , perpMarket . perpMarketIndex ) *
1.02 ;
2022-09-23 02:43:26 -07:00
const quoteQty = baseQty * price ;
console . log (
` ...placing max qty perp ask * 1.02 clientId ${ clientId } at price ${ price } , base ${ baseQty } , quote ${ quoteQty } ` ,
) ;
2022-09-20 10:50:21 -07:00
const sig = await client . perpPlaceOrder (
group ,
mangoAccount ,
2022-09-29 06:51:09 -07:00
perpMarket . perpMarketIndex ,
2022-09-27 06:13:53 -07:00
PerpOrderSide . ask ,
2022-09-20 10:50:21 -07:00
price ,
2022-09-23 02:43:26 -07:00
baseQty ,
quoteQty ,
2022-09-20 10:50:21 -07:00
clientId ,
PerpOrderType . limit ,
2022-11-09 00:59:34 -08:00
false ,
2022-09-20 10:50:21 -07:00
0 , //Date.now() + 200,
1 ,
) ;
console . log ( ` sig https://explorer.solana.com/tx/ ${ sig } ?cluster=devnet ` ) ;
} catch ( error ) {
2022-10-07 04:52:04 -07:00
console . log ( error ) ;
2022-09-23 02:43:26 -07:00
console . log ( 'Errored out as expected' ) ;
2022-09-20 10:50:21 -07:00
}
2022-09-23 02:43:26 -07:00
console . log ( ` ...cancelling all perp orders ` ) ;
2022-09-29 06:51:09 -07:00
sig = await client . perpCancelAllOrders (
group ,
mangoAccount ,
perpMarket . perpMarketIndex ,
10 ,
) ;
2022-09-23 02:43:26 -07:00
console . log ( ` sig https://explorer.solana.com/tx/ ${ sig } ?cluster=devnet ` ) ;
2022-10-07 04:52:04 -07:00
// scenario 2
// make + take orders
try {
const clientId = Math . floor ( Math . random ( ) * 99999 ) ;
const price = group . banksMapByName . get ( 'BTC' ) ! [ 0 ] . uiPrice ! ;
console . log ( ` ...placing perp bid ${ clientId } at ${ price } ` ) ;
const sig = await client . perpPlaceOrder (
group ,
mangoAccount ,
perpMarket . perpMarketIndex ,
PerpOrderSide . bid ,
price ,
0.01 ,
price * 0.01 ,
clientId ,
PerpOrderType . limit ,
2022-11-09 00:59:34 -08:00
false ,
2022-10-07 04:52:04 -07:00
0 , //Date.now() + 200,
1 ,
) ;
console . log ( ` sig https://explorer.solana.com/tx/ ${ sig } ?cluster=devnet ` ) ;
} catch ( error ) {
console . log ( error ) ;
}
try {
const clientId = Math . floor ( Math . random ( ) * 99999 ) ;
const price = group . banksMapByName . get ( 'BTC' ) ! [ 0 ] . uiPrice ! ;
console . log ( ` ...placing perp ask ${ clientId } at ${ price } ` ) ;
const sig = await client . perpPlaceOrder (
group ,
mangoAccount ,
perpMarket . perpMarketIndex ,
PerpOrderSide . ask ,
price ,
0.01 ,
price * 0.011 ,
clientId ,
PerpOrderType . limit ,
2022-11-09 00:59:34 -08:00
false ,
2022-10-07 04:52:04 -07:00
0 , //Date.now() + 200,
1 ,
) ;
console . log ( ` sig https://explorer.solana.com/tx/ ${ sig } ?cluster=devnet ` ) ;
} catch ( error ) {
console . log ( error ) ;
}
// // should be able to cancel them : know bug
// console.log(`...cancelling all perp orders`);
// sig = await client.perpCancelAllOrders(group, mangoAccount, perpMarket.perpMarketIndex, 10);
// console.log(`sig https://explorer.solana.com/tx/${sig}?cluster=devnet`);
2022-09-20 10:50:21 -07:00
2022-09-20 03:57:01 -07:00
await perpMarket ? . loadEventQueue ( client ) ! ;
2022-09-27 06:13:53 -07:00
const fr = perpMarket ? . getCurrentFundingRate (
2022-09-20 03:57:01 -07:00
await perpMarket . loadBids ( client ) ,
await perpMarket . loadAsks ( client ) ,
) ;
console . log ( ` current funding rate per hour is ${ fr } ` ) ;
const eq = await perpMarket ? . loadEventQueue ( client ) ! ;
2022-10-07 04:52:04 -07:00
console . log (
` raw events - ${ JSON . stringify ( eq . eventsSince ( new BN ( 0 ) ) , null , 2 ) } ` ,
) ;
2022-09-20 03:57:01 -07:00
// sleep so that keeper can catch up
await new Promise ( ( r ) = > setTimeout ( r , 2000 ) ) ;
2022-10-07 04:52:04 -07:00
// make+take orders should have cancelled each other, and if keeper has already cranked, then should not appear in position or we see a small quotePositionNative
2022-09-20 03:57:01 -07:00
await group . reloadAll ( client ) ;
2022-09-29 06:51:09 -07:00
await mangoAccount . reload ( client ) ;
2022-09-20 03:57:01 -07:00
console . log ( ` ${ mangoAccount . toString ( group ) } ` ) ;
2022-05-11 04:33:01 -07:00
}
2022-04-07 23:29:35 -07:00
process . exit ( ) ;
2022-04-07 08:16:46 -07:00
}
2022-11-21 10:34:41 -08:00
async function logBidsAndAsks ( client : MangoClient , group : Group ) {
await group . reloadAll ( client ) ;
const perpMarket = group . getPerpMarketByName ( 'BTC-PERP' ) ;
const res = [
( await perpMarket ? . loadBids ( client ) ) . items ( ) ,
( await perpMarket ? . loadAsks ( client ) ! ) . items ( ) ,
] ;
console . log ( ` bids ${ JSON . stringify ( Array . from ( res [ 0 ] ) , null , 2 ) } ` ) ;
console . log ( ` asks ${ JSON . stringify ( Array . from ( res [ 1 ] ) , null , 2 ) } ` ) ;
return res ;
}
2022-04-07 08:16:46 -07:00
main ( ) ;