2023-02-21 23:36:59 -08:00
|
|
|
import { AnchorProvider, BN, Wallet } from '@coral-xyz/anchor';
|
2023-05-17 06:50:05 -07:00
|
|
|
import { Cluster, Connection, Keypair, PublicKey } from '@solana/web3.js';
|
2022-08-08 08:49:10 -07:00
|
|
|
import fs from 'fs';
|
2023-04-07 06:04:32 -07:00
|
|
|
import { Bank } from '../../src/accounts/bank';
|
|
|
|
import { MangoAccount } from '../../src/accounts/mangoAccount';
|
2023-04-07 07:25:05 -07:00
|
|
|
import {
|
|
|
|
PerpMarket,
|
|
|
|
PerpOrderSide,
|
|
|
|
PerpOrderType,
|
|
|
|
} from '../../src/accounts/perp';
|
2022-09-01 04:43:17 -07:00
|
|
|
import {
|
|
|
|
Serum3OrderType,
|
|
|
|
Serum3SelfTradeBehavior,
|
|
|
|
Serum3Side,
|
2023-04-07 06:04:32 -07:00
|
|
|
} from '../../src/accounts/serum3';
|
|
|
|
import { Builder } from '../../src/builder';
|
|
|
|
import { MangoClient } from '../../src/client';
|
2023-01-14 05:09:26 -08:00
|
|
|
import {
|
|
|
|
NullPerpEditParams,
|
|
|
|
NullTokenEditParams,
|
2023-04-07 06:04:32 -07:00
|
|
|
} from '../../src/clientIxParamBuilder';
|
|
|
|
import { MANGO_V4_ID } from '../../src/constants';
|
2022-08-08 08:49:10 -07:00
|
|
|
|
|
|
|
//
|
|
|
|
// This script creates liquidation candidates
|
|
|
|
//
|
|
|
|
|
2022-09-01 02:47:37 -07:00
|
|
|
const GROUP_NUM = Number(process.env.GROUP_NUM || 200);
|
2023-05-17 06:50:05 -07:00
|
|
|
const CLUSTER = process.env.CLUSTER || 'mainnet-beta';
|
2022-08-08 08:49:10 -07:00
|
|
|
|
|
|
|
// native prices
|
|
|
|
const PRICES = {
|
2022-12-16 04:10:46 -08:00
|
|
|
ETH: 1200.0,
|
|
|
|
SOL: 0.015,
|
2022-08-08 08:49:10 -07:00
|
|
|
USDC: 1,
|
2022-12-16 04:10:46 -08:00
|
|
|
MNGO: 0.02,
|
2022-08-08 08:49:10 -07:00
|
|
|
};
|
|
|
|
|
2022-12-16 04:10:46 -08:00
|
|
|
const TOKEN_SCENARIOS: [string, [string, number][], [string, number][]][] = [
|
|
|
|
[
|
|
|
|
'LIQTEST, FUNDING',
|
|
|
|
[
|
|
|
|
['USDC', 5000000],
|
|
|
|
['ETH', 100000],
|
|
|
|
['SOL', 150000000],
|
|
|
|
],
|
|
|
|
[],
|
|
|
|
],
|
|
|
|
['LIQTEST, LIQOR', [['USDC', 1000000]], []],
|
|
|
|
['LIQTEST, A: USDC, L: SOL', [['USDC', 1000 * PRICES.SOL]], [['SOL', 920]]],
|
|
|
|
['LIQTEST, A: SOL, L: USDC', [['SOL', 1000]], [['USDC', 990 * PRICES.SOL]]],
|
|
|
|
[
|
|
|
|
'LIQTEST, A: ETH, L: SOL',
|
|
|
|
[['ETH', 20]],
|
|
|
|
[['SOL', (18 * PRICES.ETH) / PRICES.SOL]],
|
|
|
|
],
|
2022-08-08 08:49:10 -07:00
|
|
|
];
|
|
|
|
|
|
|
|
async function main() {
|
|
|
|
const options = AnchorProvider.defaultOptions();
|
2023-02-03 04:51:18 -08:00
|
|
|
options.commitment = 'processed';
|
|
|
|
options.preflightCommitment = 'finalized';
|
2022-09-01 02:47:37 -07:00
|
|
|
const connection = new Connection(process.env.CLUSTER_URL!, options);
|
2022-08-08 08:49:10 -07:00
|
|
|
|
|
|
|
const admin = Keypair.fromSecretKey(
|
|
|
|
Buffer.from(
|
2023-05-17 06:50:05 -07:00
|
|
|
JSON.parse(fs.readFileSync(process.env.PAYER_KEYPAIR!, 'utf-8')),
|
2022-08-08 08:49:10 -07:00
|
|
|
),
|
|
|
|
);
|
|
|
|
const userWallet = new Wallet(admin);
|
|
|
|
const userProvider = new AnchorProvider(connection, userWallet, options);
|
|
|
|
const client = await MangoClient.connect(
|
|
|
|
userProvider,
|
2023-05-17 06:50:05 -07:00
|
|
|
CLUSTER as Cluster,
|
|
|
|
MANGO_V4_ID[CLUSTER],
|
2022-11-04 07:35:40 -07:00
|
|
|
{
|
|
|
|
idsSource: 'get-program-accounts',
|
2023-02-03 04:51:18 -08:00
|
|
|
prioritizationFee: 100,
|
|
|
|
txConfirmationCommitment: 'confirmed',
|
2022-11-04 07:35:40 -07:00
|
|
|
},
|
2022-08-08 08:49:10 -07:00
|
|
|
);
|
|
|
|
console.log(`User ${userWallet.publicKey.toBase58()}`);
|
|
|
|
|
|
|
|
// fetch group
|
|
|
|
const group = await client.getGroupForCreator(admin.publicKey, GROUP_NUM);
|
|
|
|
console.log(group.toString());
|
|
|
|
|
2022-12-16 04:10:46 -08:00
|
|
|
const MAINNET_MINTS = new Map([
|
|
|
|
['USDC', group.banksMapByName.get('USDC')![0].mint],
|
|
|
|
['ETH', group.banksMapByName.get('ETH')![0].mint],
|
|
|
|
['SOL', group.banksMapByName.get('SOL')![0].mint],
|
|
|
|
]);
|
|
|
|
|
2022-08-08 08:49:10 -07:00
|
|
|
const accounts = await client.getMangoAccountsForOwner(
|
|
|
|
group,
|
|
|
|
admin.publicKey,
|
|
|
|
);
|
2022-09-01 04:43:17 -07:00
|
|
|
let maxAccountNum = Math.max(0, ...accounts.map((a) => a.accountNum));
|
2022-09-15 00:57:48 -07:00
|
|
|
|
|
|
|
async function createMangoAccount(name: string): Promise<MangoAccount> {
|
|
|
|
const accountNum = maxAccountNum + 1;
|
|
|
|
maxAccountNum = maxAccountNum + 1;
|
|
|
|
await client.createMangoAccount(group, accountNum, name, 4, 4, 4, 4);
|
|
|
|
return (await client.getMangoAccountForOwner(
|
|
|
|
group,
|
|
|
|
admin.publicKey,
|
|
|
|
accountNum,
|
|
|
|
))!;
|
|
|
|
}
|
2022-08-08 08:49:10 -07:00
|
|
|
|
2022-12-16 04:10:46 -08:00
|
|
|
async function setBankPrice(bank: Bank, price: number): Promise<void> {
|
|
|
|
await client.stubOracleSet(group, bank.oracle, price);
|
|
|
|
// reset stable price
|
|
|
|
await client.tokenEdit(
|
|
|
|
group,
|
|
|
|
bank.mint,
|
2023-01-14 05:09:26 -08:00
|
|
|
Builder(NullTokenEditParams).resetStablePrice(true).build(),
|
2022-12-16 04:10:46 -08:00
|
|
|
);
|
|
|
|
}
|
|
|
|
async function setPerpPrice(
|
|
|
|
perpMarket: PerpMarket,
|
|
|
|
price: number,
|
|
|
|
): Promise<void> {
|
|
|
|
await client.stubOracleSet(group, perpMarket.oracle, price);
|
|
|
|
// reset stable price
|
|
|
|
await client.perpEditMarket(
|
|
|
|
group,
|
|
|
|
perpMarket.perpMarketIndex,
|
2023-02-03 04:56:55 -08:00
|
|
|
Builder(NullPerpEditParams).resetStablePrice(true).build(),
|
2022-12-16 04:10:46 -08:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-09-01 04:43:17 -07:00
|
|
|
for (const scenario of TOKEN_SCENARIOS) {
|
2022-12-16 04:10:46 -08:00
|
|
|
const [name, assets, liabs] = scenario;
|
2022-08-08 08:49:10 -07:00
|
|
|
|
|
|
|
// create account
|
|
|
|
console.log(`Creating mangoaccount...`);
|
2023-05-17 06:50:05 -07:00
|
|
|
const mangoAccount = await createMangoAccount(name);
|
2022-08-08 08:49:10 -07:00
|
|
|
console.log(
|
|
|
|
`...created mangoAccount ${mangoAccount.publicKey} for ${name}`,
|
|
|
|
);
|
|
|
|
|
2023-05-17 06:50:05 -07:00
|
|
|
for (const [assetName, assetAmount] of assets) {
|
2022-12-16 04:10:46 -08:00
|
|
|
const assetMint = new PublicKey(MAINNET_MINTS.get(assetName)!);
|
|
|
|
await client.tokenDepositNative(
|
|
|
|
group,
|
|
|
|
mangoAccount,
|
|
|
|
assetMint,
|
|
|
|
new BN(assetAmount),
|
|
|
|
);
|
|
|
|
await mangoAccount.reload(client);
|
|
|
|
}
|
2022-09-01 02:47:37 -07:00
|
|
|
|
2023-05-17 06:50:05 -07:00
|
|
|
for (const [liabName, liabAmount] of liabs) {
|
2022-12-16 04:10:46 -08:00
|
|
|
const liabMint = new PublicKey(MAINNET_MINTS.get(liabName)!);
|
2022-08-08 08:49:10 -07:00
|
|
|
|
2022-08-09 01:57:03 -07:00
|
|
|
// temporarily drop the borrowed token value, so the borrow goes through
|
2022-12-16 04:10:46 -08:00
|
|
|
const bank = group.banksMapByName.get(liabName)![0];
|
2022-08-09 01:57:03 -07:00
|
|
|
try {
|
2022-12-16 04:10:46 -08:00
|
|
|
await setBankPrice(bank, PRICES[liabName] / 2);
|
2022-08-09 01:57:03 -07:00
|
|
|
|
2023-02-02 06:08:57 -08:00
|
|
|
await client.tokenWithdrawNative(
|
2022-08-09 01:57:03 -07:00
|
|
|
group,
|
|
|
|
mangoAccount,
|
2022-09-01 02:47:37 -07:00
|
|
|
liabMint,
|
2022-10-11 00:38:52 -07:00
|
|
|
new BN(liabAmount),
|
2022-08-09 01:57:03 -07:00
|
|
|
true,
|
|
|
|
);
|
|
|
|
} finally {
|
|
|
|
// restore the oracle
|
2022-12-16 04:10:46 -08:00
|
|
|
await setBankPrice(bank, PRICES[liabName]);
|
2022-08-09 01:57:03 -07:00
|
|
|
}
|
|
|
|
}
|
2022-08-08 08:49:10 -07:00
|
|
|
}
|
|
|
|
|
2022-12-16 04:10:46 -08:00
|
|
|
const accounts2 = await client.getMangoAccountsForOwner(
|
|
|
|
group,
|
|
|
|
admin.publicKey,
|
|
|
|
);
|
|
|
|
const fundingAccount = accounts2.find(
|
|
|
|
(account) => account.name == 'LIQTEST, FUNDING',
|
|
|
|
);
|
|
|
|
if (!fundingAccount) {
|
|
|
|
throw new Error('could not find funding account');
|
|
|
|
}
|
|
|
|
|
2022-09-01 04:43:17 -07:00
|
|
|
// Serum order scenario
|
|
|
|
{
|
|
|
|
const name = 'LIQTEST, serum orders';
|
|
|
|
|
|
|
|
console.log(`Creating mangoaccount...`);
|
2023-05-17 06:50:05 -07:00
|
|
|
const mangoAccount = await createMangoAccount(name);
|
2022-09-01 04:43:17 -07:00
|
|
|
console.log(
|
|
|
|
`...created mangoAccount ${mangoAccount.publicKey} for ${name}`,
|
|
|
|
);
|
|
|
|
|
2022-10-11 00:38:52 -07:00
|
|
|
const market = group.getSerum3MarketByName('SOL/USDC')!;
|
2022-09-01 04:43:17 -07:00
|
|
|
const sellMint = new PublicKey(MAINNET_MINTS.get('USDC')!);
|
|
|
|
const buyMint = new PublicKey(MAINNET_MINTS.get('SOL')!);
|
|
|
|
|
2022-10-11 00:38:52 -07:00
|
|
|
await client.tokenDepositNative(
|
|
|
|
group,
|
|
|
|
mangoAccount,
|
|
|
|
sellMint,
|
|
|
|
new BN(100000),
|
|
|
|
);
|
|
|
|
await mangoAccount.reload(client);
|
2022-09-01 04:43:17 -07:00
|
|
|
|
|
|
|
// temporarily up the init asset weight of the bought token
|
|
|
|
await client.tokenEdit(
|
|
|
|
group,
|
|
|
|
buyMint,
|
2023-01-14 05:09:26 -08:00
|
|
|
Builder(NullTokenEditParams)
|
|
|
|
.oracle(group.getFirstBankByMint(buyMint).oracle)
|
|
|
|
.maintAssetWeight(1.0)
|
|
|
|
.initAssetWeight(1.0)
|
|
|
|
.build(),
|
2022-09-01 04:43:17 -07:00
|
|
|
);
|
|
|
|
try {
|
|
|
|
// At a price of $1/ui-SOL we can buy 0.1 ui-SOL for the 100k native-USDC we have.
|
|
|
|
// With maint weight of 0.9 we have 10x main-leverage. Buying 12x as much causes liquidation.
|
|
|
|
await client.serum3PlaceOrder(
|
|
|
|
group,
|
|
|
|
mangoAccount,
|
|
|
|
market.serumMarketExternal,
|
|
|
|
Serum3Side.bid,
|
|
|
|
1,
|
|
|
|
12 * 0.1,
|
|
|
|
Serum3SelfTradeBehavior.abortTransaction,
|
|
|
|
Serum3OrderType.limit,
|
|
|
|
0,
|
|
|
|
5,
|
|
|
|
);
|
|
|
|
} finally {
|
|
|
|
// restore the weights
|
|
|
|
await client.tokenEdit(
|
|
|
|
group,
|
|
|
|
buyMint,
|
2023-01-14 05:09:26 -08:00
|
|
|
Builder(NullTokenEditParams)
|
|
|
|
.oracle(group.getFirstBankByMint(buyMint).oracle)
|
|
|
|
.maintAssetWeight(0.9)
|
|
|
|
.initAssetWeight(0.8)
|
|
|
|
.build(),
|
2022-09-01 04:43:17 -07:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-15 00:57:48 -07:00
|
|
|
// Perp orders bring health <0, liquidator force closes
|
|
|
|
{
|
|
|
|
const name = 'LIQTEST, perp orders';
|
|
|
|
|
|
|
|
console.log(`Creating mangoaccount...`);
|
2023-05-17 06:50:05 -07:00
|
|
|
const mangoAccount = await createMangoAccount(name);
|
2022-09-15 00:57:48 -07:00
|
|
|
console.log(
|
|
|
|
`...created mangoAccount ${mangoAccount.publicKey} for ${name}`,
|
|
|
|
);
|
|
|
|
|
|
|
|
const collateralMint = new PublicKey(MAINNET_MINTS.get('SOL')!);
|
2022-12-16 04:10:46 -08:00
|
|
|
const collateralBank = group.banksMapByName.get('SOL')![0];
|
2022-09-15 00:57:48 -07:00
|
|
|
|
|
|
|
await client.tokenDepositNative(
|
|
|
|
group,
|
|
|
|
mangoAccount,
|
|
|
|
collateralMint,
|
2022-12-16 04:10:46 -08:00
|
|
|
new BN(300000),
|
|
|
|
); // valued as 0.0003 SOL, $0.0045 maint collateral
|
2022-10-11 00:38:52 -07:00
|
|
|
await mangoAccount.reload(client);
|
2022-09-15 00:57:48 -07:00
|
|
|
|
2022-12-16 04:10:46 -08:00
|
|
|
await setBankPrice(collateralBank, PRICES['SOL'] * 4);
|
2022-09-15 00:57:48 -07:00
|
|
|
|
|
|
|
try {
|
2023-01-16 03:30:34 -08:00
|
|
|
// placing this order decreases maint health by (0.9 - 1)*$0.06 = $-0.006
|
2022-09-15 00:57:48 -07:00
|
|
|
await client.perpPlaceOrder(
|
|
|
|
group,
|
|
|
|
mangoAccount,
|
2023-05-17 06:50:05 -07:00
|
|
|
assertNotUndefined(
|
|
|
|
group.perpMarketsMapByName.get('MNGO-PERP')?.perpMarketIndex,
|
|
|
|
),
|
2022-10-11 00:38:52 -07:00
|
|
|
PerpOrderSide.bid,
|
2022-12-16 04:10:46 -08:00
|
|
|
0.001, // ui price that won't get hit
|
2023-01-16 03:30:34 -08:00
|
|
|
3.0, // ui base quantity, 30 base lots, 3.0 MNGO, $0.06
|
|
|
|
0.06, // ui quote quantity
|
2022-09-15 00:57:48 -07:00
|
|
|
4200,
|
|
|
|
PerpOrderType.limit,
|
2022-11-09 00:59:34 -08:00
|
|
|
false,
|
2022-09-15 00:57:48 -07:00
|
|
|
0,
|
|
|
|
5,
|
|
|
|
);
|
|
|
|
} finally {
|
2022-12-16 04:10:46 -08:00
|
|
|
await setBankPrice(collateralBank, PRICES['SOL']);
|
2022-09-15 00:57:48 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Perp base pos brings health<0, liquidator takes most of it
|
|
|
|
{
|
|
|
|
const name = 'LIQTEST, perp base pos';
|
|
|
|
|
|
|
|
console.log(`Creating mangoaccount...`);
|
2023-05-17 06:50:05 -07:00
|
|
|
const mangoAccount = await createMangoAccount(name);
|
2022-09-15 00:57:48 -07:00
|
|
|
console.log(
|
|
|
|
`...created mangoAccount ${mangoAccount.publicKey} for ${name}`,
|
|
|
|
);
|
|
|
|
|
|
|
|
const collateralMint = new PublicKey(MAINNET_MINTS.get('SOL')!);
|
2022-12-16 04:10:46 -08:00
|
|
|
const collateralBank = group.banksMapByName.get('SOL')![0];
|
2022-09-15 00:57:48 -07:00
|
|
|
|
|
|
|
await client.tokenDepositNative(
|
|
|
|
group,
|
|
|
|
mangoAccount,
|
|
|
|
collateralMint,
|
2022-12-16 04:10:46 -08:00
|
|
|
new BN(300000),
|
|
|
|
); // valued as 0.0003 SOL, $0.0045 maint collateral
|
2022-10-11 00:38:52 -07:00
|
|
|
await mangoAccount.reload(client);
|
2022-09-15 00:57:48 -07:00
|
|
|
|
2022-12-16 04:10:46 -08:00
|
|
|
await setBankPrice(collateralBank, PRICES['SOL'] * 10);
|
2022-09-15 00:57:48 -07:00
|
|
|
|
|
|
|
try {
|
|
|
|
await client.perpPlaceOrder(
|
|
|
|
group,
|
|
|
|
fundingAccount,
|
2023-05-17 06:50:05 -07:00
|
|
|
assertNotUndefined(
|
|
|
|
group.perpMarketsMapByName.get('MNGO-PERP')?.perpMarketIndex,
|
|
|
|
),
|
2022-10-11 00:38:52 -07:00
|
|
|
PerpOrderSide.ask,
|
2022-12-16 04:10:46 -08:00
|
|
|
0.03,
|
|
|
|
1.1, // ui base quantity, 11 base lots, $0.022 value, gain $0.033
|
|
|
|
0.033, // ui quote quantity
|
2022-09-15 00:57:48 -07:00
|
|
|
4200,
|
|
|
|
PerpOrderType.limit,
|
2022-11-09 00:59:34 -08:00
|
|
|
false,
|
2022-09-15 00:57:48 -07:00
|
|
|
0,
|
|
|
|
5,
|
|
|
|
);
|
|
|
|
|
|
|
|
await client.perpPlaceOrder(
|
|
|
|
group,
|
|
|
|
mangoAccount,
|
2023-05-17 06:50:05 -07:00
|
|
|
assertNotUndefined(
|
|
|
|
group.perpMarketsMapByName.get('MNGO-PERP')?.perpMarketIndex,
|
|
|
|
),
|
2022-10-11 00:38:52 -07:00
|
|
|
PerpOrderSide.bid,
|
2022-12-16 04:10:46 -08:00
|
|
|
0.03,
|
|
|
|
1.1, // ui base quantity, 11 base lots, $0.022 value, cost $0.033
|
|
|
|
0.033, // ui quote quantity
|
2022-09-15 00:57:48 -07:00
|
|
|
4200,
|
|
|
|
PerpOrderType.market,
|
2022-11-09 00:59:34 -08:00
|
|
|
false,
|
2022-09-15 00:57:48 -07:00
|
|
|
0,
|
|
|
|
5,
|
|
|
|
);
|
|
|
|
|
2022-10-11 00:38:52 -07:00
|
|
|
await client.perpConsumeAllEvents(
|
|
|
|
group,
|
2023-05-17 06:50:05 -07:00
|
|
|
assertNotUndefined(
|
|
|
|
group.perpMarketsMapByName.get('MNGO-PERP')?.perpMarketIndex,
|
|
|
|
),
|
2022-10-11 00:38:52 -07:00
|
|
|
);
|
2022-09-15 00:57:48 -07:00
|
|
|
} finally {
|
2022-12-16 04:10:46 -08:00
|
|
|
await setBankPrice(collateralBank, PRICES['SOL']);
|
2022-09-15 00:57:48 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-26 04:27:31 -07:00
|
|
|
// borrows and positive perp pnl (but no position)
|
|
|
|
{
|
|
|
|
const name = 'LIQTEST, perp positive pnl';
|
|
|
|
|
|
|
|
console.log(`Creating mangoaccount...`);
|
2023-05-17 06:50:05 -07:00
|
|
|
const mangoAccount = await createMangoAccount(name);
|
2022-09-26 04:27:31 -07:00
|
|
|
console.log(
|
|
|
|
`...created mangoAccount ${mangoAccount.publicKey} for ${name}`,
|
|
|
|
);
|
|
|
|
|
2022-12-16 04:10:46 -08:00
|
|
|
const perpMarket = group.perpMarketsMapByName.get('MNGO-PERP')!;
|
|
|
|
const perpIndex = perpMarket.perpMarketIndex;
|
2022-09-26 04:27:31 -07:00
|
|
|
const liabMint = new PublicKey(MAINNET_MINTS.get('USDC')!);
|
|
|
|
const collateralMint = new PublicKey(MAINNET_MINTS.get('SOL')!);
|
2022-12-16 04:10:46 -08:00
|
|
|
const collateralBank = group.banksMapByName.get('SOL')![0];
|
2022-09-26 04:27:31 -07:00
|
|
|
|
|
|
|
await client.tokenDepositNative(
|
|
|
|
group,
|
|
|
|
mangoAccount,
|
|
|
|
collateralMint,
|
2022-12-16 04:10:46 -08:00
|
|
|
new BN(300000),
|
|
|
|
); // valued as $0.0045 maint collateral
|
2022-10-11 00:38:52 -07:00
|
|
|
await mangoAccount.reload(client);
|
2022-09-26 04:27:31 -07:00
|
|
|
|
|
|
|
try {
|
2022-12-16 04:10:46 -08:00
|
|
|
await setBankPrice(collateralBank, PRICES['SOL'] * 10);
|
2022-09-26 04:27:31 -07:00
|
|
|
|
|
|
|
// Spot-borrow more than the collateral is worth
|
2023-02-02 06:08:57 -08:00
|
|
|
await client.tokenWithdrawNative(
|
2022-09-26 04:27:31 -07:00
|
|
|
group,
|
|
|
|
mangoAccount,
|
|
|
|
liabMint,
|
2022-10-11 00:38:52 -07:00
|
|
|
new BN(-5000),
|
2022-09-26 04:27:31 -07:00
|
|
|
true,
|
|
|
|
);
|
2022-10-11 00:38:52 -07:00
|
|
|
await mangoAccount.reload(client);
|
2022-09-26 04:27:31 -07:00
|
|
|
|
2022-12-16 04:10:46 -08:00
|
|
|
// Execute two trades that leave the account with +$0.011 positive pnl
|
|
|
|
await setPerpPrice(perpMarket, PRICES['MNGO'] / 2);
|
2022-09-26 04:27:31 -07:00
|
|
|
await client.perpPlaceOrder(
|
|
|
|
group,
|
|
|
|
fundingAccount,
|
2022-12-16 04:10:46 -08:00
|
|
|
perpIndex,
|
2022-10-11 00:38:52 -07:00
|
|
|
PerpOrderSide.ask,
|
2022-12-16 04:10:46 -08:00
|
|
|
0.01,
|
|
|
|
1.1, // ui base quantity, 11 base lots, $0.011
|
|
|
|
0.011, // ui quote quantity
|
2022-09-26 04:27:31 -07:00
|
|
|
4200,
|
|
|
|
PerpOrderType.limit,
|
2022-11-09 00:59:34 -08:00
|
|
|
false,
|
2022-09-26 04:27:31 -07:00
|
|
|
0,
|
|
|
|
5,
|
|
|
|
);
|
|
|
|
await client.perpPlaceOrder(
|
|
|
|
group,
|
|
|
|
mangoAccount,
|
2022-12-16 04:10:46 -08:00
|
|
|
perpIndex,
|
2022-10-11 00:38:52 -07:00
|
|
|
PerpOrderSide.bid,
|
2022-12-16 04:10:46 -08:00
|
|
|
0.01,
|
|
|
|
1.1, // ui base quantity, 11 base lots, $0.011
|
|
|
|
0.011, // ui quote quantity
|
2022-09-26 04:27:31 -07:00
|
|
|
4200,
|
|
|
|
PerpOrderType.market,
|
2022-11-09 00:59:34 -08:00
|
|
|
false,
|
2022-09-26 04:27:31 -07:00
|
|
|
0,
|
|
|
|
5,
|
|
|
|
);
|
2022-12-16 04:10:46 -08:00
|
|
|
await client.perpConsumeAllEvents(group, perpIndex);
|
2022-09-26 04:27:31 -07:00
|
|
|
|
2022-12-16 04:10:46 -08:00
|
|
|
await setPerpPrice(perpMarket, PRICES['MNGO']);
|
2022-09-26 04:27:31 -07:00
|
|
|
|
|
|
|
await client.perpPlaceOrder(
|
|
|
|
group,
|
|
|
|
fundingAccount,
|
2022-12-16 04:10:46 -08:00
|
|
|
perpIndex,
|
2022-10-11 00:38:52 -07:00
|
|
|
PerpOrderSide.bid,
|
2022-12-16 04:10:46 -08:00
|
|
|
0.02,
|
|
|
|
1.1, // ui base quantity, 11 base lots, $0.022
|
|
|
|
0.022, // ui quote quantity
|
2022-09-26 04:27:31 -07:00
|
|
|
4201,
|
|
|
|
PerpOrderType.limit,
|
2022-11-09 00:59:34 -08:00
|
|
|
false,
|
2022-09-26 04:27:31 -07:00
|
|
|
0,
|
|
|
|
5,
|
|
|
|
);
|
|
|
|
await client.perpPlaceOrder(
|
|
|
|
group,
|
|
|
|
mangoAccount,
|
2022-12-16 04:10:46 -08:00
|
|
|
perpIndex,
|
2022-10-11 00:38:52 -07:00
|
|
|
PerpOrderSide.ask,
|
2022-12-16 04:10:46 -08:00
|
|
|
0.02,
|
|
|
|
1.1, // ui base quantity, 11 base lots, $0.022
|
|
|
|
0.022, // ui quote quantity
|
2022-09-26 04:27:31 -07:00
|
|
|
4201,
|
|
|
|
PerpOrderType.market,
|
2022-11-09 00:59:34 -08:00
|
|
|
false,
|
2022-09-26 04:27:31 -07:00
|
|
|
0,
|
|
|
|
5,
|
|
|
|
);
|
2022-12-16 04:10:46 -08:00
|
|
|
await client.perpConsumeAllEvents(group, perpIndex);
|
2022-09-26 04:27:31 -07:00
|
|
|
} finally {
|
2022-12-16 04:10:46 -08:00
|
|
|
await setPerpPrice(perpMarket, PRICES['MNGO']);
|
|
|
|
await setBankPrice(collateralBank, PRICES['SOL']);
|
2022-09-26 04:27:31 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-16 03:30:34 -08:00
|
|
|
// assets and negative perp pnl (but no position)
|
|
|
|
{
|
|
|
|
const name = 'LIQTEST, perp negative pnl';
|
|
|
|
|
|
|
|
console.log(`Creating mangoaccount...`);
|
2023-05-17 06:50:05 -07:00
|
|
|
const mangoAccount = await createMangoAccount(name);
|
2023-01-16 03:30:34 -08:00
|
|
|
console.log(
|
|
|
|
`...created mangoAccount ${mangoAccount.publicKey} for ${name}`,
|
|
|
|
);
|
|
|
|
|
|
|
|
const perpMarket = group.perpMarketsMapByName.get('MNGO-PERP')!;
|
|
|
|
const perpIndex = perpMarket.perpMarketIndex;
|
|
|
|
const liabMint = new PublicKey(MAINNET_MINTS.get('USDC')!);
|
|
|
|
const collateralMint = new PublicKey(MAINNET_MINTS.get('SOL')!);
|
|
|
|
const collateralBank = group.banksMapByName.get('SOL')![0];
|
|
|
|
|
|
|
|
await client.tokenDepositNative(
|
|
|
|
group,
|
|
|
|
mangoAccount,
|
|
|
|
collateralMint,
|
|
|
|
new BN(300000),
|
|
|
|
); // valued as $0.0045 maint collateral
|
|
|
|
await mangoAccount.reload(client);
|
|
|
|
|
|
|
|
try {
|
|
|
|
await setBankPrice(collateralBank, PRICES['SOL'] * 10);
|
|
|
|
|
|
|
|
// Execute two trades that leave the account with -$0.011 negative pnl
|
|
|
|
await setPerpPrice(perpMarket, PRICES['MNGO'] / 2);
|
|
|
|
await client.perpPlaceOrder(
|
|
|
|
group,
|
|
|
|
fundingAccount,
|
|
|
|
perpIndex,
|
|
|
|
PerpOrderSide.bid,
|
|
|
|
0.01,
|
|
|
|
1.1, // ui base quantity, 11 base lots, $0.011
|
|
|
|
0.011, // ui quote quantity
|
|
|
|
4200,
|
|
|
|
PerpOrderType.limit,
|
|
|
|
false,
|
|
|
|
0,
|
|
|
|
5,
|
|
|
|
);
|
|
|
|
await client.perpPlaceOrder(
|
|
|
|
group,
|
|
|
|
mangoAccount,
|
|
|
|
perpIndex,
|
|
|
|
PerpOrderSide.ask,
|
|
|
|
0.01,
|
|
|
|
1.1, // ui base quantity, 11 base lots, $0.011
|
|
|
|
0.011, // ui quote quantity
|
|
|
|
4200,
|
|
|
|
PerpOrderType.market,
|
|
|
|
false,
|
|
|
|
0,
|
|
|
|
5,
|
|
|
|
);
|
|
|
|
await client.perpConsumeAllEvents(group, perpIndex);
|
|
|
|
|
|
|
|
await setPerpPrice(perpMarket, PRICES['MNGO']);
|
|
|
|
|
|
|
|
await client.perpPlaceOrder(
|
|
|
|
group,
|
|
|
|
fundingAccount,
|
|
|
|
perpIndex,
|
|
|
|
PerpOrderSide.ask,
|
|
|
|
0.02,
|
|
|
|
1.1, // ui base quantity, 11 base lots, $0.022
|
|
|
|
0.022, // ui quote quantity
|
|
|
|
4201,
|
|
|
|
PerpOrderType.limit,
|
|
|
|
false,
|
|
|
|
0,
|
|
|
|
5,
|
|
|
|
);
|
|
|
|
await client.perpPlaceOrder(
|
|
|
|
group,
|
|
|
|
mangoAccount,
|
|
|
|
perpIndex,
|
|
|
|
PerpOrderSide.bid,
|
|
|
|
0.02,
|
|
|
|
1.1, // ui base quantity, 11 base lots, $0.022
|
|
|
|
0.022, // ui quote quantity
|
|
|
|
4201,
|
|
|
|
PerpOrderType.market,
|
|
|
|
false,
|
|
|
|
0,
|
|
|
|
5,
|
|
|
|
);
|
|
|
|
await client.perpConsumeAllEvents(group, perpIndex);
|
|
|
|
} finally {
|
|
|
|
await setPerpPrice(perpMarket, PRICES['MNGO']);
|
|
|
|
await setBankPrice(collateralBank, PRICES['SOL']);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-08 08:49:10 -07:00
|
|
|
process.exit();
|
|
|
|
}
|
|
|
|
|
2023-05-17 06:50:05 -07:00
|
|
|
function assertNotUndefined<T>(value: T | undefined): T {
|
|
|
|
if (value === undefined) {
|
|
|
|
throw new Error('Value was undefined');
|
|
|
|
}
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
2022-08-08 08:49:10 -07:00
|
|
|
main();
|