Merge pull request #6 from blockworks-foundation/srm_account

PR: Support MangoSrmAccount for fee discount deposit and withdraws
This commit is contained in:
Tyler 2021-03-04 18:07:33 -05:00 committed by GitHub
commit d0d38ea41b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 153 additions and 31 deletions

View File

@ -12,7 +12,7 @@ import {
} from '@solana/web3.js';
import {
encodeMangoInstruction,
MangoGroupLayout,
MangoGroupLayout, MangoSrmAccountLayout,
MarginAccountLayout,
MAX_RATE,
NUM_MARKETS,
@ -157,7 +157,6 @@ export class MarginAccount {
deposits!: number[];
borrows!: number[];
openOrders!: PublicKey[];
srmBalance!: number;
openOrdersAccounts: (OpenOrders | undefined)[] // undefined if an openOrdersAccount not yet initialized and has zeroKey
// TODO keep updated with websocket
@ -181,9 +180,7 @@ export class MarginAccount {
return nativeToUi(this.getNativeBorrow(mangoGroup, tokenIndex), mangoGroup.mintDecimals[tokenIndex])
}
getUiSrmBalance() {
return nativeToUi(this.srmBalance, SRM_DECIMALS)
}
async loadOpenOrders(
connection: Connection,
@ -362,6 +359,24 @@ export class MarginAccount {
}
export class MangoSrmAccount {
publicKey: PublicKey;
accountFlags!: WideBits;
mangoGroup!: PublicKey;
amount!: number;
constructor(publicKey: PublicKey, decoded: any) {
this.publicKey = publicKey
Object.assign(this, decoded)
}
getUiSrmAmount() {
return nativeToUi(this.amount, SRM_DECIMALS)
}
}
export class MangoClient {
async sendTransaction(
@ -766,39 +781,48 @@ export class MangoClient {
connection: Connection,
programId: PublicKey,
mangoGroup: MangoGroup,
marginAccount: MarginAccount,
owner: Account,
srmAccount: PublicKey,
quantity: number,
mangoSrmAccount?: PublicKey
): Promise<PublicKey> {
const transaction = new Transaction()
const additionalSigners: Account[] = []
if (!mangoSrmAccount) {
const accInstr = await createAccountInstruction(connection,
owner.publicKey, MangoSrmAccountLayout.span, programId)
transaction.add(accInstr.instruction)
additionalSigners.push(accInstr.account)
mangoSrmAccount = accInstr.account.publicKey
}
quantity: number
): Promise<TransactionSignature> {
const nativeQuantity = uiToNative(quantity, SRM_DECIMALS)
const keys = [
{ isSigner: false, isWritable: true, pubkey: mangoGroup.publicKey },
{ isSigner: false, isWritable: true, pubkey: marginAccount.publicKey },
{ isSigner: false, isWritable: true, pubkey: mangoSrmAccount },
{ isSigner: true, isWritable: false, pubkey: owner.publicKey },
{ isSigner: false, isWritable: true, pubkey: srmAccount },
{ isSigner: false, isWritable: true, pubkey: mangoGroup.srmVault },
{ isSigner: false, isWritable: false, pubkey: TOKEN_PROGRAM_ID },
{ isSigner: false, isWritable: false, pubkey: SYSVAR_CLOCK_PUBKEY }
{ isSigner: false, isWritable: false, pubkey: SYSVAR_CLOCK_PUBKEY },
{ isSigner: false, isWritable: false, pubkey: SYSVAR_RENT_PUBKEY }
]
const data = encodeMangoInstruction({DepositSrm: {quantity: nativeQuantity}})
const instruction = new TransactionInstruction( { keys, data, programId })
const transaction = new Transaction()
transaction.add(instruction)
const additionalSigners = []
return await this.sendTransaction(connection, transaction, owner, additionalSigners)
await this.sendTransaction(connection, transaction, owner, additionalSigners)
return mangoSrmAccount
}
async withdrawSrm(
connection: Connection,
programId: PublicKey,
mangoGroup: MangoGroup,
marginAccount: MarginAccount,
mangoSrmAccount: MangoSrmAccount,
owner: Account,
srmAccount: PublicKey,
@ -808,7 +832,7 @@ export class MangoClient {
const keys = [
{ isSigner: false, isWritable: true, pubkey: mangoGroup.publicKey },
{ isSigner: false, isWritable: true, pubkey: marginAccount.publicKey },
{ isSigner: false, isWritable: true, pubkey: mangoSrmAccount.publicKey },
{ isSigner: true, isWritable: false, pubkey: owner.publicKey },
{ isSigner: false, isWritable: true, pubkey: srmAccount },
{ isSigner: false, isWritable: true, pubkey: mangoGroup.srmVault },
@ -930,6 +954,7 @@ export class MangoClient {
return await this.sendTransaction(connection, transaction, owner, additionalSigners)
}
}
async settleFunds(
connection: Connection,
programId: PublicKey,
@ -1143,5 +1168,48 @@ export class MangoClient {
return marginAccounts
}
async getMangoSrmAccount(
connection: Connection,
mangoSrmAccountPk: PublicKey
): Promise<MangoSrmAccount> {
const acc = await connection.getAccountInfo(mangoSrmAccountPk, 'singleGossip')
return new MangoSrmAccount(mangoSrmAccountPk, MangoSrmAccountLayout.decode(acc == null ? undefined : acc.data))
}
async getMangoSrmAccountsForOwner(
connection: Connection,
programId: PublicKey,
mangoGroup: MangoGroup,
owner: Account | Wallet
): Promise<MangoSrmAccount[]> {
const filters = [
{
memcmp: {
offset: MangoSrmAccountLayout.offsetOf('mangoGroup'),
bytes: mangoGroup.publicKey.toBase58(),
},
},
{
memcmp: {
offset: MangoSrmAccountLayout.offsetOf('owner'),
bytes: owner.publicKey.toBase58(),
}
},
{
dataSize: MangoSrmAccountLayout.span,
},
];
const accounts = await getFilteredProgramAccounts(connection, programId, filters);
const srmAccounts = accounts.map(
({ publicKey, accountInfo }) =>
new MangoSrmAccount(publicKey, MangoSrmAccountLayout.decode(accountInfo == null ? undefined : accountInfo.data))
)
return srmAccounts
}
}

View File

@ -41,15 +41,15 @@
]
},
"BTC_ETH_USDT": {
"mango_group_pk": "5faCLrkbaLhp4kDUiwkEZP2CsH6pHFRV8NSC8kgDf4bm",
"mango_group_pk": "CAsLeiWN4S2Q8SAcbo6P7nLUaxs4urVSpzrHpgZLPGLL",
"mint_pks": [
"C6kYXcaRUMqeBF5fhg165RWU7AnpT9z92fvKNoMqjmz6",
"8p968u9m7jZzKSsqxFDqki69MjqdFkwPM9FN4AN8hvHR",
"7tSPGVhneTBWZjLGJGZb9V2UntC7T98cwtSLtgcXjeSs"
],
"oracle_pks": [
"3iQqi9nBREjVvKtVWd44Jcbvs39CDAe6zSd613QzxuPE",
"5qxMJFJXB42j3kKo3FbTughREjziottXHcgLnjCNwjEs"
"EHasrbBk5mFnTYPjmdNzDoa7cEBH3yN8D4DLJn7Q41hY",
"3ynBi9nQyKoEJwC47cmXviLSgHaaXQBKRxukatYYLN1Y"
],
"spot_market_pks": [
"ELXP9wTE4apvK9sxAqtCtMidbAvJJDrNVg4wL6jqQEBA",
@ -59,25 +59,25 @@
"BTC/USDT": "ELXP9wTE4apvK9sxAqtCtMidbAvJJDrNVg4wL6jqQEBA",
"ETH/USDT": "97mbLfi4S56y5Vg2LCF4Z7ru8jD1QjHa5SH3eyFYrMdg"
},
"srm_vault_pk": "Bf9VhCut3mfkz2xbVs4N7Q2ddLoRxLxoGNakBAWFfKDJ",
"srm_vault_pk": "BnYohERJjx6sADWe1P3n5cwr2JJFz3HaBidqspDMezm6",
"symbols": {
"BTC": "C6kYXcaRUMqeBF5fhg165RWU7AnpT9z92fvKNoMqjmz6",
"ETH": "8p968u9m7jZzKSsqxFDqki69MjqdFkwPM9FN4AN8hvHR",
"USDT": "7tSPGVhneTBWZjLGJGZb9V2UntC7T98cwtSLtgcXjeSs"
},
"vault_pks": [
"EP1oJGFhYTR6Vfr3zGrRySiwcCcNiJRkppBreVsuaLR9",
"AsyDJrq2TRewDGa4hiyWoHF6R4Los5y7yt5XjxergNzM",
"5CHhWpkWCevB3CDnf7jSVV7vagRq3CpHv6vZ48LNYLsP"
"DKh18z5VYwGNergmKztewEBAe6SCQXaMuJkYVDQhWcyY",
"3vyfCDP4EyZPVHMHgJLhFjZrYdQpv5cKrcdKjm8KAFKQ",
"BMfn9XdjGQUpdZRLS8TEf1oX9n5cDhgUxJBuqUz7E3k9"
]
}
},
"mango_program_id": "Ahf4Q9U9sh86YzRHNkR6u94iRacd9XL2zvUtp2iN94wb",
"mango_program_id": "JD3bq9hGdy38PuWQ4h2YJpELmHVGPPfFSuFkpzAd9zfu",
"oracles": {
"BTC/USDC": "3iQqi9nBREjVvKtVWd44Jcbvs39CDAe6zSd613QzxuPE",
"BTC/USDT": "3iQqi9nBREjVvKtVWd44Jcbvs39CDAe6zSd613QzxuPE",
"ETH/USDC": "5qxMJFJXB42j3kKo3FbTughREjziottXHcgLnjCNwjEs",
"ETH/USDT": "5qxMJFJXB42j3kKo3FbTughREjziottXHcgLnjCNwjEs"
"BTC/USDC": "EHasrbBk5mFnTYPjmdNzDoa7cEBH3yN8D4DLJn7Q41hY",
"BTC/USDT": "EHasrbBk5mFnTYPjmdNzDoa7cEBH3yN8D4DLJn7Q41hY",
"ETH/USDC": "3ynBi9nQyKoEJwC47cmXviLSgHaaXQBKRxukatYYLN1Y",
"ETH/USDT": "3ynBi9nQyKoEJwC47cmXviLSgHaaXQBKRxukatYYLN1Y"
},
"spot_markets": {
"BTC/USDC": "FKysSZkCCh41G1SCxpE7Cb7eaLofYBhEneLzHFz6JvjH",

View File

@ -1,5 +1,10 @@
import { MangoClient, MangoGroup } from './client';
import IDS from './ids.json';
import { Account, Connection, PublicKey } from '@solana/web3.js';
import { Aggregator } from './schema';
import { homedir } from 'os';
import fs from 'fs';
import { sleep } from './utils';
export { MangoClient, MangoGroup, MarginAccount } from './client';
export { MangoIndexLayout, MarginAccountLayout, MangoGroupLayout } from './layout';
@ -7,3 +12,45 @@ export * from './layout';
export * from './utils'
export { IDS }
// async function tests() {
// const cluster = "devnet";
// const client = new MangoClient();
// const clusterIds = IDS[cluster]
//
// const connection = new Connection(IDS.cluster_urls[cluster], 'singleGossip')
// const mangoGroupPk = new PublicKey(clusterIds.mango_groups['BTC_ETH_USDT'].mango_group_pk);
// const mangoProgramId = new PublicKey(clusterIds.mango_program_id);
//
// const keyPairPath = process.env.KEYPAIR || homedir() + '/.config/solana/id.json'
// const payer = new Account(JSON.parse(fs.readFileSync(keyPairPath, 'utf-8')))
//
//
// async function testSolink() {
//
// const oraclePk = new PublicKey(IDS[cluster].oracles['ETH/USDT'])
// const agg = await Aggregator.loadWithConnection(oraclePk, connection)
//
// // const agg = await Aggregator.loadWithConnection(oraclePk, connection)
// console.log(agg.answer.median.toNumber(), agg.answer.updatedAt.toNumber(), agg.round.id.toNumber())
//
// }
//
// async function testDepositSrm() {
// const srmVaultPk = new PublicKey(clusterIds['mango_groups']['BTC_ETH_USDT']['srm_vault_pk'])
// const mangoGroup = await client.getMangoGroup(connection, mangoGroupPk, srmVaultPk)
// const srmAccountPk = new PublicKey("6utvndL8EEjpwK5QVtguErncQEPVbkuyABmXu6FeygeV")
// const mangoSrmAccountPk = await client.depositSrm(connection, mangoProgramId, mangoGroup, payer, srmAccountPk, 100)
// console.log(mangoSrmAccountPk.toBase58())
// await sleep(2000)
// const mangoSrmAccount = await client.getMangoSrmAccount(connection, mangoSrmAccountPk)
// const txid = await client.withdrawSrm(connection, mangoProgramId, mangoGroup, mangoSrmAccount, payer, srmAccountPk, 50)
// console.log('success', txid)
// }
//
// // await testSolink()
// testDepositSrm()
// }
//
// tests()

View File

@ -111,6 +111,7 @@ const ACCOUNT_FLAGS_LAYOUT = new WideBits(undefined);
ACCOUNT_FLAGS_LAYOUT.addBoolean('Initialized');
ACCOUNT_FLAGS_LAYOUT.addBoolean('MangoGroup');
ACCOUNT_FLAGS_LAYOUT.addBoolean('MarginAccount');
ACCOUNT_FLAGS_LAYOUT.addBoolean('MangoSrmAccount');
export function accountFlagsLayout(property = 'accountFlags') {
return ACCOUNT_FLAGS_LAYOUT.replicate(property); // TODO: when ts check is on, replicate throws error, doesn't compile
@ -153,8 +154,14 @@ export const MarginAccountLayout = struct([
seq(U64F64(), NUM_TOKENS, 'deposits'),
seq(U64F64(), NUM_TOKENS, 'borrows'),
seq(publicKeyLayout(), NUM_MARKETS, 'openOrders'),
u64('srmBalance')
seq(publicKeyLayout(), NUM_MARKETS, 'openOrders')
]);
export const MangoSrmAccountLayout = struct([
accountFlagsLayout('accountFlags'),
publicKeyLayout('mangoGroup'),
publicKeyLayout('owner'),
u64('amount')
]);