Added Account.build_redeem_pnl_instructions_for_market() to build redeem instructions.
* Simpler access is through Account.redeem_pnl_for_perp_market() and Account.redeem_all_perp_pnl() * Added redeem-pnl command to allow redemption via command line and to show how to exercise these methods.
This commit is contained in:
parent
66446fa2c9
commit
b5916fcb50
|
@ -0,0 +1,97 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import os
|
||||||
|
import os.path
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from solana.publickey import PublicKey
|
||||||
|
|
||||||
|
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
|
||||||
|
import mango # nopep8
|
||||||
|
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description="redeems PnL for a Mango account")
|
||||||
|
mango.ContextBuilder.add_command_line_parameters(parser)
|
||||||
|
mango.Wallet.add_command_line_parameters(parser)
|
||||||
|
parser.add_argument(
|
||||||
|
"--market", type=str, help="perp market symbol to redeem PnL (e.g. ETH-PERP)"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--all",
|
||||||
|
action="store_true",
|
||||||
|
default=False,
|
||||||
|
help="redeem all MNGO in all perp markets in the account",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--account-address",
|
||||||
|
type=PublicKey,
|
||||||
|
help="address of the specific account to use, if more than one available",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--dry-run",
|
||||||
|
action="store_true",
|
||||||
|
default=False,
|
||||||
|
help="runs as read-only and does not perform any transactions",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--wait",
|
||||||
|
action="store_true",
|
||||||
|
default=False,
|
||||||
|
help="wait until the transactions are confirmed",
|
||||||
|
)
|
||||||
|
args: argparse.Namespace = mango.parse_args(parser)
|
||||||
|
|
||||||
|
if (not args.all) and (args.market is None):
|
||||||
|
raise Exception(
|
||||||
|
"Must specify either an individual market (using --market) or use --all for all markets"
|
||||||
|
)
|
||||||
|
|
||||||
|
with mango.ContextBuilder.from_command_line_parameters(args) as context:
|
||||||
|
wallet = mango.Wallet.from_command_line_parameters_or_raise(args)
|
||||||
|
|
||||||
|
group = mango.Group.load(context, context.group_address)
|
||||||
|
cache = mango.Cache.load(context, group.cache)
|
||||||
|
account = mango.Account.load_for_owner_by_address(
|
||||||
|
context, wallet.address, group, args.account_address
|
||||||
|
)
|
||||||
|
|
||||||
|
if args.all:
|
||||||
|
signatures = account.redeem_all_perp_pnl(context, wallet, group, cache)
|
||||||
|
else:
|
||||||
|
group_slots = [
|
||||||
|
gs
|
||||||
|
for gs in group.slots
|
||||||
|
if mango.Market.symbols_match(gs.perp_market_symbol, args.market)
|
||||||
|
]
|
||||||
|
if len(group_slots) != 1:
|
||||||
|
raise Exception(
|
||||||
|
f"Could not find perp market slot with symbol '{args.market}'"
|
||||||
|
)
|
||||||
|
|
||||||
|
group_slot = group_slots[0]
|
||||||
|
slot = account.slots[group_slot.index]
|
||||||
|
perp_market_cache = group.perp_market_cache_from_cache(
|
||||||
|
cache, slot.base_instrument
|
||||||
|
)
|
||||||
|
if perp_market_cache is None:
|
||||||
|
raise Exception(
|
||||||
|
f"Could not find perp market cache for {slot.base_instrument.symbol}"
|
||||||
|
)
|
||||||
|
|
||||||
|
price = group.token_price_from_cache(cache, slot.base_instrument)
|
||||||
|
signatures = account.redeem_pnl_for_perp_market(
|
||||||
|
context, wallet, group, slot, perp_market_cache, price
|
||||||
|
)
|
||||||
|
|
||||||
|
if args.wait:
|
||||||
|
mango.output("Waiting on transaction signatures:")
|
||||||
|
mango.output(mango.indent_collection_as_str(signatures, 1))
|
||||||
|
results = mango.WebSocketTransactionMonitor.wait_for_all(
|
||||||
|
context.client.cluster_ws_url, signatures
|
||||||
|
)
|
||||||
|
mango.output("Transaction results:")
|
||||||
|
mango.output(mango.indent_collection_as_str(results, 1))
|
||||||
|
else:
|
||||||
|
mango.output("Transaction signatures:")
|
||||||
|
mango.output(mango.indent_collection_as_str(signatures, 1))
|
|
@ -105,6 +105,12 @@ from .instructions import (
|
||||||
from .instructions import (
|
from .instructions import (
|
||||||
build_mango_set_referrer_memory_instructions as build_mango_set_referrer_memory_instructions,
|
build_mango_set_referrer_memory_instructions as build_mango_set_referrer_memory_instructions,
|
||||||
)
|
)
|
||||||
|
from .instructions import (
|
||||||
|
build_mango_settle_fees_instructions as build_mango_settle_fees_instructions,
|
||||||
|
)
|
||||||
|
from .instructions import (
|
||||||
|
build_mango_settle_pnl_instructions as build_mango_settle_pnl_instructions,
|
||||||
|
)
|
||||||
from .instructions import (
|
from .instructions import (
|
||||||
build_mango_update_funding_instructions as build_mango_update_funding_instructions,
|
build_mango_update_funding_instructions as build_mango_update_funding_instructions,
|
||||||
)
|
)
|
||||||
|
|
207
mango/account.py
207
mango/account.py
|
@ -30,6 +30,8 @@ from .encoding import encode_key
|
||||||
from .group import Group, GroupSlot, GroupSlotPerpMarket
|
from .group import Group, GroupSlot, GroupSlotPerpMarket
|
||||||
from .instructions import (
|
from .instructions import (
|
||||||
build_mango_deposit_instructions,
|
build_mango_deposit_instructions,
|
||||||
|
build_mango_settle_fees_instructions,
|
||||||
|
build_mango_settle_pnl_instructions,
|
||||||
build_mango_withdraw_instructions,
|
build_mango_withdraw_instructions,
|
||||||
)
|
)
|
||||||
from .instrumentvalue import InstrumentValue
|
from .instrumentvalue import InstrumentValue
|
||||||
|
@ -39,6 +41,7 @@ from .observables import Disposable
|
||||||
from .openorders import OpenOrders
|
from .openorders import OpenOrders
|
||||||
from .orders import Side
|
from .orders import Side
|
||||||
from .perpaccount import PerpAccount
|
from .perpaccount import PerpAccount
|
||||||
|
from .perpmarketdetails import PerpMarketDetails
|
||||||
from .perpopenorders import PerpOpenOrders
|
from .perpopenorders import PerpOpenOrders
|
||||||
from .placedorder import PlacedOrder
|
from .placedorder import PlacedOrder
|
||||||
from .tokens import Instrument, Token
|
from .tokens import Instrument, Token
|
||||||
|
@ -167,6 +170,15 @@ class AccountSlot:
|
||||||
def raw_net_value(self) -> Decimal:
|
def raw_net_value(self) -> Decimal:
|
||||||
return self.raw_deposit - self.raw_borrow
|
return self.raw_deposit - self.raw_borrow
|
||||||
|
|
||||||
|
def pnl(
|
||||||
|
self,
|
||||||
|
perp_market_cache: PerpMarketCache,
|
||||||
|
price: InstrumentValue,
|
||||||
|
) -> Decimal:
|
||||||
|
if self.perp_account is None:
|
||||||
|
return Decimal(0)
|
||||||
|
return self.perp_account.pnl(perp_market_cache, price)
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
perp_account: str = "None"
|
perp_account: str = "None"
|
||||||
if self.perp_account is not None:
|
if self.perp_account is not None:
|
||||||
|
@ -697,6 +709,201 @@ class Account(AddressableAccount):
|
||||||
all_instructions = signers + create_ata + withdraw
|
all_instructions = signers + create_ata + withdraw
|
||||||
return all_instructions.execute(context)
|
return all_instructions.execute(context)
|
||||||
|
|
||||||
|
def redeem_all_perp_pnl(
|
||||||
|
self,
|
||||||
|
context: Context,
|
||||||
|
wallet: Wallet,
|
||||||
|
group: Group,
|
||||||
|
cache: Cache,
|
||||||
|
) -> typing.Sequence[str]:
|
||||||
|
all_accounts = Account.load_all(context, group)
|
||||||
|
self._logger.debug(f"Fetched {len(all_accounts)} Mango Accounts.")
|
||||||
|
|
||||||
|
instructions = CombinableInstructions.from_wallet(wallet)
|
||||||
|
for slot in self.slots:
|
||||||
|
if (slot.perp_account is not None) and (not slot.perp_account.empty):
|
||||||
|
self._logger.debug(
|
||||||
|
f"Redeeming perp account for {slot.base_instrument.symbol}"
|
||||||
|
)
|
||||||
|
price = group.token_price_from_cache(cache, slot.base_instrument)
|
||||||
|
perp_market_cache = group.perp_market_cache_from_cache(
|
||||||
|
cache, slot.base_instrument
|
||||||
|
)
|
||||||
|
if perp_market_cache is None:
|
||||||
|
raise Exception(
|
||||||
|
f"Could not load perp market cache for {slot.base_instrument.symbol} despite having a perp account for it."
|
||||||
|
)
|
||||||
|
|
||||||
|
instructions += self.build_redeem_pnl_instructions_for_market(
|
||||||
|
context, group, all_accounts, slot, perp_market_cache, price
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self._logger.debug(f"No perp account for {slot.base_instrument.symbol}")
|
||||||
|
|
||||||
|
self._logger.debug(
|
||||||
|
f"Have {len(instructions.instructions)} instructions to send for all perp markets."
|
||||||
|
)
|
||||||
|
|
||||||
|
return instructions.execute(context)
|
||||||
|
|
||||||
|
def redeem_pnl_for_perp_market(
|
||||||
|
self,
|
||||||
|
context: Context,
|
||||||
|
wallet: Wallet,
|
||||||
|
group: Group,
|
||||||
|
slot: AccountSlot,
|
||||||
|
perp_market_cache: PerpMarketCache,
|
||||||
|
price: InstrumentValue,
|
||||||
|
) -> typing.Sequence[str]:
|
||||||
|
group_slot = group.slots[slot.index]
|
||||||
|
if group_slot.perp_market is None:
|
||||||
|
return []
|
||||||
|
|
||||||
|
if slot.perp_account is None:
|
||||||
|
return []
|
||||||
|
|
||||||
|
pnl = slot.perp_account.pnl(perp_market_cache, price)
|
||||||
|
if pnl == 0:
|
||||||
|
# No PnL to redeem
|
||||||
|
return []
|
||||||
|
|
||||||
|
self._logger.debug(
|
||||||
|
f"Trying to settle {pnl:,.8f} {group_slot.quote_token_bank.token.symbol}."
|
||||||
|
)
|
||||||
|
|
||||||
|
instructions = CombinableInstructions.from_wallet(wallet)
|
||||||
|
|
||||||
|
all_accounts = Account.load_all(context, group)
|
||||||
|
self._logger.debug(f"Fetched {len(all_accounts)} Mango Accounts.")
|
||||||
|
|
||||||
|
instructions += self.build_redeem_pnl_instructions_for_market(
|
||||||
|
context, group, all_accounts, slot, perp_market_cache, price
|
||||||
|
)
|
||||||
|
|
||||||
|
return instructions.execute(context)
|
||||||
|
|
||||||
|
def build_redeem_pnl_instructions_for_market(
|
||||||
|
self,
|
||||||
|
context: Context,
|
||||||
|
group: Group,
|
||||||
|
all_accounts: typing.Sequence["Account"],
|
||||||
|
slot: AccountSlot,
|
||||||
|
perp_market_cache: PerpMarketCache,
|
||||||
|
price: InstrumentValue,
|
||||||
|
) -> CombinableInstructions:
|
||||||
|
group_slot = group.slots[slot.index]
|
||||||
|
if group_slot.perp_market is None:
|
||||||
|
self._logger.debug(f"No perp market for {slot.base_instrument.symbol}")
|
||||||
|
return CombinableInstructions.empty()
|
||||||
|
|
||||||
|
if slot.perp_account is None:
|
||||||
|
self._logger.debug(f"No perp account for {slot.base_instrument.symbol}")
|
||||||
|
return CombinableInstructions.empty()
|
||||||
|
|
||||||
|
pnl = slot.perp_account.pnl(perp_market_cache, price)
|
||||||
|
if pnl == 0:
|
||||||
|
# No PnL to redeem
|
||||||
|
return CombinableInstructions.empty()
|
||||||
|
|
||||||
|
self._logger.debug(
|
||||||
|
f"Trying to settle {pnl:,.8f} {group_slot.quote_token_bank.token.symbol} on {group_slot.perp_market_symbol}."
|
||||||
|
)
|
||||||
|
|
||||||
|
pnl_is_negative: bool = False
|
||||||
|
if pnl < 0:
|
||||||
|
pnl_is_negative = True
|
||||||
|
|
||||||
|
quote_root_bank = group.shared_quote.ensure_root_bank(context)
|
||||||
|
|
||||||
|
instructions = CombinableInstructions.empty()
|
||||||
|
|
||||||
|
# If negative, build settle fees instruction
|
||||||
|
if pnl_is_negative:
|
||||||
|
perp_market = PerpMarketDetails.load(
|
||||||
|
context, group_slot.perp_market.address, group
|
||||||
|
)
|
||||||
|
quote_node_bank = quote_root_bank.pick_node_bank(context)
|
||||||
|
self._logger.debug("Adding SettleFees instruction.")
|
||||||
|
instructions += build_mango_settle_fees_instructions(
|
||||||
|
context,
|
||||||
|
group,
|
||||||
|
perp_market,
|
||||||
|
self,
|
||||||
|
quote_root_bank,
|
||||||
|
quote_node_bank,
|
||||||
|
)
|
||||||
|
|
||||||
|
all_accounts_except_self = filter(
|
||||||
|
lambda acc: acc.address != self.address,
|
||||||
|
all_accounts,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Filter out all accounts with zero or same-signed PnL
|
||||||
|
if pnl_is_negative:
|
||||||
|
filtered = list(
|
||||||
|
filter(
|
||||||
|
lambda acc: acc.slots[slot.index].pnl(perp_market_cache, price) > 0,
|
||||||
|
all_accounts_except_self,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
filtered = list(
|
||||||
|
filter(
|
||||||
|
lambda acc: acc.slots[slot.index].pnl(perp_market_cache, price) < 0,
|
||||||
|
all_accounts_except_self,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self._logger.debug(
|
||||||
|
f"Removed irrelevent accounts - now have {len(filtered)} Mango Accounts."
|
||||||
|
)
|
||||||
|
|
||||||
|
# Now we have a filtered list, sort it
|
||||||
|
sorted_accounts = sorted(
|
||||||
|
filtered,
|
||||||
|
key=lambda acc: acc.slots[slot.index].pnl(perp_market_cache, price),
|
||||||
|
reverse=pnl_is_negative,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add 5% to our collection so we're sure we're sending enough accounts even if
|
||||||
|
# the price has shifted. (This doesn't affect the redemption value.)
|
||||||
|
target_pnl = (pnl * Decimal("1.01")).copy_abs()
|
||||||
|
|
||||||
|
# Loop over top N accounts until we have redeemed enough or we run out of accounts.
|
||||||
|
collected = Decimal(0)
|
||||||
|
for other in sorted_accounts:
|
||||||
|
other_perp_account = other.slots[slot.index].perp_account
|
||||||
|
if other_perp_account is not None:
|
||||||
|
other_pnl = other_perp_account.pnl(perp_market_cache, price)
|
||||||
|
|
||||||
|
# Build instruction
|
||||||
|
instructions += build_mango_settle_pnl_instructions(
|
||||||
|
context,
|
||||||
|
group,
|
||||||
|
group_slot,
|
||||||
|
self,
|
||||||
|
other,
|
||||||
|
quote_root_bank,
|
||||||
|
)
|
||||||
|
|
||||||
|
collected += other_pnl
|
||||||
|
self._logger.debug(
|
||||||
|
f"Collected {collected:,.8f} out of {target_pnl:,.8f} - added {other_pnl:,.8f} from {other.address}"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add 1% to our collection so we're sure we're sending enough accounts even if
|
||||||
|
# the price has shifted. (This doesn't affect the redemption value.)
|
||||||
|
if collected.copy_abs() > target_pnl:
|
||||||
|
self._logger.debug(
|
||||||
|
f"Done. Have collected {collected:,.8f} to redeem against."
|
||||||
|
)
|
||||||
|
break
|
||||||
|
|
||||||
|
self._logger.debug(
|
||||||
|
f"Have {len(instructions.instructions)} instructions to send for {group_slot.perp_market_symbol}."
|
||||||
|
)
|
||||||
|
|
||||||
|
return instructions
|
||||||
|
|
||||||
def slot_by_instrument_or_none(
|
def slot_by_instrument_or_none(
|
||||||
self, instrument: Instrument
|
self, instrument: Instrument
|
||||||
) -> typing.Optional[AccountSlot]:
|
) -> typing.Optional[AccountSlot]:
|
||||||
|
|
|
@ -108,6 +108,7 @@ class IGroupSlot(typing.Protocol):
|
||||||
class IGroup(typing.Protocol):
|
class IGroup(typing.Protocol):
|
||||||
cache: PublicKey
|
cache: PublicKey
|
||||||
signer_key: PublicKey
|
signer_key: PublicKey
|
||||||
|
fees_vault: PublicKey
|
||||||
shared_quote: TokenBank
|
shared_quote: TokenBank
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -1712,3 +1713,81 @@ def build_mango_update_funding_instructions(
|
||||||
data=layouts.UPDATE_FUNDING.build({}),
|
data=layouts.UPDATE_FUNDING.build({}),
|
||||||
)
|
)
|
||||||
return CombinableInstructions(signers=[], instructions=[instruction])
|
return CombinableInstructions(signers=[], instructions=[instruction])
|
||||||
|
|
||||||
|
|
||||||
|
def build_mango_settle_fees_instructions(
|
||||||
|
context: Context,
|
||||||
|
group: IGroup,
|
||||||
|
perp_market_details: PerpMarketDetails,
|
||||||
|
account: IAccount,
|
||||||
|
root_bank: RootBank,
|
||||||
|
node_bank: NodeBank,
|
||||||
|
) -> CombinableInstructions:
|
||||||
|
# /// Take an account that has losses in the selected perp market to account for fees_accrued
|
||||||
|
# ///
|
||||||
|
# /// Accounts expected: 10
|
||||||
|
# /// 0. `[]` mango_group_ai - MangoGroup
|
||||||
|
# /// 1. `[]` mango_cache_ai - MangoCache
|
||||||
|
# /// 2. `[writable]` perp_market_ai - PerpMarket
|
||||||
|
# /// 3. `[writable]` mango_account_ai - MangoAccount
|
||||||
|
# /// 4. `[]` root_bank_ai - RootBank
|
||||||
|
# /// 5. `[writable]` node_bank_ai - NodeBank
|
||||||
|
# /// 6. `[writable]` bank_vault_ai - ?
|
||||||
|
# /// 7. `[writable]` fees_vault_ai - fee vault owned by mango DAO token governance
|
||||||
|
# /// 8. `[]` signer_ai - Group Signer Account
|
||||||
|
# /// 9. `[]` token_prog_ai - Token Program Account
|
||||||
|
instruction = TransactionInstruction(
|
||||||
|
keys=[
|
||||||
|
AccountMeta(is_signer=False, is_writable=False, pubkey=group.address),
|
||||||
|
AccountMeta(is_signer=False, is_writable=False, pubkey=group.cache),
|
||||||
|
AccountMeta(
|
||||||
|
is_signer=False, is_writable=True, pubkey=perp_market_details.address
|
||||||
|
),
|
||||||
|
AccountMeta(is_signer=False, is_writable=True, pubkey=account.address),
|
||||||
|
AccountMeta(is_signer=False, is_writable=False, pubkey=root_bank.address),
|
||||||
|
AccountMeta(is_signer=False, is_writable=True, pubkey=node_bank.address),
|
||||||
|
AccountMeta(is_signer=False, is_writable=True, pubkey=node_bank.vault),
|
||||||
|
AccountMeta(is_signer=False, is_writable=True, pubkey=group.fees_vault),
|
||||||
|
AccountMeta(is_signer=False, is_writable=False, pubkey=group.signer_key),
|
||||||
|
AccountMeta(is_signer=False, is_writable=False, pubkey=TOKEN_PROGRAM_ID),
|
||||||
|
],
|
||||||
|
program_id=context.mango_program_address,
|
||||||
|
data=layouts.SETTLE_FEES.build({}),
|
||||||
|
)
|
||||||
|
return CombinableInstructions(signers=[], instructions=[instruction])
|
||||||
|
|
||||||
|
|
||||||
|
def build_mango_settle_pnl_instructions(
|
||||||
|
context: Context,
|
||||||
|
group: IGroup,
|
||||||
|
group_slot: IGroupSlot,
|
||||||
|
account_a: IAccount,
|
||||||
|
account_b: IAccount,
|
||||||
|
root_bank: RootBank,
|
||||||
|
) -> CombinableInstructions:
|
||||||
|
# /// Take two MangoAccounts and settle profits and losses between them for a perp market
|
||||||
|
# ///
|
||||||
|
# /// Accounts expected (6):
|
||||||
|
# const keys = [
|
||||||
|
# { isSigner: false, isWritable: false, pubkey: mangoGroupPk },
|
||||||
|
# { isSigner: false, isWritable: true, pubkey: mangoAccountAPk },
|
||||||
|
# { isSigner: false, isWritable: true, pubkey: mangoAccountBPk },
|
||||||
|
# { isSigner: false, isWritable: false, pubkey: mangoCachePk },
|
||||||
|
# { isSigner: false, isWritable: false, pubkey: rootBankPk },
|
||||||
|
# { isSigner: false, isWritable: true, pubkey: nodeBankPk },
|
||||||
|
# ];
|
||||||
|
instruction = TransactionInstruction(
|
||||||
|
keys=[
|
||||||
|
AccountMeta(is_signer=False, is_writable=False, pubkey=group.address),
|
||||||
|
AccountMeta(is_signer=False, is_writable=True, pubkey=account_a.address),
|
||||||
|
AccountMeta(is_signer=False, is_writable=True, pubkey=account_b.address),
|
||||||
|
AccountMeta(is_signer=False, is_writable=False, pubkey=group.cache),
|
||||||
|
AccountMeta(is_signer=False, is_writable=False, pubkey=root_bank.address),
|
||||||
|
AccountMeta(
|
||||||
|
is_signer=False, is_writable=True, pubkey=root_bank.node_banks[0]
|
||||||
|
),
|
||||||
|
],
|
||||||
|
program_id=context.mango_program_address,
|
||||||
|
data=layouts.SETTLE_PNL.build({"market_index": group_slot.index}),
|
||||||
|
)
|
||||||
|
return CombinableInstructions(signers=[], instructions=[instruction])
|
||||||
|
|
|
@ -1584,6 +1584,32 @@ UPDATE_ROOT_BANK = construct.Struct(
|
||||||
"variant" / construct.Const(21, construct.BytesInteger(4, swapped=True)),
|
"variant" / construct.Const(21, construct.BytesInteger(4, swapped=True)),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# /// Take two MangoAccounts and settle profits and losses between them for a perp market
|
||||||
|
# ///
|
||||||
|
# /// Accounts expected (6):
|
||||||
|
SETTLE_PNL = construct.Struct(
|
||||||
|
"variant" / construct.Const(22, construct.BytesInteger(4, swapped=True)),
|
||||||
|
"market_index" / DecimalAdapter(),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# /// Take an account that has losses in the selected perp market to account for fees_accrued
|
||||||
|
# ///
|
||||||
|
# /// Accounts expected: 10
|
||||||
|
# /// 0. `[]` mango_group_ai - MangoGroup
|
||||||
|
# /// 1. `[]` mango_cache_ai - MangoCache
|
||||||
|
# /// 2. `[writable]` perp_market_ai - PerpMarket
|
||||||
|
# /// 3. `[writable]` mango_account_ai - MangoAccount
|
||||||
|
# /// 4. `[]` root_bank_ai - RootBank
|
||||||
|
# /// 5. `[writable]` node_bank_ai - NodeBank
|
||||||
|
# /// 6. `[writable]` bank_vault_ai - ?
|
||||||
|
# /// 7. `[writable]` fees_vault_ai - fee vault owned by mango DAO token governance
|
||||||
|
# /// 8. `[]` signer_ai - Group Signer Account
|
||||||
|
# /// 9. `[]` token_prog_ai - Token Program Account
|
||||||
|
SETTLE_FEES = construct.Struct(
|
||||||
|
"variant" / construct.Const(29, construct.BytesInteger(4, swapped=True))
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# /// Redeem the mngo_accrued in a PerpAccount for MNGO in MangoAccount deposits
|
# /// Redeem the mngo_accrued in a PerpAccount for MNGO in MangoAccount deposits
|
||||||
# ///
|
# ///
|
||||||
|
@ -1830,14 +1856,14 @@ InstructionParsersByVariant = {
|
||||||
19: SETTLE_FUNDS, # SETTLE_FUNDS,
|
19: SETTLE_FUNDS, # SETTLE_FUNDS,
|
||||||
20: CANCEL_SPOT_ORDER, # CANCEL_SPOT_ORDER,
|
20: CANCEL_SPOT_ORDER, # CANCEL_SPOT_ORDER,
|
||||||
21: UPDATE_ROOT_BANK, # UPDATE_ROOT_BANK,
|
21: UPDATE_ROOT_BANK, # UPDATE_ROOT_BANK,
|
||||||
22: UNSPECIFIED, # SETTLE_PNL,
|
22: SETTLE_PNL, # SETTLE_PNL,
|
||||||
23: UNSPECIFIED, # SETTLE_BORROW,
|
23: UNSPECIFIED, # SETTLE_BORROW,
|
||||||
24: UNSPECIFIED, # FORCE_CANCEL_SPOT_ORDERS,
|
24: UNSPECIFIED, # FORCE_CANCEL_SPOT_ORDERS,
|
||||||
25: UNSPECIFIED, # FORCE_CANCEL_PERP_ORDERS,
|
25: UNSPECIFIED, # FORCE_CANCEL_PERP_ORDERS,
|
||||||
26: UNSPECIFIED, # LIQUIDATE_TOKEN_AND_TOKEN,
|
26: UNSPECIFIED, # LIQUIDATE_TOKEN_AND_TOKEN,
|
||||||
27: UNSPECIFIED, # LIQUIDATE_TOKEN_AND_PERP,
|
27: UNSPECIFIED, # LIQUIDATE_TOKEN_AND_PERP,
|
||||||
28: UNSPECIFIED, # LIQUIDATE_PERP_MARKET,
|
28: UNSPECIFIED, # LIQUIDATE_PERP_MARKET,
|
||||||
29: UNSPECIFIED, # SETTLE_FEES,
|
29: SETTLE_FEES, # SETTLE_FEES,
|
||||||
30: UNSPECIFIED, # RESOLVE_PERP_BANKRUPTCY,
|
30: UNSPECIFIED, # RESOLVE_PERP_BANKRUPTCY,
|
||||||
31: UNSPECIFIED, # RESOLVE_TOKEN_BANKRUPTCY,
|
31: UNSPECIFIED, # RESOLVE_TOKEN_BANKRUPTCY,
|
||||||
32: UNSPECIFIED, # INIT_SPOT_OPEN_ORDERS,
|
32: UNSPECIFIED, # INIT_SPOT_OPEN_ORDERS,
|
||||||
|
|
Loading…
Reference in New Issue