ts: fix typechecking on scripts (#269)
Signed-off-by: microwavedcola1 <microwavedcola@gmail.com> Signed-off-by: microwavedcola1 <microwavedcola@gmail.com>
This commit is contained in:
parent
a66177a77e
commit
cd8c500be5
|
@ -2,9 +2,9 @@ import { AnchorProvider, Wallet } from '@project-serum/anchor';
|
|||
import { coder } from '@project-serum/anchor/dist/cjs/spl/token';
|
||||
import { Cluster, Connection, Keypair } from '@solana/web3.js';
|
||||
import fs from 'fs';
|
||||
import { I80F48, ZERO_I80F48 } from '../accounts/I80F48';
|
||||
import { MangoClient } from '../client';
|
||||
import { MANGO_V4_ID } from '../constants';
|
||||
import { I80F48, ZERO_I80F48 } from '../numbers/I80F48';
|
||||
import { toUiDecimals } from '../utils';
|
||||
|
||||
const CLUSTER_URL =
|
||||
|
@ -15,7 +15,7 @@ const GROUP_NUM = Number(process.env.GROUP_NUM || 2);
|
|||
const CLUSTER: Cluster =
|
||||
(process.env.CLUSTER_OVERRIDE as Cluster) || 'mainnet-beta';
|
||||
|
||||
async function main() {
|
||||
async function main(): Promise<void> {
|
||||
const options = AnchorProvider.defaultOptions();
|
||||
const connection = new Connection(CLUSTER_URL!, options);
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ async function debugUser(
|
|||
client: MangoClient,
|
||||
group: Group,
|
||||
mangoAccount: MangoAccount,
|
||||
) {
|
||||
): Promise<void> {
|
||||
console.log(mangoAccount.toString(group));
|
||||
|
||||
await mangoAccount.reload(client);
|
||||
|
@ -80,7 +80,9 @@ async function debugUser(
|
|||
),
|
||||
);
|
||||
|
||||
async function getMaxWithdrawWithBorrowForTokenUiWrapper(token) {
|
||||
async function getMaxWithdrawWithBorrowForTokenUiWrapper(
|
||||
token,
|
||||
): Promise<void> {
|
||||
console.log(
|
||||
`mangoAccount.getMaxWithdrawWithBorrowForTokenUi(group, ${token}) ` +
|
||||
mangoAccount.getMaxWithdrawWithBorrowForTokenUi(
|
||||
|
@ -93,7 +95,7 @@ async function debugUser(
|
|||
await getMaxWithdrawWithBorrowForTokenUiWrapper(srcToken);
|
||||
}
|
||||
|
||||
function simHealthRatioWithTokenPositionChangesWrapper(debug, change) {
|
||||
function simHealthRatioWithTokenPositionChangesWrapper(debug, change): void {
|
||||
console.log(
|
||||
`mangoAccount.simHealthRatioWithTokenPositionChanges ${debug}` +
|
||||
mangoAccount.simHealthRatioWithTokenPositionUiChanges(group, [change]),
|
||||
|
@ -110,7 +112,7 @@ async function debugUser(
|
|||
});
|
||||
}
|
||||
|
||||
function getMaxSourceForTokenSwapWrapper(src, tgt) {
|
||||
function getMaxSourceForTokenSwapWrapper(src, tgt): void {
|
||||
console.log(
|
||||
`getMaxSourceForTokenSwap ${src.padEnd(4)} ${tgt.padEnd(4)} ` +
|
||||
mangoAccount.getMaxSourceUiForTokenSwap(
|
||||
|
@ -129,7 +131,7 @@ async function debugUser(
|
|||
}
|
||||
}
|
||||
|
||||
function getMaxForPerpWrapper(perpMarket: PerpMarket) {
|
||||
function getMaxForPerpWrapper(perpMarket: PerpMarket): void {
|
||||
console.log(
|
||||
`getMaxQuoteForPerpBidUi ${perpMarket.perpMarketIndex} ` +
|
||||
mangoAccount.getMaxQuoteForPerpBidUi(group, perpMarket.perpMarketIndex),
|
||||
|
@ -145,7 +147,7 @@ async function debugUser(
|
|||
getMaxForPerpWrapper(perpMarket);
|
||||
}
|
||||
|
||||
function getMaxForSerum3Wrapper(serum3Market: Serum3Market) {
|
||||
function getMaxForSerum3Wrapper(serum3Market: Serum3Market): void {
|
||||
// if (serum3Market.name !== 'SOL/USDC') return;
|
||||
console.log(
|
||||
`getMaxQuoteForSerum3BidUi ${serum3Market.name} ` +
|
||||
|
@ -169,7 +171,7 @@ async function debugUser(
|
|||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
async function main(): Promise<void> {
|
||||
const options = AnchorProvider.defaultOptions();
|
||||
const connection = new Connection(CLUSTER_URL!, options);
|
||||
|
||||
|
|
|
@ -1,108 +0,0 @@
|
|||
import { AnchorProvider, Wallet } from '@project-serum/anchor';
|
||||
|
||||
import { Connection, Keypair } from '@solana/web3.js';
|
||||
import fs from 'fs';
|
||||
import idsJson from '../../../ids.json';
|
||||
import { MangoClient } from '../../client';
|
||||
import { MANGO_V4_ID, SERUM3_PROGRAM_ID } from '../../constants';
|
||||
import { Id } from '../../ids';
|
||||
|
||||
//
|
||||
// script to add a group to ids json
|
||||
//
|
||||
|
||||
function replacer(key, value) {
|
||||
if (value instanceof Map) {
|
||||
return Object.fromEntries(value);
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const groupName = 'devnet.microwavedcola';
|
||||
const cluster = 'devnet';
|
||||
|
||||
// build client and fetch group for admin
|
||||
const options = AnchorProvider.defaultOptions();
|
||||
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);
|
||||
const userProvider = new AnchorProvider(connection, userWallet, options);
|
||||
const client = await MangoClient.connect(
|
||||
userProvider,
|
||||
cluster,
|
||||
MANGO_V4_ID[cluster],
|
||||
);
|
||||
const admin = Keypair.fromSecretKey(
|
||||
Buffer.from(
|
||||
JSON.parse(fs.readFileSync(process.env.ADMIN_KEYPAIR!, 'utf-8')),
|
||||
),
|
||||
);
|
||||
const group = await client.getGroupForCreator(admin.publicKey, 0);
|
||||
|
||||
// collect mappings &
|
||||
// collect pubkeys
|
||||
const banks = await client.getBanksForGroup(group);
|
||||
const banksMapByMint = new Map(
|
||||
banks.map((tuple) => [tuple.mint.toBase58(), tuple]),
|
||||
);
|
||||
const stubOracles = await client.getStubOracle(group);
|
||||
const mintInfos = await client.getMintInfosForGroup(group);
|
||||
const serum3Markets = await client.serum3GetMarkets(group);
|
||||
const perpMarkets = await client.perpGetMarkets(group);
|
||||
|
||||
// build ids
|
||||
const toDump = new Id(
|
||||
cluster,
|
||||
groupName,
|
||||
group.publicKey.toBase58(),
|
||||
SERUM3_PROGRAM_ID[cluster].toBase58(),
|
||||
MANGO_V4_ID[cluster].toBase58(),
|
||||
banks.map((tuple) => ({
|
||||
name: tuple.name,
|
||||
publicKey: tuple.publicKey.toBase58(),
|
||||
})),
|
||||
stubOracles.map((tuple) => ({
|
||||
name: banksMapByMint.get(tuple.mint.toBase58())!.name,
|
||||
publicKey: tuple.publicKey.toBase58(),
|
||||
})),
|
||||
mintInfos.map((tuple) => ({
|
||||
name: banksMapByMint.get(tuple.mint.toBase58())!.name,
|
||||
publicKey: tuple.publicKey.toBase58(),
|
||||
})),
|
||||
serum3Markets.map((tuple) => ({
|
||||
name: tuple.name,
|
||||
publicKey: tuple.publicKey.toBase58(),
|
||||
marketExternal: tuple.serumMarketExternal.toBase58(),
|
||||
})),
|
||||
perpMarkets.map((tuple) => ({
|
||||
name: tuple.name,
|
||||
publicKey: tuple.publicKey.toBase58(),
|
||||
})),
|
||||
);
|
||||
|
||||
// adds ids for group in existing ids.json
|
||||
const existingGroup = idsJson.groups.find((group) => group.name == groupName);
|
||||
if (existingGroup) {
|
||||
console.log('Updating existing group with latest state...');
|
||||
} else {
|
||||
console.log('Group does not exist yet...');
|
||||
}
|
||||
idsJson.groups = idsJson.groups.filter((group) => group.name !== groupName);
|
||||
idsJson.groups.push(toDump);
|
||||
|
||||
// dump
|
||||
const file = `${process.cwd()}/ts/client/ids.json`;
|
||||
await fs.writeFileSync(file, JSON.stringify(idsJson, replacer, 2));
|
||||
|
||||
process.exit();
|
||||
}
|
||||
main();
|
|
@ -1,122 +0,0 @@
|
|||
import { AnchorProvider, Wallet } from '@project-serum/anchor';
|
||||
import { Connection, Keypair } from '@solana/web3.js';
|
||||
import fs from 'fs';
|
||||
import { MangoClient } from '../../client';
|
||||
import { MANGO_V4_ID } from '../../constants';
|
||||
|
||||
const GROUP_NUM = Number(process.env.GROUP_NUM || 0);
|
||||
|
||||
const DEVNET_MINTS = new Map([
|
||||
['USDC', '8FRFC6MoGGkMFQwngccyu69VnYbzykGeez7ignHVAFSN'], // use devnet usdc
|
||||
['BTC', '3UNBZ6o52WTWwjac2kPUb4FyodhU1vFkRJheu1Sh2TvU'],
|
||||
['SOL', 'So11111111111111111111111111111111111111112'],
|
||||
['ORCA', 'orcarKHSqC5CDDsGbho8GKvwExejWHxTqGzXgcewB9L'],
|
||||
['MNGO', 'Bb9bsTQa1bGEtQ5KagGkvSHyuLqDWumFUcRqFusFNJWC'],
|
||||
]);
|
||||
|
||||
async function main() {
|
||||
const options = AnchorProvider.defaultOptions();
|
||||
const connection = new Connection(
|
||||
'https://mango.devnet.rpcpool.com',
|
||||
options,
|
||||
);
|
||||
|
||||
// user1
|
||||
const user1 = Keypair.fromSecretKey(
|
||||
Buffer.from(
|
||||
JSON.parse(fs.readFileSync(process.env.PAYER_KEYPAIR!, 'utf-8')),
|
||||
),
|
||||
);
|
||||
const user1Wallet = new Wallet(user1);
|
||||
const user1Provider = new AnchorProvider(connection, user1Wallet, options);
|
||||
const user1Client = await MangoClient.connect(
|
||||
user1Provider,
|
||||
'devnet',
|
||||
MANGO_V4_ID['devnet'],
|
||||
);
|
||||
console.log(`user1 ${user1Wallet.publicKey.toBase58()}`);
|
||||
|
||||
const admin = Keypair.fromSecretKey(
|
||||
Buffer.from(
|
||||
JSON.parse(fs.readFileSync(process.env.ADMIN_KEYPAIR!, 'utf-8')),
|
||||
),
|
||||
);
|
||||
const group = await user1Client.getGroupForAdmin(admin.publicKey, GROUP_NUM);
|
||||
console.log(`Found group ${group.publicKey.toBase58()}`);
|
||||
|
||||
const user1MangoAccount = await user1Client.getOrCreateMangoAccount(group);
|
||||
|
||||
console.log(`...mangoAccount1 ${user1MangoAccount.publicKey}`);
|
||||
|
||||
/// user1 deposits some btc, so user2 can borrow it
|
||||
let amount = 0.001;
|
||||
let token = 'BTC';
|
||||
console.log(`Depositing...${amount} 'BTC'`);
|
||||
await user1Client.tokenDeposit(group, user1MangoAccount, token, amount);
|
||||
await user1MangoAccount.reload(user1Client, group);
|
||||
console.log(`${user1MangoAccount.toString(group)}`);
|
||||
|
||||
// user 2
|
||||
const user2 = Keypair.fromSecretKey(
|
||||
Buffer.from(
|
||||
JSON.parse(fs.readFileSync(process.env.USER_KEYPAIR!, 'utf-8')),
|
||||
),
|
||||
);
|
||||
const user2Wallet = new Wallet(user2);
|
||||
const user2Provider = new AnchorProvider(connection, user2Wallet, options);
|
||||
const user2Client = await MangoClient.connect(
|
||||
user2Provider,
|
||||
'devnet',
|
||||
MANGO_V4_ID['devnet'],
|
||||
);
|
||||
console.log(`user2 ${user2Wallet.publicKey.toBase58()}`);
|
||||
|
||||
const user2MangoAccount = await user2Client.getOrCreateMangoAccount(group);
|
||||
console.log(`...mangoAccount2 ${user2MangoAccount.publicKey}`);
|
||||
|
||||
/// Increase usdc price temporarily to allow lots of borrows
|
||||
console.log(
|
||||
`Setting USDC price to 1.5, to allow the user to borrow lots of btc`,
|
||||
);
|
||||
const adminWallet = new Wallet(admin);
|
||||
console.log(`Admin ${adminWallet.publicKey.toBase58()}`);
|
||||
const adminProvider = new AnchorProvider(connection, adminWallet, options);
|
||||
const client = await MangoClient.connect(
|
||||
adminProvider,
|
||||
'devnet',
|
||||
MANGO_V4_ID['devnet'],
|
||||
);
|
||||
await client.stubOracleSet(group, group.banksMap.get('USDC')?.oracle!, 1.5);
|
||||
|
||||
/// user2 deposits some collateral and borrows BTC
|
||||
amount = 1;
|
||||
console.log(`Depositing...${amount} 'USDC'`);
|
||||
await user2Client.tokenDeposit(group, user2MangoAccount, 'USDC', amount);
|
||||
await user2MangoAccount.reload(user2Client, group);
|
||||
console.log(`${user2MangoAccount.toString(group)}`);
|
||||
|
||||
const maxNative = await (
|
||||
await user2MangoAccount.getMaxWithdrawWithBorrowForToken(group, token)
|
||||
).toNumber();
|
||||
amount = 0.9 * maxNative;
|
||||
console.log(`Withdrawing...${amount} native BTC'`);
|
||||
await user2Client.tokenWithdrawNative(
|
||||
group,
|
||||
user2MangoAccount,
|
||||
token,
|
||||
amount,
|
||||
true,
|
||||
);
|
||||
await user2MangoAccount.reload(user2Client, group);
|
||||
console.log(`${user2MangoAccount.toString(group)}`);
|
||||
|
||||
/// Reduce usdc price to normal again
|
||||
console.log(
|
||||
`Setting USDC price back to 1.0, decreasing the user's collateral size`,
|
||||
);
|
||||
await client.stubOracleSet(group, group.banksMap.get('USDC')?.oracle!, 1.0);
|
||||
|
||||
process.exit();
|
||||
}
|
||||
|
||||
main();
|
|
@ -1,84 +0,0 @@
|
|||
import { AnchorProvider, Wallet } from '@project-serum/anchor';
|
||||
import { Connection, Keypair, PublicKey } from '@solana/web3.js';
|
||||
import fs from 'fs';
|
||||
import { MangoClient } from '../../client';
|
||||
import { MANGO_V4_ID } from '../../constants';
|
||||
|
||||
//
|
||||
// (unfinished?) script which shows how to use the flash loan 1 ix
|
||||
//
|
||||
|
||||
const DEVNET_MINTS = new Map([
|
||||
['USDC', '8FRFC6MoGGkMFQwngccyu69VnYbzykGeez7ignHVAFSN'], // use devnet usdc
|
||||
['BTC', '3UNBZ6o52WTWwjac2kPUb4FyodhU1vFkRJheu1Sh2TvU'],
|
||||
['SOL', 'So11111111111111111111111111111111111111112'],
|
||||
['ORCA', 'orcarKHSqC5CDDsGbho8GKvwExejWHxTqGzXgcewB9L'],
|
||||
['MNGO', 'Bb9bsTQa1bGEtQ5KagGkvSHyuLqDWumFUcRqFusFNJWC'],
|
||||
]);
|
||||
|
||||
async function main() {
|
||||
const options = AnchorProvider.defaultOptions();
|
||||
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);
|
||||
const userProvider = new AnchorProvider(connection, userWallet, options);
|
||||
const client = await MangoClient.connect(
|
||||
userProvider,
|
||||
'devnet',
|
||||
MANGO_V4_ID['devnet'],
|
||||
);
|
||||
console.log(`User ${userWallet.publicKey.toBase58()}`);
|
||||
|
||||
// fetch group
|
||||
const admin = Keypair.fromSecretKey(
|
||||
Buffer.from(
|
||||
JSON.parse(fs.readFileSync(process.env.ADMIN_KEYPAIR!, 'utf-8')),
|
||||
),
|
||||
);
|
||||
const group = await client.getGroupForCreator(admin.publicKey, 0);
|
||||
console.log(`Found group ${group.publicKey.toBase58()}`);
|
||||
|
||||
// create + fetch account
|
||||
console.log(`Creating mangoaccount...`);
|
||||
const mangoAccount = await client.getOrCreateMangoAccount(group);
|
||||
console.log(`...created/found mangoAccount ${mangoAccount.publicKey}`);
|
||||
console.log(mangoAccount.toString());
|
||||
|
||||
if (false) {
|
||||
// deposit and withdraw
|
||||
console.log(`Depositing...50 USDC`);
|
||||
await client.tokenDeposit(group, mangoAccount, 'USDC', 50);
|
||||
await mangoAccount.reload(client, group);
|
||||
|
||||
console.log(`Depositing...0.0005 BTC`);
|
||||
await client.tokenDeposit(group, mangoAccount, 'BTC', 0.0005);
|
||||
await mangoAccount.reload(client, group);
|
||||
}
|
||||
try {
|
||||
const sig = await client.marginTrade({
|
||||
group: group,
|
||||
mangoAccount: mangoAccount,
|
||||
inputMintPk: new PublicKey(DEVNET_MINTS['USDC']),
|
||||
amountIn: 0.001,
|
||||
outputMintPk: new PublicKey(DEVNET_MINTS['SOL']),
|
||||
slippage: 1,
|
||||
});
|
||||
console.log(
|
||||
`sig https://explorer.solana.com/address/${sig}?cluster=devnet`,
|
||||
);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
process.exit();
|
||||
}
|
||||
|
||||
main();
|
|
@ -1,39 +0,0 @@
|
|||
import { AnchorProvider, Wallet } from '@project-serum/anchor';
|
||||
import { Connection, Keypair } from '@solana/web3.js';
|
||||
import fs from 'fs';
|
||||
import { MangoClient } from '../../client';
|
||||
|
||||
//
|
||||
// script which shows example usage of ids json (saves having to do gpa)
|
||||
//
|
||||
async function main() {
|
||||
const options = AnchorProvider.defaultOptions();
|
||||
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);
|
||||
const userProvider = new AnchorProvider(connection, userWallet, options);
|
||||
const client = await MangoClient.connectForGroupName(
|
||||
userProvider,
|
||||
'devnet.microwavedcola' /* Use ids json instead of getProgramAccounts */,
|
||||
);
|
||||
console.log(`User ${userWallet.publicKey.toBase58()}`);
|
||||
|
||||
const admin = Keypair.fromSecretKey(
|
||||
Buffer.from(
|
||||
JSON.parse(fs.readFileSync(process.env.ADMIN_KEYPAIR!, 'utf-8')),
|
||||
),
|
||||
);
|
||||
const group = await client.getGroupForCreator(admin.publicKey, 0);
|
||||
console.log(`Found group ${group.publicKey.toBase58()}`);
|
||||
process.exit();
|
||||
}
|
||||
|
||||
main();
|
|
@ -1,69 +0,0 @@
|
|||
import { AnchorProvider, Wallet } from '@project-serum/anchor';
|
||||
import { Connection, Keypair } from '@solana/web3.js';
|
||||
import fs from 'fs';
|
||||
import { MANGO_V4_ID } from '../../constants';
|
||||
import { MangoClient } from '../../index';
|
||||
|
||||
//
|
||||
// An example for users based on high level api i.e. the client
|
||||
// Create
|
||||
// process.env.USER_KEYPAIR - mango account owner keypair path
|
||||
// process.env.ADMIN_KEYPAIR - group admin keypair path (useful for automatically finding the group)
|
||||
//
|
||||
async function main() {
|
||||
const options = AnchorProvider.defaultOptions();
|
||||
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);
|
||||
const userProvider = new AnchorProvider(connection, userWallet, options);
|
||||
const client = await MangoClient.connect(
|
||||
userProvider,
|
||||
'devnet',
|
||||
MANGO_V4_ID['devnet'],
|
||||
);
|
||||
console.log(`User ${userWallet.publicKey.toBase58()}`);
|
||||
|
||||
// fetch group
|
||||
const admin = Keypair.fromSecretKey(
|
||||
Buffer.from(
|
||||
JSON.parse(fs.readFileSync(process.env.ADMIN_KEYPAIR!, 'utf-8')),
|
||||
),
|
||||
);
|
||||
const group = await client.getGroupForCreator(admin.publicKey, 0);
|
||||
console.log(`Found group ${group.publicKey.toBase58()}`);
|
||||
|
||||
// create + fetch account
|
||||
console.log(`Creating mangoaccount...`);
|
||||
const mangoAccount = await client.getOrCreateMangoAccount(group);
|
||||
console.log(`...created/found mangoAccount ${mangoAccount.publicKey}`);
|
||||
|
||||
// logging serum3 open orders for user
|
||||
while (true) {
|
||||
console.log(`Current own orders on OB...`);
|
||||
const orders = await client.getSerum3Orders(
|
||||
group,
|
||||
|
||||
'BTC/USDC',
|
||||
);
|
||||
for (const order of orders) {
|
||||
console.log(
|
||||
` - Order orderId ${order.orderId}, ${order.side}, ${order.price}, ${
|
||||
order.size
|
||||
} ${order.openOrdersAddress.toBase58()}`,
|
||||
);
|
||||
}
|
||||
await new Promise((r) => setTimeout(r, 500));
|
||||
}
|
||||
|
||||
process.exit();
|
||||
}
|
||||
|
||||
main();
|
|
@ -1,58 +0,0 @@
|
|||
import { AnchorProvider, Wallet } from '@project-serum/anchor';
|
||||
import { Connection, Keypair } from '@solana/web3.js';
|
||||
import fs from 'fs';
|
||||
import { TokenPosition } from '../../accounts/mangoAccount';
|
||||
import { MANGO_V4_ID } from '../../constants';
|
||||
import { MangoClient } from '../../index';
|
||||
|
||||
//
|
||||
// An example for users based on high level api i.e. the client
|
||||
// Create
|
||||
// process.env.USER_KEYPAIR - mango account owner keypair path
|
||||
// process.env.ADMIN_KEYPAIR - group admin keypair path (useful for automatically finding the group)
|
||||
//
|
||||
async function main() {
|
||||
const options = AnchorProvider.defaultOptions();
|
||||
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);
|
||||
const userProvider = new AnchorProvider(connection, userWallet, options);
|
||||
const client = await MangoClient.connect(
|
||||
userProvider,
|
||||
'devnet',
|
||||
MANGO_V4_ID['devnet'],
|
||||
);
|
||||
console.log(`User ${userWallet.publicKey.toBase58()}`);
|
||||
|
||||
// fetch group
|
||||
const admin = Keypair.fromSecretKey(
|
||||
Buffer.from(
|
||||
JSON.parse(fs.readFileSync(process.env.ADMIN_KEYPAIR!, 'utf-8')),
|
||||
),
|
||||
);
|
||||
const group = await client.getGroupForCreator(admin.publicKey, 0);
|
||||
console.log(`Found group ${group.publicKey.toBase58()}`);
|
||||
|
||||
// create + fetch account
|
||||
console.log(`Creating mangoaccount...`);
|
||||
const mangoAccount = await client.getOrCreateMangoAccount(group);
|
||||
console.log(`...created/found mangoAccount ${mangoAccount.publicKey}`);
|
||||
|
||||
// log users tokens
|
||||
for (const token of mangoAccount.tokens) {
|
||||
if (token.tokenIndex == TokenPosition.TokenIndexUnset) continue;
|
||||
console.log(token.toString());
|
||||
}
|
||||
|
||||
process.exit();
|
||||
}
|
||||
|
||||
main();
|
|
@ -1,192 +0,0 @@
|
|||
import { AnchorProvider, Wallet } from '@project-serum/anchor';
|
||||
import { Connection, Keypair, PublicKey } from '@solana/web3.js';
|
||||
import fs from 'fs';
|
||||
import { OrderType, Side } from '../../accounts/perp';
|
||||
import {
|
||||
Serum3OrderType,
|
||||
Serum3SelfTradeBehavior,
|
||||
Serum3Side,
|
||||
} from '../../accounts/serum3';
|
||||
import { MangoClient } from '../../client';
|
||||
import { MANGO_V4_ID } from '../../constants';
|
||||
|
||||
//
|
||||
// An example for users based on high level api i.e. the client
|
||||
// Create
|
||||
// process.env.USER_KEYPAIR - mango account owner keypair path
|
||||
// process.env.ADMIN_KEYPAIR - group admin keypair path (useful for automatically finding the group)
|
||||
//
|
||||
// This script deposits some tokens, places some serum orders, cancels them, places some perp orders
|
||||
//
|
||||
|
||||
const DEVNET_MINTS = new Map([
|
||||
['USDC', '8FRFC6MoGGkMFQwngccyu69VnYbzykGeez7ignHVAFSN'], // use devnet usdc
|
||||
['BTC', '3UNBZ6o52WTWwjac2kPUb4FyodhU1vFkRJheu1Sh2TvU'],
|
||||
['SOL', 'So11111111111111111111111111111111111111112'],
|
||||
['ORCA', 'orcarKHSqC5CDDsGbho8GKvwExejWHxTqGzXgcewB9L'],
|
||||
['MNGO', 'Bb9bsTQa1bGEtQ5KagGkvSHyuLqDWumFUcRqFusFNJWC'],
|
||||
]);
|
||||
|
||||
async function main() {
|
||||
const options = AnchorProvider.defaultOptions();
|
||||
const connection = new Connection(
|
||||
'https://mango.devnet.rpcpool.com',
|
||||
options,
|
||||
);
|
||||
|
||||
// mango account owner
|
||||
const user = Keypair.fromSecretKey(
|
||||
Buffer.from(
|
||||
JSON.parse(fs.readFileSync(process.env.USER_KEYPAIR!, 'utf-8')),
|
||||
),
|
||||
);
|
||||
const userWallet = new Wallet(user);
|
||||
const userProvider = new AnchorProvider(connection, userWallet, options);
|
||||
const client = await MangoClient.connect(
|
||||
userProvider,
|
||||
'devnet',
|
||||
MANGO_V4_ID['devnet'],
|
||||
);
|
||||
console.log(`User ${userWallet.publicKey.toBase58()}`);
|
||||
|
||||
// delegate
|
||||
const delegate = Keypair.fromSecretKey(
|
||||
Buffer.from(
|
||||
JSON.parse(fs.readFileSync(process.env.USER3_KEYPAIR!, 'utf-8')),
|
||||
),
|
||||
);
|
||||
const delegateWallet = new Wallet(delegate);
|
||||
const delegateProvider = new AnchorProvider(
|
||||
connection,
|
||||
delegateWallet,
|
||||
options,
|
||||
);
|
||||
// Note: simply create a client with delegate and use this client to execute ixs
|
||||
const delegateClient = await MangoClient.connect(
|
||||
delegateProvider,
|
||||
'devnet',
|
||||
MANGO_V4_ID['devnet'],
|
||||
);
|
||||
console.log(`Delegate ${delegateWallet.publicKey.toBase58()}`);
|
||||
|
||||
// fetch group
|
||||
const admin = Keypair.fromSecretKey(
|
||||
Buffer.from(
|
||||
JSON.parse(fs.readFileSync(process.env.ADMIN_KEYPAIR!, 'utf-8')),
|
||||
),
|
||||
);
|
||||
const group = await delegateClient.getGroupForAdmin(admin.publicKey, 0);
|
||||
console.log(group.toString());
|
||||
|
||||
// fetch mango account using owners pubkey
|
||||
console.log(`Fetching mangoaccount...`);
|
||||
const mangoAccount = (
|
||||
await delegateClient.getMangoAccountForOwner(group, user.publicKey)
|
||||
)[0];
|
||||
console.log(`...created/found mangoAccount ${mangoAccount.publicKey}`);
|
||||
console.log(mangoAccount.toString());
|
||||
|
||||
if (true) {
|
||||
// set delegate, and change name
|
||||
console.log(`...changing mango account name, and setting a delegate`);
|
||||
await client.editMangoAccount(
|
||||
group,
|
||||
mangoAccount,
|
||||
'my_changed_name',
|
||||
delegate.publicKey,
|
||||
);
|
||||
await mangoAccount.reload(client, group);
|
||||
console.log(mangoAccount.toString());
|
||||
}
|
||||
|
||||
if (true) {
|
||||
// deposit
|
||||
console.log(`...depositing 50 USDC`);
|
||||
await client.tokenDeposit(
|
||||
group,
|
||||
mangoAccount,
|
||||
new PublicKey(DEVNET_MINTS['USDC']),
|
||||
50,
|
||||
);
|
||||
await mangoAccount.reload(client, group);
|
||||
|
||||
console.log(`...depositing 0.0005 BTC`);
|
||||
await client.tokenDeposit(
|
||||
group,
|
||||
mangoAccount,
|
||||
new PublicKey(DEVNET_MINTS['BTC']),
|
||||
0.0005,
|
||||
);
|
||||
await mangoAccount.reload(client, group);
|
||||
|
||||
// serum3
|
||||
console.log(`...placing serum3 bid`);
|
||||
await delegateClient.serum3PlaceOrder(
|
||||
group,
|
||||
mangoAccount,
|
||||
'BTC/USDC',
|
||||
Serum3Side.bid,
|
||||
20,
|
||||
0.0001,
|
||||
Serum3SelfTradeBehavior.decrementTake,
|
||||
Serum3OrderType.limit,
|
||||
Date.now(),
|
||||
10,
|
||||
);
|
||||
await mangoAccount.reload(delegateClient, group);
|
||||
|
||||
console.log(`...current own orders on OB`);
|
||||
let orders = await delegateClient.getSerum3Orders(
|
||||
group,
|
||||
|
||||
'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 delegateClient.serum3CancelOrder(
|
||||
group,
|
||||
mangoAccount,
|
||||
'BTC/USDC',
|
||||
order.side === 'buy' ? Serum3Side.bid : Serum3Side.ask,
|
||||
order.orderId,
|
||||
);
|
||||
}
|
||||
|
||||
console.log(`...settling funds`);
|
||||
await delegateClient.serum3SettleFunds(
|
||||
group,
|
||||
mangoAccount,
|
||||
|
||||
'BTC/USDC',
|
||||
);
|
||||
}
|
||||
|
||||
if (true) {
|
||||
// perps
|
||||
console.log(`...placing perp bid`);
|
||||
try {
|
||||
await delegateClient.perpPlaceOrder(
|
||||
group,
|
||||
mangoAccount,
|
||||
'BTC-PERP',
|
||||
Side.bid,
|
||||
30000,
|
||||
0.000001,
|
||||
30000 * 0.000001,
|
||||
Math.floor(Math.random() * 99999),
|
||||
OrderType.limit,
|
||||
0,
|
||||
1,
|
||||
);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
process.exit();
|
||||
}
|
||||
|
||||
main();
|
|
@ -1,150 +0,0 @@
|
|||
import { AnchorProvider, Wallet } from '@project-serum/anchor';
|
||||
import { Connection, Keypair, PublicKey } from '@solana/web3.js';
|
||||
import fs from 'fs';
|
||||
import { HealthType } from '../../accounts/mangoAccount';
|
||||
import { MangoClient } from '../../client';
|
||||
import { MANGO_V4_ID } from '../../constants';
|
||||
import { toUiDecimalsForQuote } from '../../utils';
|
||||
|
||||
const DEVNET_MINTS = new Map([
|
||||
['USDC', '8FRFC6MoGGkMFQwngccyu69VnYbzykGeez7ignHVAFSN'], // use devnet usdc
|
||||
['BTC', '3UNBZ6o52WTWwjac2kPUb4FyodhU1vFkRJheu1Sh2TvU'],
|
||||
['SOL', 'So11111111111111111111111111111111111111112'],
|
||||
['ORCA', 'orcarKHSqC5CDDsGbho8GKvwExejWHxTqGzXgcewB9L'],
|
||||
['MNGO', 'Bb9bsTQa1bGEtQ5KagGkvSHyuLqDWumFUcRqFusFNJWC'],
|
||||
]);
|
||||
|
||||
const GROUP_NUM = Number(process.env.GROUP_NUM || 0);
|
||||
|
||||
async function main() {
|
||||
const options = AnchorProvider.defaultOptions();
|
||||
const connection = new Connection(
|
||||
'https://mango.devnet.rpcpool.com',
|
||||
options,
|
||||
);
|
||||
|
||||
const user = Keypair.fromSecretKey(
|
||||
Buffer.from(
|
||||
JSON.parse(fs.readFileSync(process.env.USER2_KEYPAIR!, 'utf-8')),
|
||||
),
|
||||
);
|
||||
const userWallet = new Wallet(user);
|
||||
const userProvider = new AnchorProvider(connection, userWallet, options);
|
||||
const client = await MangoClient.connect(
|
||||
userProvider,
|
||||
'devnet',
|
||||
MANGO_V4_ID['devnet'],
|
||||
);
|
||||
console.log(`User ${userWallet.publicKey.toBase58()}`);
|
||||
|
||||
// fetch group
|
||||
const admin = Keypair.fromSecretKey(
|
||||
Buffer.from(
|
||||
JSON.parse(fs.readFileSync(process.env.ADMIN_KEYPAIR!, 'utf-8')),
|
||||
),
|
||||
);
|
||||
const group = await client.getGroupForCreator(admin.publicKey, GROUP_NUM);
|
||||
console.log(group.toString());
|
||||
|
||||
// create + fetch account
|
||||
console.log(`Creating mangoaccount...`);
|
||||
const mangoAccount = await client.getOrCreateMangoAccount(group);
|
||||
console.log(`...created/found mangoAccount ${mangoAccount.publicKey}`);
|
||||
console.log(mangoAccount.toString());
|
||||
|
||||
if (true) {
|
||||
await group.reloadAll(client);
|
||||
console.log(group.banksMapByName.get('USDC')![0].toString());
|
||||
console.log(group.banksMapByName.get('BTC')![0].toString());
|
||||
}
|
||||
|
||||
if (false) {
|
||||
// deposit and withdraw
|
||||
try {
|
||||
console.log(`...depositing 0.0005 BTC`);
|
||||
await client.tokenDeposit(
|
||||
group,
|
||||
mangoAccount,
|
||||
new PublicKey(DEVNET_MINTS['BTC']),
|
||||
0.0005,
|
||||
);
|
||||
await mangoAccount.reload(client, group);
|
||||
console.log(`...withdrawing 5 USDC`);
|
||||
await client.tokenWithdraw(
|
||||
group,
|
||||
mangoAccount,
|
||||
new PublicKey(DEVNET_MINTS['USDC']),
|
||||
50,
|
||||
true,
|
||||
);
|
||||
await mangoAccount.reload(client, group);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
if (true) {
|
||||
await mangoAccount.reload(client, group);
|
||||
console.log(
|
||||
'...mangoAccount.getEquity() ' +
|
||||
toUiDecimalsForQuote(mangoAccount.getEquity().toNumber()),
|
||||
);
|
||||
console.log(
|
||||
'...mangoAccount.getCollateralValue() ' +
|
||||
toUiDecimalsForQuote(mangoAccount.getCollateralValue().toNumber()),
|
||||
);
|
||||
console.log(
|
||||
'...mangoAccount.accountData["healthCache"].health(HealthType.init) ' +
|
||||
toUiDecimalsForQuote(
|
||||
mangoAccount.accountData['healthCache']
|
||||
.health(HealthType.init)
|
||||
.toNumber(),
|
||||
),
|
||||
);
|
||||
console.log(
|
||||
'...mangoAccount.getAssetsVal() ' +
|
||||
toUiDecimalsForQuote(mangoAccount.getAssetsVal().toNumber()),
|
||||
);
|
||||
console.log(
|
||||
'...mangoAccount.getLiabsVal() ' +
|
||||
toUiDecimalsForQuote(mangoAccount.getLiabsVal().toNumber()),
|
||||
);
|
||||
console.log(
|
||||
'...mangoAccount.getMaxWithdrawWithBorrowForToken(group, "SOL") ' +
|
||||
toUiDecimalsForQuote(
|
||||
(
|
||||
await mangoAccount.getMaxWithdrawWithBorrowForToken(
|
||||
group,
|
||||
new PublicKey(DEVNET_MINTS['SOL']),
|
||||
)
|
||||
).toNumber(),
|
||||
),
|
||||
);
|
||||
console.log(
|
||||
"...mangoAccount.getSerum3MarketMarginAvailable(group, 'BTC/USDC') " +
|
||||
toUiDecimalsForQuote(
|
||||
mangoAccount
|
||||
.getSerum3MarketMarginAvailable(group, 'BTC/USDC')
|
||||
.toNumber(),
|
||||
),
|
||||
);
|
||||
console.log(
|
||||
"...mangoAccount.getPerpMarketMarginAvailable(group, 'BTC-PERP') " +
|
||||
toUiDecimalsForQuote(
|
||||
mangoAccount
|
||||
.getPerpMarketMarginAvailable(group, 'BTC-PERP')
|
||||
.toNumber(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
if (true) {
|
||||
await group.reloadAll(client);
|
||||
console.log(group.banksMapByName.get('USDC')![0].toString());
|
||||
console.log(group.banksMapByName.get('BTC')![0].toString());
|
||||
}
|
||||
|
||||
process.exit();
|
||||
}
|
||||
|
||||
main();
|
|
@ -1,109 +0,0 @@
|
|||
import { AnchorProvider, Wallet } from '@project-serum/anchor';
|
||||
|
||||
import { Connection, Keypair } from '@solana/web3.js';
|
||||
import fs from 'fs';
|
||||
import idsJson from '../../../ids.json';
|
||||
import { MangoClient } from '../../client';
|
||||
import { MANGO_V4_ID, SERUM3_PROGRAM_ID } from '../../constants';
|
||||
import { Id } from '../../ids';
|
||||
|
||||
//
|
||||
// script to add a group to ids json
|
||||
//
|
||||
|
||||
function replacer(key, value) {
|
||||
if (value instanceof Map) {
|
||||
return Object.fromEntries(value);
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const groupName = 'mainnet-beta.microwavedcola';
|
||||
const cluster = 'mainnet-beta';
|
||||
|
||||
// build client and fetch group for admin
|
||||
const options = AnchorProvider.defaultOptions();
|
||||
const connection = new Connection(process.env.MB_CLUSTER_URL, options);
|
||||
const user = Keypair.fromSecretKey(
|
||||
Buffer.from(
|
||||
JSON.parse(fs.readFileSync(process.env.USER_KEYPAIR!, 'utf-8')),
|
||||
),
|
||||
);
|
||||
const userWallet = new Wallet(user);
|
||||
const userProvider = new AnchorProvider(connection, userWallet, options);
|
||||
const client = await MangoClient.connect(
|
||||
userProvider,
|
||||
cluster,
|
||||
MANGO_V4_ID[cluster],
|
||||
);
|
||||
const admin = Keypair.fromSecretKey(
|
||||
Buffer.from(
|
||||
JSON.parse(fs.readFileSync(process.env.MB_PAYER_KEYPAIR!, 'utf-8')),
|
||||
),
|
||||
);
|
||||
console.log(`Admin ${admin.publicKey.toBase58()}`);
|
||||
|
||||
const group = await client.getGroupForCreator(admin.publicKey, 0);
|
||||
|
||||
// collect mappings &
|
||||
// collect pubkeys
|
||||
const banks = await client.getBanksForGroup(group);
|
||||
const banksMapByMint = new Map(
|
||||
banks.map((tuple) => [tuple.mint.toBase58(), tuple]),
|
||||
);
|
||||
const stubOracles = await client.getStubOracle(group);
|
||||
const mintInfos = await client.getMintInfosForGroup(group);
|
||||
const serum3Markets = await client.serum3GetMarkets(group);
|
||||
const perpMarkets = await client.perpGetMarkets(group);
|
||||
|
||||
// build ids
|
||||
const toDump = new Id(
|
||||
cluster,
|
||||
groupName,
|
||||
group.publicKey.toBase58(),
|
||||
SERUM3_PROGRAM_ID[cluster].toBase58(),
|
||||
MANGO_V4_ID[cluster].toBase58(),
|
||||
banks.map((tuple) => ({
|
||||
name: tuple.name,
|
||||
publicKey: tuple.publicKey.toBase58(),
|
||||
})),
|
||||
stubOracles.map((tuple) => ({
|
||||
name: banksMapByMint.get(tuple.mint.toBase58())!.name,
|
||||
publicKey: tuple.publicKey.toBase58(),
|
||||
})),
|
||||
mintInfos.map((tuple) => ({
|
||||
name: banksMapByMint.get(tuple.mint.toBase58())!.name,
|
||||
publicKey: tuple.publicKey.toBase58(),
|
||||
})),
|
||||
serum3Markets.map((tuple) => ({
|
||||
name: tuple.name,
|
||||
publicKey: tuple.publicKey.toBase58(),
|
||||
marketExternal: tuple.serumMarketExternal.toBase58(),
|
||||
})),
|
||||
perpMarkets.map((tuple) => ({
|
||||
name: tuple.name,
|
||||
publicKey: tuple.publicKey.toBase58(),
|
||||
})),
|
||||
);
|
||||
|
||||
console.log(toDump);
|
||||
|
||||
// adds ids for group in existing ids.json
|
||||
const existingGroup = idsJson.groups.find((group) => group.name == groupName);
|
||||
if (existingGroup) {
|
||||
console.log('Updating existing group with latest state...');
|
||||
} else {
|
||||
console.log('Group does not exist yet...');
|
||||
}
|
||||
idsJson.groups = idsJson.groups.filter((group) => group.name !== groupName);
|
||||
idsJson.groups.push(toDump);
|
||||
|
||||
// dump
|
||||
const file = `${process.cwd()}/ts/client/ids.json`;
|
||||
await fs.writeFileSync(file, JSON.stringify(idsJson, replacer, 2));
|
||||
|
||||
process.exit();
|
||||
}
|
||||
main();
|
|
@ -1,280 +0,0 @@
|
|||
import { Jupiter } from '@jup-ag/core';
|
||||
import { AnchorProvider, Wallet } from '@project-serum/anchor';
|
||||
import {
|
||||
AccountMeta,
|
||||
Connection,
|
||||
Keypair,
|
||||
SYSVAR_INSTRUCTIONS_PUBKEY,
|
||||
TransactionInstruction,
|
||||
} from '@solana/web3.js';
|
||||
import BN from 'bn.js';
|
||||
import fs from 'fs';
|
||||
import { QUOTE_DECIMALS } from '../../accounts/bank';
|
||||
import { MangoClient } from '../../index';
|
||||
import { getAssociatedTokenAddress } from '../../utils';
|
||||
|
||||
const MB_CLUSTER_URL =
|
||||
process.env.MB_CLUSTER_URL ||
|
||||
'https://mango.rpcpool.com/946ef7337da3f5b8d3e4a34e7f88';
|
||||
const MB_PAYER_KEYPAIR =
|
||||
process.env.MB_PAYER_KEYPAIR ||
|
||||
'/Users/tylershipe/.config/solana/deploy.json';
|
||||
|
||||
//
|
||||
// example script which shows usage of flash loan ix using a jupiter swap
|
||||
//
|
||||
// NOTE: we assume that ATA for source and target already exist for wallet
|
||||
async function main() {
|
||||
const options = AnchorProvider.defaultOptions();
|
||||
const connection = new Connection(MB_CLUSTER_URL, options);
|
||||
|
||||
// load user key
|
||||
const user = Keypair.fromSecretKey(
|
||||
Buffer.from(JSON.parse(fs.readFileSync(MB_PAYER_KEYPAIR!, 'utf-8'))),
|
||||
);
|
||||
const userWallet = new Wallet(user);
|
||||
const userProvider = new AnchorProvider(connection, userWallet, options);
|
||||
const client = await MangoClient.connectForGroupName(
|
||||
userProvider,
|
||||
'mainnet-beta.microwavedcola',
|
||||
);
|
||||
console.log(`User ${userWallet.publicKey.toBase58()}`);
|
||||
|
||||
// load admin key
|
||||
const admin = Keypair.fromSecretKey(
|
||||
Buffer.from(JSON.parse(fs.readFileSync(MB_PAYER_KEYPAIR!, 'utf-8'))),
|
||||
);
|
||||
console.log(`Admin ${admin.publicKey.toBase58()}`);
|
||||
|
||||
// fetch group
|
||||
const group = await client.getGroupForCreator(admin.publicKey, 0);
|
||||
console.log(`Found group ${group.publicKey.toBase58()}`);
|
||||
console.log(`start btc bank ${group.banksMap.get('BTC').toString()}`);
|
||||
|
||||
// create + fetch account
|
||||
console.log(`Creating mangoaccount...`);
|
||||
const mangoAccount = await client.getOrCreateMangoAccount(group);
|
||||
console.log(`...created/found mangoAccount ${mangoAccount.publicKey}`);
|
||||
console.log(`start balance \n${mangoAccount.toString(group)}`);
|
||||
|
||||
//
|
||||
// flash loan 3
|
||||
//
|
||||
if (true) {
|
||||
// source of swap
|
||||
const sourceBank = group.banksMap.get('USDC');
|
||||
// target of swap
|
||||
const targetBank = group.banksMap.get('BTC');
|
||||
// 0.2$, at 1BTC=20,000$, 0.2$=0.00001BTC
|
||||
const sourceAmount = 2 * Math.pow(10, QUOTE_DECIMALS - 1);
|
||||
|
||||
console.log(`Flash loaning ${sourceBank.name} to ${targetBank.name}`);
|
||||
|
||||
// jupiter route
|
||||
const jupiter = await Jupiter.load({
|
||||
connection: client.program.provider.connection,
|
||||
cluster: 'mainnet-beta',
|
||||
user: mangoAccount.owner, // or public key
|
||||
// platformFeeAndAccounts: NO_PLATFORM_FEE,
|
||||
routeCacheDuration: 10_000, // Will not refetch data on computeRoutes for up to 10 seconds
|
||||
});
|
||||
const routes = await jupiter.computeRoutes({
|
||||
inputMint: sourceBank.mint, // Mint address of the input token
|
||||
outputMint: targetBank.mint, // Mint address of the output token
|
||||
inputAmount: sourceAmount, // raw input amount of tokens
|
||||
slippage: 5, // The slippage in % terms
|
||||
forceFetch: false, // false is the default value => will use cache if not older than routeCacheDuration
|
||||
});
|
||||
const routesInfosWithoutRaydium = routes.routesInfos.filter((r) => {
|
||||
if (r.marketInfos.length > 1) {
|
||||
for (const mkt of r.marketInfos) {
|
||||
if (mkt.amm.label === 'Raydium' || mkt.amm.label === 'Serum')
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
// loop until we manage first successful swap
|
||||
let res;
|
||||
let i = 0;
|
||||
while (true) {
|
||||
const instructions: TransactionInstruction[] = [];
|
||||
|
||||
// select a route and fetch+build its tx
|
||||
const selectedRoute = routesInfosWithoutRaydium[i];
|
||||
const { transactions } = await jupiter.exchange({
|
||||
routeInfo: selectedRoute,
|
||||
});
|
||||
|
||||
const { setupTransaction, swapTransaction } = transactions;
|
||||
for (const ix of swapTransaction.instructions) {
|
||||
if (
|
||||
ix.programId.toBase58() ===
|
||||
'JUP2jxvXaqu7NQY1GmNF4m1vodw12LVXYxbFL2uJvfo'
|
||||
) {
|
||||
instructions.push(ix);
|
||||
}
|
||||
}
|
||||
|
||||
// run jup setup in a separate tx, ideally this should be packed before flashLoanBegin in same tx,
|
||||
// but it increases chance of flash loan tx to exceed tx size limit
|
||||
if (setupTransaction) {
|
||||
await this.program.provider.sendAndConfirm(setupTransaction);
|
||||
}
|
||||
|
||||
// flash loan start ix - takes a loan for source token,
|
||||
// flash loan end ix - returns increase in all token account's amounts to respective vaults,
|
||||
const healthRemainingAccounts =
|
||||
client.buildFixedAccountRetrieverHealthAccounts(
|
||||
group,
|
||||
mangoAccount,
|
||||
[sourceBank, targetBank], // we would be taking a sol loan potentially
|
||||
);
|
||||
// 1. build flash loan end ix
|
||||
const flashLoadnEndIx = await client.program.methods
|
||||
.flashLoanEnd(true)
|
||||
.accounts({
|
||||
account: mangoAccount.publicKey,
|
||||
owner: (client.program.provider as AnchorProvider).wallet.publicKey,
|
||||
})
|
||||
.remainingAccounts([
|
||||
...healthRemainingAccounts.map(
|
||||
(pk) =>
|
||||
({
|
||||
pubkey: pk,
|
||||
isWritable: false,
|
||||
isSigner: false,
|
||||
} as AccountMeta),
|
||||
),
|
||||
{
|
||||
pubkey: sourceBank.vault,
|
||||
isWritable: true,
|
||||
isSigner: false,
|
||||
} as AccountMeta,
|
||||
{
|
||||
pubkey: targetBank.vault,
|
||||
isWritable: true,
|
||||
isSigner: false,
|
||||
} as AccountMeta,
|
||||
{
|
||||
pubkey: await getAssociatedTokenAddress(
|
||||
sourceBank.mint,
|
||||
mangoAccount.owner,
|
||||
),
|
||||
isWritable: true, // increase in this address amount is transferred back to the sourceBank.vault above in this case whatever is residual of source bank loan
|
||||
isSigner: false,
|
||||
} as AccountMeta,
|
||||
{
|
||||
pubkey: await getAssociatedTokenAddress(
|
||||
targetBank.mint,
|
||||
mangoAccount.owner,
|
||||
),
|
||||
isWritable: true, // increase in this address amount is transferred back to the targetBank.vault above in this case whatever is result of swap
|
||||
isSigner: false,
|
||||
} as AccountMeta,
|
||||
{
|
||||
pubkey: group.publicKey,
|
||||
isWritable: false,
|
||||
isSigner: false,
|
||||
} as AccountMeta,
|
||||
])
|
||||
.instruction();
|
||||
instructions.push(flashLoadnEndIx);
|
||||
// 2. build flash loan start ix, add end ix as a post ix
|
||||
try {
|
||||
res = await client.program.methods
|
||||
.flashLoanBegin([
|
||||
new BN(sourceAmount),
|
||||
new BN(
|
||||
0,
|
||||
) /* we don't care about borrowing the target amount, this is just a dummy */,
|
||||
])
|
||||
.accounts({
|
||||
// for observing ixs in the entire tx,
|
||||
// e.g. apart from flash loan start and end no other ix should target mango v4 program
|
||||
// e.g. forbid FlashLoanBegin been called from CPI
|
||||
instructions: SYSVAR_INSTRUCTIONS_PUBKEY,
|
||||
})
|
||||
.remainingAccounts([
|
||||
{
|
||||
pubkey: sourceBank.publicKey,
|
||||
isWritable: true, // metadata for flash loan is updated
|
||||
isSigner: false,
|
||||
} as AccountMeta,
|
||||
{
|
||||
pubkey: targetBank.publicKey,
|
||||
isWritable: true, // this is a dummy, its just done so that we match flash loan start and end ix
|
||||
isSigner: false,
|
||||
} as AccountMeta,
|
||||
{
|
||||
pubkey: sourceBank.vault,
|
||||
isWritable: true,
|
||||
isSigner: false,
|
||||
} as AccountMeta,
|
||||
{
|
||||
pubkey: targetBank.vault,
|
||||
isWritable: true, // this is a dummy, its just done so that we match flash loan start and end ix
|
||||
isSigner: false,
|
||||
} as AccountMeta,
|
||||
{
|
||||
pubkey: await getAssociatedTokenAddress(
|
||||
sourceBank.mint,
|
||||
mangoAccount.owner,
|
||||
),
|
||||
isWritable: true, // token transfer i.e. loan to a desired token account e.g. user's ATA when using a route made for a specific user
|
||||
isSigner: false,
|
||||
} as AccountMeta,
|
||||
{
|
||||
pubkey: await getAssociatedTokenAddress(
|
||||
targetBank.mint,
|
||||
mangoAccount.owner,
|
||||
),
|
||||
isWritable: false, // this is a dummy, its just done so that we match flash loan start and end ix
|
||||
isSigner: false,
|
||||
} as AccountMeta,
|
||||
{
|
||||
pubkey: group.publicKey,
|
||||
isWritable: false,
|
||||
isSigner: false,
|
||||
} as AccountMeta,
|
||||
])
|
||||
.postInstructions(instructions)
|
||||
.rpc();
|
||||
|
||||
// break when success
|
||||
break;
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
if (
|
||||
(error.toString() as string).includes('Transaction too large:') ||
|
||||
(error.toString() as string).includes(
|
||||
'encoding overruns Uint8Array',
|
||||
) ||
|
||||
(error.toString() as string).includes(
|
||||
'The value of "offset" is out of range. It must be >= 0 and <= 1231. Received 1232',
|
||||
) ||
|
||||
(error.toString() as string).includes(
|
||||
'The value of "value" is out of range. It must be >= 0 and <= 255. Received',
|
||||
) ||
|
||||
i > 10
|
||||
) {
|
||||
console.log(`route ${i} was bad, trying next one...`);
|
||||
i++;
|
||||
} else {
|
||||
throw error; // let others bubble up
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`success tx - https://explorer.solana.com/tx/${res}`);
|
||||
|
||||
group.reloadBanks(client);
|
||||
console.log(`end btc bank ${group.banksMap.get('BTC').toString()}`);
|
||||
|
||||
await mangoAccount.reload(client, group);
|
||||
console.log(`end balance \n${mangoAccount.toString(group)}`);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
|
@ -1,42 +0,0 @@
|
|||
import { AnchorProvider } from '@project-serum/anchor';
|
||||
import { Connection, PublicKey } from '@solana/web3.js';
|
||||
import { parseSwitchboardOracle } from '../../accounts/oracle';
|
||||
|
||||
async function main() {
|
||||
const options = AnchorProvider.defaultOptions();
|
||||
|
||||
async function foo(obj) {
|
||||
let connection = new Connection(obj.net, options);
|
||||
let ai = await connection.getAccountInfo(new PublicKey(obj.pk));
|
||||
console.log(`${obj.name} price ${await parseSwitchboardOracle(ai!)}`);
|
||||
}
|
||||
|
||||
for (const oracle of [
|
||||
{
|
||||
name: 'devnet mngo v1',
|
||||
pk: '8k7F9Xb36oFJsjpCKpsXvg4cgBRoZtwNTc3EzG5Ttd2o',
|
||||
net: 'https://mango.devnet.rpcpool.com',
|
||||
},
|
||||
{
|
||||
name: 'devnet sol v2',
|
||||
pk: 'GvDMxPzN1sCj7L26YDK2HnMRXEQmQ2aemov8YBtPS7vR',
|
||||
net: 'https://mango.devnet.rpcpool.com',
|
||||
},
|
||||
{
|
||||
name: 'mainnet btc v2',
|
||||
pk: '3HtmwdXJPAdMZ73fTGeCFgbDQZGLZWpmsm3JAB5quGJN',
|
||||
net: 'http://api.mainnet-beta.solana.com/',
|
||||
},
|
||||
{
|
||||
name: 'mainnet sol v2',
|
||||
pk: 'GvDMxPzN1sCj7L26YDK2HnMRXEQmQ2aemov8YBtPS7vR',
|
||||
net: 'http://api.mainnet-beta.solana.com/',
|
||||
},
|
||||
]) {
|
||||
await foo(oracle);
|
||||
}
|
||||
|
||||
process.exit();
|
||||
}
|
||||
|
||||
main();
|
|
@ -1,51 +0,0 @@
|
|||
import { AnchorProvider, Wallet } from '@project-serum/anchor';
|
||||
import { Market } from '@project-serum/serum';
|
||||
import { Connection, Keypair, PublicKey } from '@solana/web3.js';
|
||||
import fs from 'fs';
|
||||
import * as os from 'os';
|
||||
|
||||
import { MangoClient } from '../../client';
|
||||
import { MANGO_V4_ID } from '../../constants';
|
||||
|
||||
const main = async () => {
|
||||
const options = AnchorProvider.defaultOptions();
|
||||
const connection = new Connection(
|
||||
'https://mango.devnet.rpcpool.com',
|
||||
options,
|
||||
);
|
||||
|
||||
const admin = Keypair.fromSecretKey(
|
||||
Buffer.from(
|
||||
JSON.parse(
|
||||
fs.readFileSync(os.homedir() + '/.config/solana/admin.json', 'utf-8'),
|
||||
),
|
||||
),
|
||||
);
|
||||
const adminWallet = new Wallet(admin);
|
||||
console.log(`Admin ${adminWallet.publicKey.toBase58()}`);
|
||||
const adminProvider = new AnchorProvider(connection, adminWallet, options);
|
||||
const client = await MangoClient.connect(
|
||||
adminProvider,
|
||||
'devnet',
|
||||
MANGO_V4_ID['devnet'],
|
||||
);
|
||||
|
||||
const btcMint = new PublicKey('3UNBZ6o52WTWwjac2kPUb4FyodhU1vFkRJheu1Sh2TvU');
|
||||
const usdcMint = new PublicKey(
|
||||
'EmXq3Ni9gfudTiyNKzzYvpnQqnJEMRw2ttnVXoJXjLo1',
|
||||
);
|
||||
const serumProgramId = new PublicKey(
|
||||
'DESVgJVGajEgKGXhb6XmqDHGz3VjdgP7rEVESBgxmroY',
|
||||
);
|
||||
|
||||
const market = await Market.findAccountsByMints(
|
||||
connection,
|
||||
btcMint,
|
||||
usdcMint,
|
||||
serumProgramId,
|
||||
);
|
||||
|
||||
console.log('market', market);
|
||||
};
|
||||
|
||||
main();
|
|
@ -57,16 +57,19 @@ async function main() {
|
|||
group.consoleLogBanks();
|
||||
|
||||
// deregister all serum markets
|
||||
for (const market of group.serum3MarketsMap.values()) {
|
||||
sig = await client.serum3deregisterMarket(group, market.name);
|
||||
for (const market of group.serum3MarketsMapByExternal.values()) {
|
||||
sig = await client.serum3deregisterMarket(
|
||||
group,
|
||||
market.serumMarketExternal,
|
||||
);
|
||||
console.log(
|
||||
`Deregistered serum market ${market.name}, sig https://explorer.solana.com/tx/${sig}?cluster=devnet`,
|
||||
);
|
||||
}
|
||||
|
||||
// close all perp markets
|
||||
for (const market of group.perpMarketsMap.values()) {
|
||||
sig = await client.perpCloseMarket(group, market.name);
|
||||
for (const market of group.perpMarketsMapByMarketIndex.values()) {
|
||||
sig = await client.perpCloseMarket(group, market.perpMarketIndex);
|
||||
console.log(
|
||||
`Closed perp market ${market.name}, sig https://explorer.solana.com/tx/${sig}?cluster=devnet`,
|
||||
);
|
||||
|
|
|
@ -1,136 +0,0 @@
|
|||
import { AnchorProvider, Wallet } from '@project-serum/anchor';
|
||||
import { Connection, Keypair } from '@solana/web3.js';
|
||||
import fs from 'fs';
|
||||
import { Serum3Side } from '../accounts/serum3';
|
||||
import { MangoClient } from '../client';
|
||||
import { MANGO_V4_ID } from '../constants';
|
||||
|
||||
//
|
||||
// script which shows how to close a mango account cleanly i.e. close all active positions, withdraw all tokens, etc.
|
||||
//
|
||||
|
||||
const GROUP_NUM = Number(process.env.GROUP_NUM || 0);
|
||||
|
||||
// note: either use finalized or expect closing certain things to fail and having to runs scrript multiple times
|
||||
async function main() {
|
||||
const options = AnchorProvider.defaultOptions();
|
||||
|
||||
// note: see note above
|
||||
// options.commitment = 'finalized';
|
||||
|
||||
const connection = new Connection(
|
||||
'https://mango.devnet.rpcpool.com',
|
||||
options,
|
||||
);
|
||||
|
||||
// user
|
||||
const user = Keypair.fromSecretKey(
|
||||
Buffer.from(
|
||||
JSON.parse(fs.readFileSync(process.env.USER2_KEYPAIR!, 'utf-8')),
|
||||
),
|
||||
);
|
||||
const userWallet = new Wallet(user);
|
||||
const userProvider = new AnchorProvider(connection, userWallet, options);
|
||||
const client = await MangoClient.connect(
|
||||
userProvider,
|
||||
'devnet',
|
||||
MANGO_V4_ID['devnet'],
|
||||
{},
|
||||
'get-program-accounts',
|
||||
);
|
||||
console.log(`User ${userWallet.publicKey.toBase58()}`);
|
||||
|
||||
try {
|
||||
// fetch group
|
||||
const admin = Keypair.fromSecretKey(
|
||||
Buffer.from(
|
||||
JSON.parse(fs.readFileSync(process.env.ADMIN_KEYPAIR!, 'utf-8')),
|
||||
),
|
||||
);
|
||||
const group = await client.getGroupForCreator(admin.publicKey, GROUP_NUM);
|
||||
console.log(`Found group ${group.publicKey.toBase58()}`);
|
||||
|
||||
// fetch account
|
||||
const mangoAccount = (
|
||||
await client.getMangoAccountsForOwner(group, user.publicKey)
|
||||
)[0];
|
||||
console.log(`...found mangoAccount ${mangoAccount.publicKey}`);
|
||||
console.log(mangoAccount.toString());
|
||||
|
||||
// close mango account serum3 positions, closing might require cancelling orders and settling
|
||||
for (const serum3Account of mangoAccount.serum3Active()) {
|
||||
let orders = await client.getSerum3Orders(
|
||||
group,
|
||||
group.getSerum3MarketByIndex(serum3Account.marketIndex)!.name,
|
||||
);
|
||||
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,
|
||||
|
||||
'BTC/USDC',
|
||||
order.side === 'buy' ? Serum3Side.bid : Serum3Side.ask,
|
||||
order.orderId,
|
||||
);
|
||||
}
|
||||
await client.serum3SettleFunds(
|
||||
group,
|
||||
mangoAccount,
|
||||
group.getSerum3MarketByIndex(serum3Account.marketIndex)!.name,
|
||||
);
|
||||
await client.serum3CloseOpenOrders(
|
||||
group,
|
||||
mangoAccount,
|
||||
group.getSerum3MarketByIndex(serum3Account.marketIndex)!.name,
|
||||
);
|
||||
}
|
||||
|
||||
// we closed a serum account, this changes the health accounts we are passing in for future ixs
|
||||
await mangoAccount.reload(client, group);
|
||||
|
||||
// withdraw all tokens
|
||||
for (const token of mangoAccount.tokensActive()) {
|
||||
let native = token.balance(
|
||||
group.getFirstBankByTokenIndex(token.tokenIndex),
|
||||
);
|
||||
|
||||
// to avoid rounding issues
|
||||
if (native.toNumber() < 1) {
|
||||
continue;
|
||||
}
|
||||
let nativeFlooredNumber = Math.floor(native.toNumber());
|
||||
console.log(
|
||||
`withdrawing token ${
|
||||
group.getFirstBankByTokenIndex(token.tokenIndex).name
|
||||
} native amount ${nativeFlooredNumber} `,
|
||||
);
|
||||
|
||||
await client.tokenWithdrawNative(
|
||||
group,
|
||||
mangoAccount,
|
||||
group.getFirstBankByTokenIndex(token.tokenIndex).mint,
|
||||
nativeFlooredNumber - 1 /* see comment in token_withdraw in program */,
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
||||
// reload and print current positions
|
||||
await mangoAccount.reload(client, group);
|
||||
console.log(`...mangoAccount ${mangoAccount.publicKey}`);
|
||||
console.log(mangoAccount.toString());
|
||||
|
||||
// close account
|
||||
console.log(`Close mango account...`);
|
||||
const res = await client.closeMangoAccount(group, mangoAccount);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
process.exit();
|
||||
}
|
||||
|
||||
main();
|
|
@ -86,7 +86,7 @@ async function main() {
|
|||
new PublicKey(DEVNET_MINTS.get('USDC')!),
|
||||
1000,
|
||||
);
|
||||
await mangoAccount.reload(client, group);
|
||||
await mangoAccount.reload(client);
|
||||
|
||||
await client.tokenDeposit(
|
||||
group,
|
||||
|
@ -94,7 +94,7 @@ async function main() {
|
|||
new PublicKey(DEVNET_MINTS.get('MNGO')!),
|
||||
100,
|
||||
);
|
||||
await mangoAccount.reload(client, group);
|
||||
await mangoAccount.reload(client);
|
||||
|
||||
await client.tokenDeposit(
|
||||
group,
|
||||
|
@ -102,7 +102,7 @@ async function main() {
|
|||
new PublicKey(DEVNET_MINTS.get('ETH')!),
|
||||
500,
|
||||
);
|
||||
await mangoAccount.reload(client, group);
|
||||
await mangoAccount.reload(client);
|
||||
|
||||
await client.tokenDeposit(
|
||||
group,
|
||||
|
@ -110,7 +110,7 @@ async function main() {
|
|||
new PublicKey(DEVNET_MINTS.get('SRM')!),
|
||||
500,
|
||||
);
|
||||
await mangoAccount.reload(client, group);
|
||||
await mangoAccount.reload(client);
|
||||
|
||||
await client.tokenDeposit(
|
||||
group,
|
||||
|
@ -118,7 +118,7 @@ async function main() {
|
|||
new PublicKey(DEVNET_MINTS.get('BTC')!),
|
||||
1,
|
||||
);
|
||||
await mangoAccount.reload(client, group);
|
||||
await mangoAccount.reload(client);
|
||||
|
||||
console.log(mangoAccount.toString(group));
|
||||
} catch (error) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { AnchorProvider, Wallet } from '@project-serum/anchor';
|
||||
import { AnchorProvider, BN, Wallet } from '@project-serum/anchor';
|
||||
import { Connection, Keypair } from '@solana/web3.js';
|
||||
import fs from 'fs';
|
||||
import { Serum3Side } from '../accounts/serum3';
|
||||
|
@ -59,9 +59,11 @@ async function main() {
|
|||
|
||||
// close mango account serum3 positions, closing might require cancelling orders and settling
|
||||
for (const serum3Account of mangoAccount.serum3Active()) {
|
||||
let orders = await client.getSerum3Orders(
|
||||
let orders = await mangoAccount.loadSerum3OpenOrdersForMarket(
|
||||
client,
|
||||
group,
|
||||
group.getSerum3MarketByIndex(serum3Account.marketIndex)!.name,
|
||||
group.serum3MarketsMapByMarketIndex.get(serum3Account.marketIndex)
|
||||
?.serumMarketExternal!,
|
||||
);
|
||||
for (const order of orders) {
|
||||
console.log(
|
||||
|
@ -71,8 +73,8 @@ async function main() {
|
|||
await client.serum3CancelOrder(
|
||||
group,
|
||||
mangoAccount,
|
||||
|
||||
'BTC/USDC',
|
||||
group.serum3MarketsMapByMarketIndex.get(serum3Account.marketIndex)
|
||||
?.serumMarketExternal!,
|
||||
order.side === 'buy' ? Serum3Side.bid : Serum3Side.ask,
|
||||
order.orderId,
|
||||
);
|
||||
|
@ -80,17 +82,19 @@ async function main() {
|
|||
await client.serum3SettleFunds(
|
||||
group,
|
||||
mangoAccount,
|
||||
group.getSerum3MarketByIndex(serum3Account.marketIndex)!.name,
|
||||
group.serum3MarketsMapByMarketIndex.get(serum3Account.marketIndex)
|
||||
?.serumMarketExternal!,
|
||||
);
|
||||
await client.serum3CloseOpenOrders(
|
||||
group,
|
||||
mangoAccount,
|
||||
group.getSerum3MarketByIndex(serum3Account.marketIndex)!.name,
|
||||
group.serum3MarketsMapByMarketIndex.get(serum3Account.marketIndex)
|
||||
?.serumMarketExternal!,
|
||||
);
|
||||
}
|
||||
|
||||
// we closed a serum account, this changes the health accounts we are passing in for future ixs
|
||||
await mangoAccount.reload(client, group);
|
||||
await mangoAccount.reload(client);
|
||||
|
||||
// withdraw all tokens
|
||||
for (const token of mangoAccount.tokensActive()) {
|
||||
|
@ -113,13 +117,15 @@ async function main() {
|
|||
group,
|
||||
mangoAccount,
|
||||
group.getFirstBankByTokenIndex(token.tokenIndex).mint,
|
||||
nativeFlooredNumber - 1 /* see comment in token_withdraw in program */,
|
||||
new BN(
|
||||
nativeFlooredNumber - 1,
|
||||
) /* see comment in token_withdraw in program */,
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
||||
// reload and print current positions
|
||||
await mangoAccount.reload(client, group);
|
||||
await mangoAccount.reload(client);
|
||||
console.log(`...mangoAccount ${mangoAccount.publicKey}`);
|
||||
console.log(mangoAccount.toString());
|
||||
|
||||
|
|
|
@ -1,97 +0,0 @@
|
|||
import { AnchorProvider, Wallet } from '@project-serum/anchor';
|
||||
import { Connection, Keypair, PublicKey } from '@solana/web3.js';
|
||||
import fs from 'fs';
|
||||
import { Serum3Side } from '../accounts/serum3';
|
||||
import { MangoClient } from '../client';
|
||||
import { MANGO_V4_ID } from '../constants';
|
||||
|
||||
const MAINNET_ORACLES = new Map([
|
||||
['USDT', '3vxLXJqLqF3JG5TCbYycbKWRBbCJQLxQmBGCkyqEEefL'],
|
||||
['BTC', 'GVXRSBjFk6e6J3NbVPXohDJetcTjaeeuykUpbQF8UoMU'],
|
||||
['ETH', 'JBu1AL4obBcCMqKBBxhpWCNUt136ijcuMZLFvTP7iWdB'],
|
||||
['soETH', 'JBu1AL4obBcCMqKBBxhpWCNUt136ijcuMZLFvTP7iWdB'],
|
||||
['SOL', 'H6ARHf6YXhGYeQfUzQNGk6rDNnLBQKrenN712K4AQJEG'],
|
||||
['MSOL', 'E4v1BBgoso9s64TQvmyownAVJbhbEPGyzA3qn4n46qj9'],
|
||||
['MNGO', '79wm3jjcPr6RaNQ4DGvP5KxG1mNd3gEBsg6FsNVFezK4'],
|
||||
]);
|
||||
|
||||
const PAYER_KEYPAIR = process.env.MB_PAYER_KEYPAIR || '';
|
||||
|
||||
//
|
||||
// (untested?) script which closes a mango account cleanly, first closes all positions, withdraws all tokens and then closes it
|
||||
//
|
||||
async function viewUnownedAccount(userKeypairFile: string) {
|
||||
const options = AnchorProvider.defaultOptions();
|
||||
const connection = new Connection(
|
||||
'https://mango.rpcpool.com/0f9acc0d45173b51bf7d7e09c1e5',
|
||||
options,
|
||||
);
|
||||
|
||||
// user
|
||||
// const userWallet = new Wallet(Keypair.generate());
|
||||
// const userProvider = new AnchorProvider(connection, userWallet, options);
|
||||
// console.log(`User ${userWallet.publicKey.toBase58()}`);
|
||||
|
||||
// admin
|
||||
const admin = Keypair.fromSecretKey(
|
||||
Buffer.from(JSON.parse(fs.readFileSync(PAYER_KEYPAIR, 'utf-8'))),
|
||||
);
|
||||
const adminWallet = new Wallet(admin);
|
||||
const adminProvider = new AnchorProvider(connection, adminWallet, options);
|
||||
console.log(`Admin ${admin.publicKey.toBase58()}`);
|
||||
|
||||
const client = await MangoClient.connect(
|
||||
adminProvider,
|
||||
'mainnet-beta',
|
||||
MANGO_V4_ID['mainnet-beta'],
|
||||
{},
|
||||
'get-program-accounts',
|
||||
);
|
||||
|
||||
// fetch group
|
||||
const group = await client.getGroupForCreator(admin.publicKey, 2);
|
||||
console.log(`Found group ${group.publicKey.toBase58()}`);
|
||||
|
||||
const btcMainnetOracle = new PublicKey(MAINNET_ORACLES.get('BTC')!);
|
||||
console.log(`Registering perp market...`);
|
||||
try {
|
||||
await client.perpCreateMarket(
|
||||
group, // group
|
||||
btcMainnetOracle, // oracle
|
||||
0, // perpMarketIndex
|
||||
'BTC-PERP', // name
|
||||
0.1, // oracleConfFilter
|
||||
6, // baseDecimals
|
||||
1, // quoteLotSize
|
||||
10, // baseLotSize
|
||||
0.975, // maintAssetWeight
|
||||
0.95, // initAssetWeight
|
||||
1.025, // maintLiabWeight
|
||||
1.05, // initLiabWeight
|
||||
0.012, // liquidationFee
|
||||
0.0002, // makerFee
|
||||
0.0, // takerFee
|
||||
0, // feePenalty
|
||||
0.05, // minFunding
|
||||
0.05, // maxFunding
|
||||
100, // impactQuantity
|
||||
false, // groupInsuranceFund
|
||||
true, // trustedMarket
|
||||
0, // settleFeeFlat
|
||||
0, // settleFeeAmountThreshold
|
||||
0, // settleFeeFractionLowHealth
|
||||
0, // settleTokenIndex
|
||||
);
|
||||
console.log('done');
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
process.exit();
|
||||
}
|
||||
|
||||
async function main() {
|
||||
await viewUnownedAccount(process.env.MB_USER2_KEYPAIR || '');
|
||||
}
|
||||
|
||||
main();
|
|
@ -1,5 +1,5 @@
|
|||
import { AnchorProvider, Wallet } from '@project-serum/anchor';
|
||||
import { Connection, Keypair, PublicKey } from '@solana/web3.js';
|
||||
import { Connection, Keypair } from '@solana/web3.js';
|
||||
import fs from 'fs';
|
||||
import { MangoClient } from '../client';
|
||||
import { MANGO_V4_ID } from '../constants';
|
||||
|
@ -65,8 +65,8 @@ async function main() {
|
|||
}
|
||||
|
||||
// close all perp markets
|
||||
for (const market of group.perpMarketsMap.values()) {
|
||||
sig = await client.perpCloseMarket(group, market.name);
|
||||
for (const market of group.perpMarketsMapByMarketIndex.values()) {
|
||||
sig = await client.perpCloseMarket(group, market.perpMarketIndex);
|
||||
console.log(
|
||||
`Closed perp market ${market.name}, sig https://explorer.solana.com/tx/${sig}`,
|
||||
);
|
||||
|
|
|
@ -350,7 +350,7 @@ async function createUser(userKeypair: string) {
|
|||
new PublicKey(MAINNET_MINTS.get('USDC')!),
|
||||
10,
|
||||
);
|
||||
await mangoAccount.reload(client, group);
|
||||
await mangoAccount.reload(client);
|
||||
console.log(`...deposited 10 USDC`);
|
||||
|
||||
await client.tokenDeposit(
|
||||
|
@ -359,7 +359,7 @@ async function createUser(userKeypair: string) {
|
|||
new PublicKey(MAINNET_MINTS.get('SOL')!),
|
||||
1,
|
||||
);
|
||||
await mangoAccount.reload(client, group);
|
||||
await mangoAccount.reload(client);
|
||||
console.log(`...deposited 1 SOL`);
|
||||
}
|
||||
|
||||
|
@ -422,7 +422,7 @@ async function placeSerum3TradeAndCancelIt(userKeypair: string) {
|
|||
console.log(order);
|
||||
}
|
||||
console.log(`...cancelling serum3 orders`);
|
||||
await client.serum3CancelAllorders(
|
||||
await client.serum3CancelAllOrders(
|
||||
group,
|
||||
mangoAccount,
|
||||
new PublicKey(MAINNET_SERUM3_MARKETS.get('SOL/USDC')!),
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { AnchorProvider, Wallet } from '@project-serum/anchor';
|
||||
import { AnchorProvider, BN, Wallet } from '@project-serum/anchor';
|
||||
import { Connection, Keypair } from '@solana/web3.js';
|
||||
import fs from 'fs';
|
||||
import { Serum3Side } from '../accounts/serum3';
|
||||
|
@ -47,9 +47,11 @@ async function closeUserAccount(userKeypairFile: string) {
|
|||
try {
|
||||
// cancel serum3 accounts, closing might require cancelling orders and settling
|
||||
for (const serum3Account of mangoAccount.serum3Active()) {
|
||||
let orders = await client.getSerum3Orders(
|
||||
let orders = await mangoAccount.loadSerum3OpenOrdersForMarket(
|
||||
client,
|
||||
group,
|
||||
group.getSerum3MarketByIndex(serum3Account.marketIndex)!.name,
|
||||
group.serum3MarketsMapByMarketIndex.get(serum3Account.marketIndex)
|
||||
?.serumMarketExternal!,
|
||||
);
|
||||
for (const order of orders) {
|
||||
console.log(
|
||||
|
@ -59,8 +61,8 @@ async function closeUserAccount(userKeypairFile: string) {
|
|||
await client.serum3CancelOrder(
|
||||
group,
|
||||
mangoAccount,
|
||||
|
||||
'BTC/USDC',
|
||||
group.serum3MarketsMapByMarketIndex.get(serum3Account.marketIndex)
|
||||
?.serumMarketExternal!,
|
||||
order.side === 'buy' ? Serum3Side.bid : Serum3Side.ask,
|
||||
order.orderId,
|
||||
);
|
||||
|
@ -69,23 +71,29 @@ async function closeUserAccount(userKeypairFile: string) {
|
|||
await client.serum3SettleFunds(
|
||||
group,
|
||||
mangoAccount,
|
||||
group.getSerum3MarketByIndex(serum3Account.marketIndex)!.name,
|
||||
group.serum3MarketsMapByMarketIndex.get(serum3Account.marketIndex)
|
||||
?.serumMarketExternal!,
|
||||
);
|
||||
await client.serum3CloseOpenOrders(
|
||||
group,
|
||||
mangoAccount,
|
||||
group.getSerum3MarketByIndex(serum3Account.marketIndex)!.name,
|
||||
group.serum3MarketsMapByMarketIndex.get(serum3Account.marketIndex)
|
||||
?.serumMarketExternal!,
|
||||
);
|
||||
}
|
||||
|
||||
// we closed a serum account, this changes the health accounts we are passing in for future ixs
|
||||
await mangoAccount.reload(client, group);
|
||||
await mangoAccount.reload(client);
|
||||
|
||||
// withdraw all tokens
|
||||
for (const token of mangoAccount.tokensActive()) {
|
||||
const native = token.native(group.findBank(token.tokenIndex)!);
|
||||
const native = token.balance(
|
||||
group.getFirstBankByTokenIndex(token.tokenIndex)!,
|
||||
);
|
||||
console.log(
|
||||
`token native ${native} ${group.findBank(token.tokenIndex)!.name}`,
|
||||
`token native ${native} ${
|
||||
group.getFirstBankByTokenIndex(token.tokenIndex)!.name
|
||||
}`,
|
||||
);
|
||||
if (native.toNumber() < 1) {
|
||||
continue;
|
||||
|
@ -94,8 +102,12 @@ async function closeUserAccount(userKeypairFile: string) {
|
|||
await client.tokenWithdrawNative(
|
||||
group,
|
||||
mangoAccount,
|
||||
group.findBank(token.tokenIndex)!.name,
|
||||
token.native(group.findBank(token.tokenIndex)!).toNumber(),
|
||||
group.getFirstBankByTokenIndex(token.tokenIndex)!.mint,
|
||||
new BN(
|
||||
token
|
||||
.balance(group.getFirstBankByTokenIndex(token.tokenIndex)!)
|
||||
.toNumber(),
|
||||
),
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
@ -103,7 +115,7 @@ async function closeUserAccount(userKeypairFile: string) {
|
|||
console.log(error);
|
||||
}
|
||||
|
||||
await mangoAccount.reload(client, group);
|
||||
await mangoAccount.reload(client);
|
||||
console.log(`...mangoAccount ${mangoAccount.publicKey}`);
|
||||
console.log(mangoAccount.toString());
|
||||
|
||||
|
|
|
@ -115,16 +115,18 @@ async function main() {
|
|||
console.log(
|
||||
'mangoAccount.simHealthWithTokenPositionChanges ' +
|
||||
toUiDecimalsForQuote(
|
||||
await mangoAccount.simHealthRatioWithTokenPositionUiChanges(group, [
|
||||
mangoAccount.simHealthRatioWithTokenPositionUiChanges(group, [
|
||||
{
|
||||
mintPk: group.banksMapByName.get('USDC')![0].mint,
|
||||
uiTokenAmount:
|
||||
-20_000 * Math.pow(10, group.banksMap.get('BTC')?.mintDecimals!),
|
||||
-20000 *
|
||||
Math.pow(10, group.banksMapByName.get('BTC')![0].mintDecimals!),
|
||||
},
|
||||
{
|
||||
mintPk: group.banksMapByName.get('BTC')![0].mint,
|
||||
uiTokenAmount:
|
||||
1 * Math.pow(10, group.banksMap.get('BTC')?.mintDecimals!),
|
||||
1 *
|
||||
Math.pow(10, group.banksMapByName.get('BTC')![0].mintDecimals!),
|
||||
},
|
||||
]),
|
||||
),
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { AnchorProvider, Wallet } from '@project-serum/anchor';
|
||||
import { Connection, Keypair, PublicKey } from '@solana/web3.js';
|
||||
import { Connection, Keypair } from '@solana/web3.js';
|
||||
import fs from 'fs';
|
||||
import { MangoClient } from '../client';
|
||||
import { MANGO_V4_ID } from '../constants';
|
||||
|
@ -59,15 +59,15 @@ async function main() {
|
|||
try {
|
||||
console.log(`...depositing 5 USDC`);
|
||||
await client.tokenDeposit(group, mangoAccount, usdcMint, 5);
|
||||
await mangoAccount.reload(client, group);
|
||||
await mangoAccount.reload(client);
|
||||
|
||||
console.log(`...depositing 0.0002 BTC`);
|
||||
await client.tokenDeposit(group, mangoAccount, btcMint, 0.0002);
|
||||
await mangoAccount.reload(client, group);
|
||||
await mangoAccount.reload(client);
|
||||
|
||||
console.log(`...depositing 0.15 SOL`);
|
||||
await client.tokenDeposit(group, mangoAccount, solMint, 0.15);
|
||||
await mangoAccount.reload(client, group);
|
||||
await mangoAccount.reload(client);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import { AnchorProvider, Wallet } from '@project-serum/anchor';
|
||||
import { AnchorProvider, BN, Wallet } from '@project-serum/anchor';
|
||||
import { Connection, Keypair, PublicKey } from '@solana/web3.js';
|
||||
import fs from 'fs';
|
||||
import { MangoAccount } from '../accounts/mangoAccount';
|
||||
import { PerpOrderSide, PerpOrderType } from '../accounts/perp';
|
||||
import {
|
||||
Serum3OrderType,
|
||||
Serum3SelfTradeBehavior,
|
||||
Serum3Side,
|
||||
} from '../accounts/serum3';
|
||||
import { Side, PerpOrderType } from '../accounts/perp';
|
||||
import { MangoAccount } from '../accounts/mangoAccount';
|
||||
import { MangoClient } from '../client';
|
||||
import { MANGO_V4_ID } from '../constants';
|
||||
|
||||
|
@ -105,9 +105,9 @@ async function main() {
|
|||
group,
|
||||
mangoAccount,
|
||||
assetMint,
|
||||
assetAmount,
|
||||
new BN(assetAmount),
|
||||
);
|
||||
await mangoAccount.reload(client, group);
|
||||
await mangoAccount.reload(client);
|
||||
|
||||
if (liabAmount > 0) {
|
||||
// temporarily drop the borrowed token value, so the borrow goes through
|
||||
|
@ -119,7 +119,7 @@ async function main() {
|
|||
group,
|
||||
mangoAccount,
|
||||
liabMint,
|
||||
liabAmount,
|
||||
new BN(liabAmount),
|
||||
true,
|
||||
);
|
||||
} finally {
|
||||
|
@ -139,12 +139,17 @@ async function main() {
|
|||
`...created mangoAccount ${mangoAccount.publicKey} for ${name}`,
|
||||
);
|
||||
|
||||
const market = group.getSerum3MarketByIndexByName('SOL/USDC')!;
|
||||
const market = group.getSerum3MarketByName('SOL/USDC')!;
|
||||
const sellMint = new PublicKey(MAINNET_MINTS.get('USDC')!);
|
||||
const buyMint = new PublicKey(MAINNET_MINTS.get('SOL')!);
|
||||
|
||||
await client.tokenDepositNative(group, mangoAccount, sellMint, 100000);
|
||||
await mangoAccount.reload(client, group);
|
||||
await client.tokenDepositNative(
|
||||
group,
|
||||
mangoAccount,
|
||||
sellMint,
|
||||
new BN(100000),
|
||||
);
|
||||
await mangoAccount.reload(client);
|
||||
|
||||
// temporarily up the init asset weight of the bought token
|
||||
await client.tokenEdit(
|
||||
|
@ -215,9 +220,9 @@ async function main() {
|
|||
group,
|
||||
mangoAccount,
|
||||
collateralMint,
|
||||
100000,
|
||||
new BN(100000),
|
||||
); // valued as $0.004 maint collateral
|
||||
await mangoAccount.reload(client, group);
|
||||
await mangoAccount.reload(client);
|
||||
|
||||
await client.stubOracleSet(group, collateralOracle, PRICES['SOL'] * 4);
|
||||
|
||||
|
@ -225,8 +230,8 @@ async function main() {
|
|||
await client.perpPlaceOrder(
|
||||
group,
|
||||
mangoAccount,
|
||||
'MNGO-PERP',
|
||||
Side.bid,
|
||||
group.perpMarketsMapByName.get('MNGO-PERP')?.perpMarketIndex!,
|
||||
PerpOrderSide.bid,
|
||||
1, // ui price that won't get hit
|
||||
0.0011, // ui base quantity, 11 base lots, $0.044
|
||||
0.044, // ui quote quantity
|
||||
|
@ -258,9 +263,9 @@ async function main() {
|
|||
group,
|
||||
mangoAccount,
|
||||
collateralMint,
|
||||
100000,
|
||||
new BN(100000),
|
||||
); // valued as $0.004 maint collateral
|
||||
await mangoAccount.reload(client, group);
|
||||
await mangoAccount.reload(client);
|
||||
|
||||
await client.stubOracleSet(group, collateralOracle, PRICES['SOL'] * 5);
|
||||
|
||||
|
@ -268,8 +273,8 @@ async function main() {
|
|||
await client.perpPlaceOrder(
|
||||
group,
|
||||
fundingAccount,
|
||||
'MNGO-PERP',
|
||||
Side.ask,
|
||||
group.perpMarketsMapByName.get('MNGO-PERP')?.perpMarketIndex!,
|
||||
PerpOrderSide.ask,
|
||||
40,
|
||||
0.0011, // ui base quantity, 11 base lots, $0.044
|
||||
0.044, // ui quote quantity
|
||||
|
@ -282,8 +287,8 @@ async function main() {
|
|||
await client.perpPlaceOrder(
|
||||
group,
|
||||
mangoAccount,
|
||||
'MNGO-PERP',
|
||||
Side.bid,
|
||||
group.perpMarketsMapByName.get('MNGO-PERP')?.perpMarketIndex!,
|
||||
PerpOrderSide.bid,
|
||||
40,
|
||||
0.0011, // ui base quantity, 11 base lots, $0.044
|
||||
0.044, // ui quote quantity
|
||||
|
@ -293,7 +298,10 @@ async function main() {
|
|||
5,
|
||||
);
|
||||
|
||||
await client.perpConsumeAllEvents(group, 'MNGO-PERP');
|
||||
await client.perpConsumeAllEvents(
|
||||
group,
|
||||
group.perpMarketsMapByName.get('MNGO-PERP')?.perpMarketIndex!,
|
||||
);
|
||||
} finally {
|
||||
await client.stubOracleSet(group, collateralOracle, PRICES['SOL']);
|
||||
}
|
||||
|
@ -320,9 +328,9 @@ async function main() {
|
|||
group,
|
||||
mangoAccount,
|
||||
collateralMint,
|
||||
100000,
|
||||
new BN(100000),
|
||||
); // valued as $0.004 maint collateral
|
||||
await mangoAccount.reload(client, group);
|
||||
await mangoAccount.reload(client);
|
||||
|
||||
try {
|
||||
await client.stubOracleSet(group, collateralOracle, PRICES['SOL'] * 10);
|
||||
|
@ -332,18 +340,18 @@ async function main() {
|
|||
group,
|
||||
mangoAccount,
|
||||
liabMint,
|
||||
-5000,
|
||||
new BN(-5000),
|
||||
true,
|
||||
);
|
||||
await mangoAccount.reload(client, group);
|
||||
await mangoAccount.reload(client);
|
||||
|
||||
// Execute two trades that leave the account with +$0.022 positive pnl
|
||||
await client.stubOracleSet(group, baseOracle, PRICES['MNGO'] / 2);
|
||||
await client.perpPlaceOrder(
|
||||
group,
|
||||
fundingAccount,
|
||||
'MNGO-PERP',
|
||||
Side.ask,
|
||||
group.perpMarketsMapByName.get('MNGO-PERP')?.perpMarketIndex!,
|
||||
PerpOrderSide.ask,
|
||||
20,
|
||||
0.0011, // ui base quantity, 11 base lots, $0.022
|
||||
0.022, // ui quote quantity
|
||||
|
@ -355,8 +363,8 @@ async function main() {
|
|||
await client.perpPlaceOrder(
|
||||
group,
|
||||
mangoAccount,
|
||||
'MNGO-PERP',
|
||||
Side.bid,
|
||||
group.perpMarketsMapByName.get('MNGO-PERP')?.perpMarketIndex!,
|
||||
PerpOrderSide.bid,
|
||||
20,
|
||||
0.0011, // ui base quantity, 11 base lots, $0.022
|
||||
0.022, // ui quote quantity
|
||||
|
@ -365,15 +373,18 @@ async function main() {
|
|||
0,
|
||||
5,
|
||||
);
|
||||
await client.perpConsumeAllEvents(group, 'MNGO-PERP');
|
||||
await client.perpConsumeAllEvents(
|
||||
group,
|
||||
group.perpMarketsMapByName.get('MNGO-PERP')?.perpMarketIndex!,
|
||||
);
|
||||
|
||||
await client.stubOracleSet(group, baseOracle, PRICES['MNGO']);
|
||||
|
||||
await client.perpPlaceOrder(
|
||||
group,
|
||||
fundingAccount,
|
||||
'MNGO-PERP',
|
||||
Side.bid,
|
||||
group.perpMarketsMapByName.get('MNGO-PERP')?.perpMarketIndex!,
|
||||
PerpOrderSide.bid,
|
||||
40,
|
||||
0.0011, // ui base quantity, 11 base lots, $0.044
|
||||
0.044, // ui quote quantity
|
||||
|
@ -385,8 +396,8 @@ async function main() {
|
|||
await client.perpPlaceOrder(
|
||||
group,
|
||||
mangoAccount,
|
||||
'MNGO-PERP',
|
||||
Side.ask,
|
||||
group.perpMarketsMapByName.get('MNGO-PERP')?.perpMarketIndex!,
|
||||
PerpOrderSide.ask,
|
||||
40,
|
||||
0.0011, // ui base quantity, 11 base lots, $0.044
|
||||
0.044, // ui quote quantity
|
||||
|
@ -395,7 +406,10 @@ async function main() {
|
|||
0,
|
||||
5,
|
||||
);
|
||||
await client.perpConsumeAllEvents(group, 'MNGO-PERP');
|
||||
await client.perpConsumeAllEvents(
|
||||
group,
|
||||
group.perpMarketsMapByName.get('MNGO-PERP')?.perpMarketIndex!,
|
||||
);
|
||||
} finally {
|
||||
await client.stubOracleSet(group, collateralOracle, PRICES['SOL']);
|
||||
await client.stubOracleSet(group, baseOracle, PRICES['MNGO']);
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import { BN, AnchorProvider, Wallet } from '@project-serum/anchor';
|
||||
import { Connection, Keypair, PublicKey } from '@solana/web3.js';
|
||||
import { AnchorProvider, Wallet } from '@project-serum/anchor';
|
||||
import { Connection, Keypair } from '@solana/web3.js';
|
||||
import fs from 'fs';
|
||||
import { MangoClient } from '../client';
|
||||
import { Side, PerpOrderType } from '../accounts/perp';
|
||||
import { MANGO_V4_ID } from '../constants';
|
||||
|
||||
//
|
||||
|
@ -49,14 +48,14 @@ async function main() {
|
|||
let accounts = await client.getMangoAccountsForOwner(group, admin.publicKey);
|
||||
for (let account of accounts) {
|
||||
for (let serumOrders of account.serum3Active()) {
|
||||
const serumMarket = group.getSerum3MarketByIndex(
|
||||
const serumMarket = group.getSerum3MarketByMarketIndex(
|
||||
serumOrders.marketIndex,
|
||||
)!;
|
||||
const serumExternal = serumMarket.serumMarketExternal;
|
||||
console.log(
|
||||
`closing serum orders on: ${account} for market ${serumMarket.name}`,
|
||||
);
|
||||
await client.serum3CancelAllorders(group, account, serumExternal, 10);
|
||||
await client.serum3CancelAllOrders(group, account, serumExternal, 10);
|
||||
await client.serum3SettleFunds(group, account, serumExternal);
|
||||
await client.serum3CloseOpenOrders(group, account, serumExternal);
|
||||
}
|
||||
|
@ -66,7 +65,12 @@ async function main() {
|
|||
console.log(
|
||||
`closing perp orders on: ${account} for market ${perpMarket.name}`,
|
||||
);
|
||||
await client.perpCancelAllOrders(group, account, perpMarket.name, 10);
|
||||
await client.perpCancelAllOrders(
|
||||
group,
|
||||
account,
|
||||
perpMarket.perpMarketIndex,
|
||||
10,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
import { AnchorProvider, Wallet } from '@project-serum/anchor';
|
||||
import { Connection, Keypair, PublicKey } from '@solana/web3.js';
|
||||
import fs from 'fs';
|
||||
import { Serum3Side } from '../accounts/serum3';
|
||||
import { MangoClient } from '../client';
|
||||
import { MANGO_V4_ID } from '../constants';
|
||||
|
||||
//
|
||||
// (untested?) script which closes a mango account cleanly, first closes all positions, withdraws all tokens and then closes it
|
||||
//
|
||||
async function viewUnownedAccount(userKeypairFile: string) {
|
||||
const options = AnchorProvider.defaultOptions();
|
||||
const connection = new Connection(
|
||||
'https://mango.rpcpool.com/0f9acc0d45173b51bf7d7e09c1e5',
|
||||
options,
|
||||
);
|
||||
|
||||
// user
|
||||
const userWallet = new Wallet(Keypair.generate());
|
||||
const userProvider = new AnchorProvider(connection, userWallet, options);
|
||||
const client = await MangoClient.connect(
|
||||
userProvider,
|
||||
'mainnet-beta',
|
||||
MANGO_V4_ID['mainnet-beta'],
|
||||
);
|
||||
console.log(`User ${userWallet.publicKey.toBase58()}`);
|
||||
|
||||
// admin
|
||||
const admin = Keypair.fromSecretKey(
|
||||
Buffer.from(
|
||||
JSON.parse(fs.readFileSync(process.env.MB_PAYER_KEYPAIR || '', 'utf-8')),
|
||||
),
|
||||
);
|
||||
console.log(`Admin ${admin.publicKey.toBase58()}`);
|
||||
|
||||
// fetch group
|
||||
const group = await client.getGroupForCreator(admin.publicKey, 2);
|
||||
console.log(`Found group ${group.publicKey.toBase58()}`);
|
||||
|
||||
const x = await client.getMangoAccount(
|
||||
new PublicKey('6cTqJrSzQZWGEeHHePqFuJV4Kf54YDVfSamdCrT3agw6'),
|
||||
);
|
||||
const y = await x.reloadAccountData(client, group);
|
||||
|
||||
process.exit();
|
||||
}
|
||||
|
||||
async function main() {
|
||||
await viewUnownedAccount(process.env.MB_USER2_KEYPAIR || '');
|
||||
}
|
||||
|
||||
main();
|
|
@ -2,7 +2,9 @@
|
|||
"compilerOptions": {
|
||||
"esModuleInterop": true,
|
||||
"moduleResolution": "node",
|
||||
"lib": ["es2019"],
|
||||
"lib": [
|
||||
"es2019"
|
||||
],
|
||||
"outDir": "./dist",
|
||||
"resolveJsonModule": true,
|
||||
"noImplicitAny": false,
|
||||
|
@ -11,12 +13,14 @@
|
|||
"target": "es2019",
|
||||
"strictNullChecks": true
|
||||
},
|
||||
"include": ["ts/client/src", "ts/client/scripts", "ts/client/scripts"],
|
||||
"include": [
|
||||
"ts/client/src",
|
||||
"ts/client/src/scripts",
|
||||
"ts/client/src/debug-scripts",
|
||||
"ts/client/src/deployment-scripts"
|
||||
],
|
||||
"exclude": [
|
||||
"./ts/**/*.test.js",
|
||||
"node_modules",
|
||||
"**/node_modules",
|
||||
"./ts/client/src/scripts",
|
||||
"./ts/client/src/debug-scripts"
|
||||
]
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue