ts: client and script fixes

This commit is contained in:
Christian Kamm 2022-08-08 16:31:38 +02:00
parent 55e891417e
commit 3257017770
6 changed files with 111 additions and 133 deletions

View File

@ -128,9 +128,7 @@ export class MangoClient {
return group;
}
public async getGroupsForCreator(
creatorPk: PublicKey,
): Promise<Group[]> {
public async getGroupsForCreator(creatorPk: PublicKey): Promise<Group[]> {
const filters: MemcmpFilter[] = [
{
memcmp: {
@ -140,8 +138,8 @@ export class MangoClient {
},
];
return (await this.program.account.group.all(filters)).map(
(tuple) => Group.from(tuple.publicKey, tuple.account),
return (await this.program.account.group.all(filters)).map((tuple) =>
Group.from(tuple.publicKey, tuple.account),
);
}
@ -149,14 +147,15 @@ export class MangoClient {
creatorPk: PublicKey,
groupNum?: number,
): Promise<Group> {
const groups = (await this.getGroupsForCreator(creatorPk))
.filter((group) => {
const groups = (await this.getGroupsForCreator(creatorPk)).filter(
(group) => {
if (groupNum !== undefined) {
return group.groupNum == groupNum;
} else {
return true;
}
});
},
);
await groups[0].reloadAll(this);
return groups[0];
@ -475,12 +474,35 @@ export class MangoClient {
accountNumber?: number,
name?: string,
): Promise<MangoAccount> {
let mangoAccounts = await this.getMangoAccountsForOwner(group, ownerPk);
if (mangoAccounts.length === 0) {
await this.createMangoAccount(group, accountNumber, name);
mangoAccounts = await this.getMangoAccountsForOwner(group, ownerPk);
// TODO: this function discards accountSize and name when the account exists already!
// TODO: this function always creates accounts for this.program.owner, and not
// ownerPk! It needs to get passed a keypair, and we need to add
// createMangoAccountForOwner
if (accountNumber === undefined) {
// Get any MangoAccount
// TODO: should probably sort by accountNum for deterministic output!
let mangoAccounts = await this.getMangoAccountsForOwner(group, ownerPk);
if (mangoAccounts.length === 0) {
await this.createMangoAccount(group, accountNumber, name);
mangoAccounts = await this.getMangoAccountsForOwner(group, ownerPk);
}
return mangoAccounts[0];
} else {
let account = await this.getMangoAccountForOwner(
group,
ownerPk,
accountNumber,
);
if (account === undefined) {
await this.createMangoAccount(group, accountNumber, name);
account = await this.getMangoAccountForOwner(
group,
ownerPk,
accountNumber,
);
}
return account;
}
return mangoAccounts[0];
}
public async createMangoAccount(
@ -540,6 +562,16 @@ export class MangoClient {
);
}
public async getMangoAccountForOwner(
group: Group,
ownerPk: PublicKey,
accountNumber: number,
): Promise<MangoAccount> {
return (await this.getMangoAccountsForOwner(group, ownerPk)).find(
(a) => a.accountNum == accountNumber,
);
}
public async getMangoAccountsForOwner(
group: Group,
ownerPk: PublicKey,
@ -626,6 +658,22 @@ export class MangoClient {
amount: number,
): Promise<TransactionSignature> {
const bank = group.banksMap.get(tokenName)!;
const nativeAmount = toNativeDecimals(amount, bank.mintDecimals).toNumber();
return await this.tokenDepositNative(
group,
mangoAccount,
tokenName,
nativeAmount,
);
}
public async tokenDepositNative(
group: Group,
mangoAccount: MangoAccount,
tokenName: string,
nativeAmount: number,
) {
const bank = group.banksMap.get(tokenName)!;
const tokenAccountPk = await getAssociatedTokenAddress(
bank.mint,
@ -638,7 +686,7 @@ export class MangoClient {
const additionalSigners: Signer[] = [];
if (bank.mint.equals(WRAPPED_SOL_MINT)) {
wrappedSolAccount = new Keypair();
const lamports = Math.round(amount * LAMPORTS_PER_SOL) + 1e7;
const lamports = nativeAmount + 1e7;
preInstructions = [
SystemProgram.createAccount({
@ -673,7 +721,7 @@ export class MangoClient {
);
return await this.program.methods
.tokenDeposit(toNativeDecimals(amount, bank.mintDecimals))
.tokenDeposit(new BN(nativeAmount))
.accounts({
group: group.publicKey,
account: mangoAccount.publicKey,
@ -702,45 +750,14 @@ export class MangoClient {
allowBorrow: boolean,
): Promise<TransactionSignature> {
const bank = group.banksMap.get(tokenName)!;
const tokenAccountPk = await getAssociatedTokenAddress(
bank.mint,
mangoAccount.owner,
const nativeAmount = toNativeDecimals(amount, bank.mintDecimals).toNumber();
return await this.tokenWithdrawNative(
group,
mangoAccount,
tokenName,
nativeAmount,
allowBorrow,
);
const healthRemainingAccounts: PublicKey[] =
this.buildHealthRemainingAccounts(
AccountRetriever.Fixed,
group,
[mangoAccount],
[bank],
);
return await this.program.methods
.tokenWithdraw(toNativeDecimals(amount, bank.mintDecimals), allowBorrow)
.accounts({
group: group.publicKey,
account: mangoAccount.publicKey,
bank: bank.publicKey,
vault: bank.vault,
tokenAccount: tokenAccountPk,
owner: mangoAccount.owner,
})
.remainingAccounts(
healthRemainingAccounts.map(
(pk) =>
({ pubkey: pk, isWritable: false, isSigner: false } as AccountMeta),
),
)
.preInstructions([
// ensure withdraws don't fail with missing ATAs
await createAssociatedTokenAccountIdempotentInstruction(
mangoAccount.owner,
mangoAccount.owner,
bank.mint,
),
])
.rpc({ skipPreflight: true });
}
public async tokenWithdrawNative(
@ -781,6 +798,14 @@ export class MangoClient {
({ pubkey: pk, isWritable: false, isSigner: false } as AccountMeta),
),
)
.preInstructions([
// ensure withdraws don't fail with missing ATAs
await createAssociatedTokenAccountIdempotentInstruction(
mangoAccount.owner,
mangoAccount.owner,
bank.mint,
),
])
.rpc({ skipPreflight: true });
}

View File

@ -30,10 +30,12 @@ async function main() {
);
const groups = await (async () => {
if (GROUP_NUM === "all") {
if (GROUP_NUM === 'all') {
return await client.getGroupsForCreator(admin.publicKey);
} else {
return [await client.getGroupForCreator(admin.publicKey, Number(GROUP_NUM))];
return [
await client.getGroupForCreator(admin.publicKey, Number(GROUP_NUM)),
];
}
})();
for (const group of groups) {

View File

@ -65,9 +65,7 @@ async function main() {
} catch (error) {
console.log(error);
}
const oracle = (
await client.getStubOracle(group, mintPk)
)[0];
const oracle = (await client.getStubOracle(group, mintPk))[0];
console.log(`...created stub oracle ${oracle.publicKey}`);
oracles.set(name, oracle.publicKey);
}

View File

@ -17,7 +17,9 @@ async function main() {
const admin = Keypair.fromSecretKey(
Buffer.from(
JSON.parse(fs.readFileSync(process.env.MANGO_MAINNET_PAYER_KEYPAIR!, 'utf-8')),
JSON.parse(
fs.readFileSync(process.env.MANGO_MAINNET_PAYER_KEYPAIR!, 'utf-8'),
),
),
);
const userWallet = new Wallet(admin);
@ -45,16 +47,16 @@ async function main() {
// deposit
try {
console.log(`...depositing 1 USDC`);
await client.tokenDeposit(group, mangoAccount, 'USDC', 1);
console.log(`...depositing 10 USDC`);
await client.tokenDeposit(group, mangoAccount, 'USDC', 10);
await mangoAccount.reload(client, group);
console.log(`...depositing 0.00004 BTC`);
await client.tokenDeposit(group, mangoAccount, 'BTC', 0.00004);
console.log(`...depositing 0.0004 BTC`);
await client.tokenDeposit(group, mangoAccount, 'BTC', 0.0004);
await mangoAccount.reload(client, group);
console.log(`...depositing 0.025 SOL`);
await client.tokenDeposit(group, mangoAccount, 'SOL', 0.025);
console.log(`...depositing 0.25 SOL`);
await client.tokenDeposit(group, mangoAccount, 'SOL', 0.25);
await mangoAccount.reload(client, group);
} catch (error) {
console.log(error);

View File

@ -1,62 +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';
//
// This script tries to withdraw all positive balances for all accounts
// by MANGO_MAINNET_PAYER_KEYPAIR in the group.
//
const GROUP_NUM = Number(process.env.GROUP_NUM || 1);
async function main() {
const options = AnchorProvider.defaultOptions();
const connection = new Connection(process.env.CLUSTER_URL, options);
const admin = Keypair.fromSecretKey(
Buffer.from(
JSON.parse(fs.readFileSync(process.env.MANGO_MAINNET_PAYER_KEYPAIR!, 'utf-8')),
),
);
const userWallet = new Wallet(admin);
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()}`);
const group = await client.getGroupForCreator(admin.publicKey, GROUP_NUM);
console.log(group.toString());
const accounts = await client.getMangoAccountsForOwner(group, admin.publicKey);
for (let account of accounts) {
console.log(`account: ${account.publicKey}`);
for (let token of account.tokensActive()) {
const bank = group.findBank(token.tokenIndex);
const amount = token.native(bank).toNumber();
if (amount > 0) {
try {
const allowBorrow = true; // TODO: set this to false once the withdraw amount ___<___ nativePosition bug is fixed
await client.tokenWithdrawNative(group, account, bank.name, amount, allowBorrow);
await account.reload(client, group);
} catch(error) {
console.log(`failed to withdraw ${bank.name} from ${account.publicKey}: ${error}`);
}
}
}
try {
await client.closeMangoAccount(group, account);
} catch (error) {
console.log(`failed to close ${account.publicKey}: ${error}`);
}
}
process.exit();
}
main();

View File

@ -17,7 +17,9 @@ async function main() {
const admin = Keypair.fromSecretKey(
Buffer.from(
JSON.parse(fs.readFileSync(process.env.MANGO_MAINNET_PAYER_KEYPAIR!, 'utf-8')),
JSON.parse(
fs.readFileSync(process.env.MANGO_MAINNET_PAYER_KEYPAIR!, 'utf-8'),
),
),
);
const userWallet = new Wallet(admin);
@ -32,19 +34,30 @@ async function main() {
const group = await client.getGroupForCreator(admin.publicKey, GROUP_NUM);
console.log(group.toString());
const accounts = await client.getMangoAccountsForOwner(group, admin.publicKey);
const accounts = await client.getMangoAccountsForOwner(
group,
admin.publicKey,
);
for (let account of accounts) {
console.log(`account: ${account.publicKey}`);
console.log(`account: ${account}`);
for (let token of account.tokensActive()) {
const bank = group.findBank(token.tokenIndex);
const amount = token.native(bank).toNumber();
if (amount > 0) {
try {
const allowBorrow = true; // TODO: set this to false once the withdraw amount ___<___ nativePosition bug is fixed
await client.tokenWithdrawNative(group, account, bank.name, amount, allowBorrow);
await client.tokenWithdrawNative(
group,
account,
bank.name,
amount,
allowBorrow,
);
await account.reload(client, group);
} catch(error) {
console.log(`failed to withdraw ${bank.name} from ${account.publicKey}: ${error}`);
} catch (error) {
console.log(
`failed to withdraw ${bank.name} from ${account.publicKey}: ${error}`,
);
}
}
}