mango-v4/ts/client/scripts/create-gov-ix.ts

391 lines
11 KiB
TypeScript

import { AnchorProvider } from '@coral-xyz/anchor';
import { BN, Wallet } from '@project-serum/anchor';
import { serializeInstructionToBase64 } from '@solana/spl-governance';
import {
AccountMeta,
Connection,
Keypair,
PublicKey,
SYSVAR_RENT_PUBKEY,
SystemProgram,
} from '@solana/web3.js';
import fs from 'fs';
import { TokenIndex } from '../src/accounts/bank';
import { PerpMarketIndex } from '../src/accounts/perp';
import { Builder } from '../src/builder';
import { MangoClient } from '../src/client';
import {
NullPerpEditParams,
NullTokenEditParams,
TrueIxGateParams,
buildIxGate,
} from '../src/clientIxParamBuilder';
import { MANGO_V4_ID, OPENBOOK_PROGRAM_ID } from '../src/constants';
import { bpsToDecimal, percentageToDecimal, toNative } from '../src/utils';
const { MB_CLUSTER_URL, MB_PAYER_KEYPAIR } = process.env;
const CLIENT_USER = MB_PAYER_KEYPAIR;
const GROUP_PK = '78b8f4cGCwmZ9ysPFMWLaLTkkaYnUjwMJYStWe5RTSSX';
const defaultOracleConfig = {
confFilter: 0.1,
maxStalenessSlots: 120,
};
const defaultInterestRate = {
adjustmentFactor: 0.004,
util0: 0.7,
rate0: 0.1,
util1: 0.85,
rate1: 0.2,
maxRate: 2.0,
};
async function buildClient(): Promise<MangoClient> {
const clientKeypair = Keypair.fromSecretKey(
Buffer.from(JSON.parse(fs.readFileSync(CLIENT_USER!, 'utf-8'))),
);
const options = AnchorProvider.defaultOptions();
const connection = new Connection(MB_CLUSTER_URL!, options);
const clientWallet = new Wallet(clientKeypair);
const clientProvider = new AnchorProvider(connection, clientWallet, options);
return await MangoClient.connect(
clientProvider,
'mainnet-beta',
MANGO_V4_ID['mainnet-beta'],
{
idsSource: 'get-program-accounts',
},
);
}
async function tokenRegister(): Promise<void> {
const client = await buildClient();
const group = await client.getGroup(new PublicKey(GROUP_PK));
const ix = await client.program.methods
.tokenRegister(
8 as TokenIndex,
'wBTC (Portal)',
defaultOracleConfig,
defaultInterestRate,
bpsToDecimal(50),
bpsToDecimal(5),
0.9,
0.8,
1.1,
1.2,
percentageToDecimal(5),
percentageToDecimal(20),
new BN(24 * 60 * 60),
new BN(toNative(50000, 6).toNumber()),
)
.accounts({
group: group.publicKey,
admin: group.admin,
mint: new PublicKey('3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh'),
oracle: new PublicKey('GVXRSBjFk6e6J3NbVPXohDJetcTjaeeuykUpbQF8UoMU'),
payer: (client.program.provider as AnchorProvider).wallet.publicKey,
rent: SYSVAR_RENT_PUBKEY,
})
.instruction();
// const coder = new BorshCoder(IDL);
// console.log(coder.instruction.decode(ix.data));
console.log(await serializeInstructionToBase64(ix));
}
async function tokenEdit(): Promise<void> {
const client = await buildClient();
const group = await client.getGroup(new PublicKey(GROUP_PK));
const params = Builder(NullTokenEditParams)
.borrowWeightScaleStartQuote(new BN(toNative(100000, 6)).toNumber())
.depositWeightScaleStartQuote(new BN(toNative(100000, 6)).toNumber())
.build();
const ix = await client.program.methods
.tokenEdit(
params.oracle,
params.oracleConfig,
params.groupInsuranceFund,
params.interestRateParams,
params.loanFeeRate,
params.loanOriginationFeeRate,
params.maintAssetWeight,
params.initAssetWeight,
params.maintLiabWeight,
params.initLiabWeight,
params.liquidationFee,
params.stablePriceDelayIntervalSeconds,
params.stablePriceDelayGrowthLimit,
params.stablePriceGrowthLimit,
params.minVaultToDepositsRatio,
params.netBorrowLimitPerWindowQuote !== null
? new BN(params.netBorrowLimitPerWindowQuote)
: null,
params.netBorrowLimitWindowSizeTs !== null
? new BN(params.netBorrowLimitWindowSizeTs)
: null,
params.borrowWeightScaleStartQuote,
params.depositWeightScaleStartQuote,
params.resetStablePrice ?? false,
params.resetNetBorrowLimit ?? false,
params.reduceOnly,
params.name,
params.forceClose,
)
.accounts({
group: group.publicKey,
oracle: new PublicKey('GVXRSBjFk6e6J3NbVPXohDJetcTjaeeuykUpbQF8UoMU'),
admin: group.admin,
mintInfo: new PublicKey('59rgC1pa45EziDPyFgJgE7gbv7Dd7VaGmd2D93i1dtFk'),
})
.remainingAccounts([
{
pubkey: new PublicKey('8gabXzwdPn5TvtuQvysh3CxVbjfNY3TZd5XEG5qnueUm'),
isWritable: true,
isSigner: false,
} as AccountMeta,
])
.instruction();
console.log(serializeInstructionToBase64(ix));
}
async function serum3Register(): Promise<void> {
const client = await buildClient();
const group = await client.getGroup(new PublicKey(GROUP_PK));
const ix = await client.program.methods
.serum3RegisterMarket(3, 'ETH (Portal)/USDC')
.accounts({
group: group.publicKey,
admin: group.admin,
serumProgram: OPENBOOK_PROGRAM_ID['mainnet-beta'],
serumMarketExternal: new PublicKey(
'BbJgE7HZMaDp5NTYvRh5jZSkQPVDTU8ubPFtpogUkEj4',
),
baseBank: group.getFirstBankByMint(
new PublicKey('7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs'),
).publicKey,
quoteBank: group.getFirstBankByMint(
new PublicKey('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'),
).publicKey,
payer: (client.program.provider as AnchorProvider).wallet.publicKey,
})
.instruction();
console.log(serializeInstructionToBase64(ix));
}
async function perpCreate(): Promise<void> {
const client = await buildClient();
const bids = new Keypair();
const asks = new Keypair();
const eventQueue = new Keypair();
const bookSideSize = (client.program as any)._coder.accounts.size(
(client.program.account.bookSide as any)._idlAccount,
);
const eventQueueSize = (client.program as any)._coder.accounts.size(
(client.program.account.eventQueue as any)._idlAccount,
);
const group = await client.getGroup(new PublicKey(GROUP_PK));
const ix = await client.program.methods
.perpCreateMarket(
2,
'SOL-PERP',
defaultOracleConfig,
9,
new BN(100),
new BN(10000000),
0.9,
0.8,
1.1,
1.2,
0,
0,
percentageToDecimal(5),
bpsToDecimal(-1),
bpsToDecimal(4),
percentageToDecimal(-5),
percentageToDecimal(5),
new BN(100),
false,
bpsToDecimal(0.5),
toNative(0.0001, 6).toNumber(),
toNative(100, 6).toNumber(),
percentageToDecimal(1),
0,
1,
new BN(60 * 60),
percentageToDecimal(10),
)
.accounts({
group: group.publicKey,
admin: group.admin,
oracle: new PublicKey('H6ARHf6YXhGYeQfUzQNGk6rDNnLBQKrenN712K4AQJEG'),
bids: bids.publicKey,
asks: asks.publicKey,
eventQueue: eventQueue.publicKey,
payer: (client.program.provider as AnchorProvider).wallet.publicKey,
})
.preInstructions([
// book sides
SystemProgram.createAccount({
programId: client.program.programId,
space: bookSideSize,
lamports:
await client.program.provider.connection.getMinimumBalanceForRentExemption(
bookSideSize,
),
fromPubkey: (client.program.provider as AnchorProvider).wallet
.publicKey,
newAccountPubkey: bids.publicKey,
}),
SystemProgram.createAccount({
programId: client.program.programId,
space: bookSideSize,
lamports:
await client.program.provider.connection.getMinimumBalanceForRentExemption(
bookSideSize,
),
fromPubkey: (client.program.provider as AnchorProvider).wallet
.publicKey,
newAccountPubkey: asks.publicKey,
}),
// event queue
SystemProgram.createAccount({
programId: client.program.programId,
space: eventQueueSize,
lamports:
await client.program.provider.connection.getMinimumBalanceForRentExemption(
eventQueueSize,
),
fromPubkey: (client.program.provider as AnchorProvider).wallet
.publicKey,
newAccountPubkey: eventQueue.publicKey,
}),
])
.signers([bids, asks, eventQueue])
.instruction();
console.log(serializeInstructionToBase64(ix));
}
async function perpEdit(): Promise<void> {
const client = await buildClient();
const group = await client.getGroup(new PublicKey(GROUP_PK));
const perpMarket = group.getPerpMarketByMarketIndex(0 as PerpMarketIndex);
const params = Builder(NullPerpEditParams)
.positivePnlLiquidationFee(bpsToDecimal(250))
.build();
const ix = await client.program.methods
.perpEditMarket(
params.oracle,
params.oracleConfig,
params.baseDecimals,
params.maintBaseAssetWeight,
params.initBaseAssetWeight,
params.maintBaseLiabWeight,
params.initBaseLiabWeight,
params.maintOverallAssetWeight,
params.initOverallAssetWeight,
params.baseLiquidationFee,
params.makerFee,
params.takerFee,
params.minFunding,
params.maxFunding,
params.impactQuantity !== null ? new BN(params.impactQuantity) : null,
params.groupInsuranceFund,
params.feePenalty,
params.settleFeeFlat,
params.settleFeeAmountThreshold,
params.settleFeeFractionLowHealth,
params.stablePriceDelayIntervalSeconds,
params.stablePriceDelayGrowthLimit,
params.stablePriceGrowthLimit,
params.settlePnlLimitFactor,
params.settlePnlLimitWindowSize !== null
? new BN(params.settlePnlLimitWindowSize)
: null,
params.reduceOnly,
params.resetStablePrice ?? false,
params.positivePnlLiquidationFee,
params.name,
params.forceClose,
)
.accounts({
group: group.publicKey,
oracle: params.oracle ?? perpMarket.oracle,
admin: group.admin,
perpMarket: perpMarket.publicKey,
})
.instruction();
console.log(serializeInstructionToBase64(ix));
}
async function ixDisable(): Promise<void> {
const client = await buildClient();
const group = await client.getGroup(new PublicKey(GROUP_PK));
const ixGateParams = TrueIxGateParams;
ixGateParams.HealthRegion = false;
const ix = await client.program.methods
.ixGateSet(buildIxGate(ixGateParams))
.accounts({
group: group.publicKey,
admin: group.securityAdmin,
})
.instruction();
console.log(await serializeInstructionToBase64(ix));
}
async function createMangoAccount(): Promise<void> {
const client = await buildClient();
const group = await client.getGroup(new PublicKey(GROUP_PK));
const ix = await client.program.methods
.accountCreate(0, 8, 8, 8, 32, 'Mango DAO 0')
.accounts({
group: group.publicKey,
owner: new PublicKey('5tgfd6XgwiXB9otEnzFpXK11m7Q7yZUaAJzWK4oT5UGF'),
payer: new PublicKey('5tgfd6XgwiXB9otEnzFpXK11m7Q7yZUaAJzWK4oT5UGF'),
})
.instruction();
console.log(await serializeInstructionToBase64(ix));
}
async function main(): Promise<void> {
try {
// await tokenRegister();
// await tokenEdit();
// await perpCreate();
await perpEdit();
// await serum3Register();
// await ixDisable();
// await createMangoAccount();
} catch (error) {
console.log(error);
}
}
try {
main();
} catch (error) {
console.log(error);
}