230 lines
7.0 KiB
TypeScript
230 lines
7.0 KiB
TypeScript
import { Market, OpenOrders } from '@project-serum/serum';
|
|
import { Account, Commitment, Connection, PublicKey } from '@solana/web3.js';
|
|
import * as os from 'os';
|
|
import * as fs from 'fs';
|
|
|
|
import { MangoClient, MangoGroup } from './client';
|
|
import IDS from './ids.json';
|
|
import {
|
|
decodeRecentEvents,
|
|
findLargestTokenAccountForOwner,
|
|
getMultipleAccounts,
|
|
nativeToUi,
|
|
parseTokenAccountData,
|
|
sleep,
|
|
} from './utils';
|
|
import { NUM_MARKETS, NUM_TOKENS } from './layout';
|
|
|
|
async function tests() {
|
|
const cluster = 'mainnet-beta';
|
|
const client = new MangoClient();
|
|
const clusterIds = IDS[cluster];
|
|
|
|
const connection = new Connection(
|
|
IDS.cluster_urls[cluster],
|
|
'processed' as Commitment,
|
|
);
|
|
const mangoGroupPk = new PublicKey(
|
|
clusterIds.mango_groups['BTC_ETH_SOL_SRM_USDC'].mango_group_pk,
|
|
);
|
|
const mangoProgramId = new PublicKey(clusterIds.mango_program_id);
|
|
|
|
const keyPairPath =
|
|
process.env.KEYPAIR || os.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(
|
|
'BZXTBk41pBuwgw4RL3hUxRXqSdiA7VQiaxr4ueEMZrsH',
|
|
);
|
|
const marginAccount = await client.getMarginAccount(
|
|
connection,
|
|
marginAccountPk,
|
|
mangoGroup.dexProgramId,
|
|
);
|
|
const prices = await mangoGroup.getPrices(connection);
|
|
|
|
console.log(marginAccount.toPrettyString(mangoGroup, prices));
|
|
console.log(marginAccount.beingLiquidated);
|
|
console.log(marginAccount.getCollateralRatio(mangoGroup, prices));
|
|
|
|
for (let i = 0; i < NUM_TOKENS; i++) {
|
|
console.log(
|
|
marginAccount.getUiDeposit(mangoGroup, i),
|
|
marginAccount.getUiBorrow(mangoGroup, i),
|
|
);
|
|
}
|
|
for (let i = 0; i < NUM_MARKETS; i++) {
|
|
let openOrdersAccount = marginAccount.openOrdersAccounts[i];
|
|
if (openOrdersAccount === undefined) {
|
|
continue;
|
|
}
|
|
|
|
console.log(
|
|
'referrer rebates',
|
|
i,
|
|
openOrdersAccount['referrerRebatesAccrued'].toNumber(),
|
|
);
|
|
console.log(
|
|
i,
|
|
nativeToUi(
|
|
openOrdersAccount.quoteTokenTotal.toNumber() +
|
|
openOrdersAccount['referrerRebatesAccrued'].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],
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
async function testMarketOrderDex() {
|
|
const NUM_MARKETS = 2;
|
|
const dexProgramId = new PublicKey(clusterIds.dex_program_id);
|
|
|
|
const mangoGroup = await client.getMangoGroup(connection, mangoGroupPk);
|
|
|
|
// load largest wallet account for each token
|
|
const tokenWallets = await Promise.all(
|
|
mangoGroup.tokens.map((mint) =>
|
|
findLargestTokenAccountForOwner(connection, payer.publicKey, mint).then(
|
|
(response) => response.publicKey,
|
|
),
|
|
),
|
|
);
|
|
console.log({ tokenWallets: tokenWallets.map((w) => w.toString()) });
|
|
|
|
// load all markets
|
|
const markets = await Promise.all(
|
|
mangoGroup.spotMarkets.map((pk) =>
|
|
Market.load(
|
|
connection,
|
|
pk,
|
|
{ skipPreflight: true, commitment: 'singleGossip' },
|
|
dexProgramId,
|
|
),
|
|
),
|
|
);
|
|
console.log({ markets });
|
|
|
|
// load open orders
|
|
const liqorOpenOrdersKeys: PublicKey[] = [];
|
|
for (let i = 0; i < NUM_MARKETS; i++) {
|
|
let openOrdersAccounts: OpenOrders[] = await markets[
|
|
i
|
|
].findOpenOrdersAccountsForOwner(connection, payer.publicKey);
|
|
if (openOrdersAccounts.length) {
|
|
liqorOpenOrdersKeys.push(openOrdersAccounts[0].publicKey);
|
|
} else {
|
|
console.log(
|
|
`No OpenOrders account found for market ${markets[
|
|
i
|
|
].publicKey.toBase58()}`,
|
|
);
|
|
}
|
|
}
|
|
console.log({
|
|
liqorOpenOrdersKeys: liqorOpenOrdersKeys.map((k) => k.toString()),
|
|
});
|
|
|
|
const marketIndex = 1;
|
|
const market = markets[marketIndex]; // ETH/USDT
|
|
const price = 4000;
|
|
const size = 0.001;
|
|
|
|
const txid = await market.placeOrder(connection, {
|
|
owner: payer,
|
|
payer: tokenWallets[marketIndex],
|
|
side: 'sell',
|
|
price,
|
|
size,
|
|
orderType: 'ioc',
|
|
openOrdersAddressKey: liqorOpenOrdersKeys[marketIndex],
|
|
feeDiscountPubkey: null, // TODO find liqor's SRM fee account
|
|
});
|
|
console.log({ txid });
|
|
|
|
var lastSeenSeqNum = undefined;
|
|
|
|
for (let i = 0; i < 50; ++i) {
|
|
const status = await connection.getSignatureStatus(txid);
|
|
console.log({ status: status!.value!.confirmations });
|
|
|
|
let orders = await market.loadOrdersForOwner(connection, payer.publicKey);
|
|
console.log({ orders });
|
|
|
|
const info = await connection.getAccountInfo(
|
|
market['_decoded'].eventQueue,
|
|
);
|
|
const { header, nodes } = decodeRecentEvents(info!.data, lastSeenSeqNum);
|
|
console.log({
|
|
header,
|
|
nodes: nodes.map((n) => [
|
|
n.nativeQuantityPaid.toNumber(),
|
|
n.nativeQuantityReleased.toNumber(),
|
|
]),
|
|
});
|
|
lastSeenSeqNum = header.seqNum;
|
|
|
|
const liqorWalletAccounts = await getMultipleAccounts(
|
|
connection,
|
|
tokenWallets,
|
|
'processed' as Commitment,
|
|
);
|
|
const liqorValuesUi = liqorWalletAccounts.map((a, i) =>
|
|
nativeToUi(
|
|
parseTokenAccountData(a.accountInfo.data).amount,
|
|
mangoGroup.mintDecimals[i],
|
|
),
|
|
);
|
|
console.log({ liqorValuesUi });
|
|
await sleep(500);
|
|
}
|
|
}
|
|
|
|
await getMarginAccountDetails();
|
|
// await testSolink()
|
|
// await testDepositSrm()
|
|
// await testMarketOrderDex()
|
|
}
|
|
|
|
tests();
|