From 6eaf842b9d9afa8f9edf3184c6c0e47c347e5f1d Mon Sep 17 00:00:00 2001 From: dd Date: Sat, 5 Jun 2021 09:46:37 -0400 Subject: [PATCH] Added support for AddMarginAccountInfo instruction but NOT TESTED --- src/client.ts | 24 ++++++++++++++++++++++++ src/instruction.ts | 25 ++++++++++++++++++++++++- src/layout.ts | 6 ++++-- src/tests.ts | 22 ++++++++++------------ 4 files changed, 62 insertions(+), 15 deletions(-) diff --git a/src/client.ts b/src/client.ts index 1c58fcb..6f840cf 100644 --- a/src/client.ts +++ b/src/client.ts @@ -47,6 +47,7 @@ import { SRM_DECIMALS } from '@project-serum/serum/lib/token-instructions'; import { Order } from '@project-serum/serum/lib/market'; import Wallet from '@project-serum/sol-wallet-adapter'; import { + makeAddMarginAccountInfoInstruction, makeBorrowInstruction, makeCancelOrderInstruction, makeForceCancelOrdersInstruction, makePartialLiquidateInstruction, @@ -1303,6 +1304,27 @@ export class MangoClient { return await this.sendTransaction(connection, transaction, owner, additionalSigners) } + async addMarginAccountInfo( + connection: Connection, + programId: PublicKey, + mangoGroup: MangoGroup, + marginAccount: MarginAccount, + owner: Account, + info: string + ): Promise { + const instruction = makeAddMarginAccountInfoInstruction( + programId, + mangoGroup.publicKey, + owner.publicKey, + marginAccount.publicKey, + info + ) + const transaction = new Transaction() + transaction.add(instruction) + const additionalSigners = [] + + return await this.sendTransaction(connection, transaction, owner, additionalSigners) + } async getMangoGroup( connection: Connection, mangoGroupPk: PublicKey, @@ -1500,5 +1522,7 @@ export class MangoClient { return srmAccounts } + + } diff --git a/src/instruction.ts b/src/instruction.ts index a515492..524d205 100644 --- a/src/instruction.ts +++ b/src/instruction.ts @@ -5,7 +5,7 @@ import { TransactionInstruction, } from '@solana/web3.js'; import { Order } from '@project-serum/serum/lib/market'; -import { encodeMangoInstruction, NUM_TOKENS } from './layout'; +import { encodeMangoInstruction, INFO_LEN, NUM_TOKENS } from './layout'; import { TOKEN_PROGRAM_ID } from '@project-serum/serum/lib/token-instructions'; import { uiToNative } from './utils'; @@ -307,3 +307,26 @@ export function makePartialLiquidateInstruction( return new TransactionInstruction({ keys, data, programId }); } + +export function makeAddMarginAccountInfoInstruction( + programId: PublicKey, + mangoGroup: PublicKey, + marginAccount: PublicKey, + owner: PublicKey, + info: string +): TransactionInstruction { + const keys = [ + { isSigner: false, isWritable: true, pubkey: mangoGroup }, + { isSigner: false, isWritable: true, pubkey: marginAccount }, + { isSigner: true, isWritable: false, pubkey: owner }, + ]; + // TODO convert info into a 32 byte utf encoded byte array + const encoded = Buffer.from(info) + if (encoded.length > INFO_LEN) { + throw new Error("info string too long. Must be less than or equal to 32 bytes") + } + const infoArray = new Uint8Array(encoded, 0, INFO_LEN) + const data = encodeMangoInstruction({ AddMarginAccountInfo: { info: infoArray } }); + + return new TransactionInstruction({ keys, data, programId }); +} \ No newline at end of file diff --git a/src/layout.ts b/src/layout.ts index aee42b2..4ee2ce2 100644 --- a/src/layout.ts +++ b/src/layout.ts @@ -8,6 +8,7 @@ export const MANGO_GROUP_PADDING = 8 - (NUM_TOKENS + NUM_MARKETS) % 8; export const MAX_RATE = 3.0 export const OPTIMAL_UTIL = 0.7 export const OPTIMAL_RATE = 0.2 +export const INFO_LEN = 32 class PublicKeyLayout extends Blob { constructor(property) { @@ -157,7 +158,8 @@ export const MarginAccountLayout = struct([ seq(publicKeyLayout(), NUM_MARKETS, 'openOrders'), u8('beingLiquidated'), u8('hasBorrows'), - seq(u8(), 70, 'padding') + seq(u8(), 32, 'info'), + seq(u8(), 38, 'padding') ]); export const MangoSrmAccountLayout = struct([ @@ -277,7 +279,7 @@ MangoInstructionLayout.addVariant(14, ) MangoInstructionLayout.addVariant(15, struct([u8('limit')]), 'ForceCancelOrders') MangoInstructionLayout.addVariant(16, struct([u64('maxDeposit')]), 'PartialLiquidate') - +MangoInstructionLayout.addVariant(17, struct([seq(u8(), INFO_LEN, 'info')]), 'AddMarginAccountInfo') // @ts-ignore const instructionMaxSpan = Math.max(...Object.values(MangoInstructionLayout.registry).map((r) => r.span)); export function encodeMangoInstruction(data) { diff --git a/src/tests.ts b/src/tests.ts index 27ce624..87555df 100644 --- a/src/tests.ts +++ b/src/tests.ts @@ -13,6 +13,7 @@ import { parseTokenAccountData, sleep } from './utils' +import { NUM_TOKENS } from './layout'; async function tests() { const cluster = "mainnet-beta"; @@ -20,7 +21,7 @@ async function tests() { const clusterIds = IDS[cluster] const connection = new Connection(IDS.cluster_urls[cluster], 'processed' as Commitment) - const mangoGroupPk = new PublicKey(clusterIds.mango_groups['BTC_ETH_USDT'].mango_group_pk); + const mangoGroupPk = new PublicKey(clusterIds.mango_groups['BTC_ETH_SOL_SRM_USDC'].mango_group_pk); const mangoProgramId = new PublicKey(clusterIds.mango_program_id); const keyPairPath = process.env.KEYPAIR || os.homedir() + '/.config/solana/id.json' @@ -52,19 +53,19 @@ async function tests() { } */ - /* async function getMarginAccountDetails() { const mangoGroup = await client.getMangoGroup(connection, mangoGroupPk); - const marginAccountPk = new PublicKey("6vAry8oHVvWqPJV6SMzzJ9EcQr5kkQYHef6ui2ewaagQ") + const marginAccountPk = new PublicKey("Ga6xNLmkq3Mw95kUWPip2xnUGGEWnFmeiYFxjaZ1GFse") const marginAccount = await client.getMarginAccount(connection, marginAccountPk, mangoGroup.dexProgramId) const prices = await mangoGroup.getPrices(connection) console.log(marginAccount.toPrettyString(mangoGroup, prices)) console.log(marginAccount.beingLiquidated) - console.log(marginAccount.getUiDeposit(mangoGroup, 0), marginAccount.getUiBorrow(mangoGroup, 0)) - console.log(marginAccount.getUiDeposit(mangoGroup, 1), marginAccount.getUiBorrow(mangoGroup, 1)) - console.log(marginAccount.getUiDeposit(mangoGroup, 2), marginAccount.getUiBorrow(mangoGroup, 2)) console.log(marginAccount.getCollateralRatio(mangoGroup, prices)) + + for (let i = 0; i < NUM_TOKENS; i++) { + console.log(marginAccount.getUiDeposit(mangoGroup, i), marginAccount.getUiBorrow(mangoGroup, i)) + } // for (let i = 0; i < NUM_MARKETS; i++) { // let openOrdersAccount = marginAccount.openOrdersAccounts[i] // if (openOrdersAccount === undefined) { @@ -85,7 +86,6 @@ async function tests() { // } } - */ async function testMarketOrderDex() { const NUM_MARKETS = 2; @@ -165,12 +165,10 @@ async function tests() { } } - /* await getMarginAccountDetails() - await testSolink() - await testDepositSrm() - */ - await testMarketOrderDex() + // await testSolink() + // await testDepositSrm() + // await testMarketOrderDex() } tests()