diff --git a/bin/account-scout b/bin/account-scout index 18b27ae..37e941e 100755 --- a/bin/account-scout +++ b/bin/account-scout @@ -11,8 +11,6 @@ from solana.publickey import PublicKey sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) import mango # nopep8 -# We explicitly want argument parsing to be outside the main try-except block because some arguments -# (like --help) will cause an exit, which our except: block traps. parser = argparse.ArgumentParser( description="Run the Account Scout to display problems and information about an account." ) diff --git a/bin/airdrop b/bin/airdrop index c9df4c7..fe70519 100755 --- a/bin/airdrop +++ b/bin/airdrop @@ -75,11 +75,7 @@ args: argparse.Namespace = mango.parse_args(parser) with mango.ContextBuilder.from_command_line_parameters(args) as context: wallet = mango.Wallet.from_command_line_parameters_or_raise(args) - - instrument = context.instrument_lookup.find_by_symbol(args.symbol) - if instrument is None: - raise Exception(f"Could not find instrument with symbol '{args.symbol}'.") - token: mango.Token = mango.Token.ensure(instrument) + token: mango.Token = mango.token(context, args.symbol) # The loaded `token` variable will be from the `context`, so if it's SOL it will be # 'wrapped SOL' with a 1112 mint address, not regular SOL with a 1111 mint address. diff --git a/bin/balance-account b/bin/balance-account index bee4718..281a991 100755 --- a/bin/balance-account +++ b/bin/balance-account @@ -83,7 +83,7 @@ with mango.ContextBuilder.from_command_line_parameters(args) as context: ops = mango.operations( context, wallet, account, market_symbol, args.dry_run ) - orderbook = ops.fetch_orderbook(context) + orderbook = ops.load_orderbook() price = orderbook.mid_price if price is None: raise Exception( diff --git a/bin/balance-wallet b/bin/balance-wallet index 4b75471..c34cedd 100755 --- a/bin/balance-wallet +++ b/bin/balance-wallet @@ -13,8 +13,6 @@ from solana.publickey import PublicKey sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) import mango # nopep8 -# We explicitly want argument parsing to be outside the main try-except block because some arguments -# (like --help) will cause an exit, which our except: block traps. parser = argparse.ArgumentParser( description="Balance the value of tokens in a Mango Markets group to specific values or percentages." ) @@ -74,27 +72,16 @@ with mango.ContextBuilder.from_command_line_parameters(args) as context: targets: typing.Sequence[mango.FixedTargetBalance] = args.target logging.info(f"Targets: {targets}") - quote_instrument: typing.Optional[ - mango.Instrument - ] = context.instrument_lookup.find_by_symbol(args.quote_symbol) - if quote_instrument is None: - raise Exception(f"Could not find quote token '{args.quote_symbol}.") - quote_token: mango.Token = mango.Token.ensure(quote_instrument) + quote_token = mango.token(context, args.quote_symbol) prices: typing.List[mango.InstrumentValue] = [] oracle_provider: mango.OracleProvider = mango.create_oracle_provider( context, "market" ) for target in targets: - target_token: typing.Optional[ - mango.Instrument - ] = context.instrument_lookup.find_by_symbol(target.symbol) - if target_token is None: - raise Exception(f"Could not find target token '{target.symbol}.") + target_token = mango.token(context, target.symbol) market_symbol: str = f"serum:{target_token.symbol}/{quote_token.symbol}" - market = context.market_lookup.find_by_symbol(market_symbol) - if market is None: - raise Exception(f"Could not find market {market_symbol}") + market = mango.market(context, market_symbol) oracle = oracle_provider.oracle_for_market(context, market) if oracle is None: raise Exception(f"Could not find oracle for market {market_symbol}") diff --git a/bin/cancel-my-orders b/bin/cancel-my-orders index 0882091..6808624 100755 --- a/bin/cancel-my-orders +++ b/bin/cancel-my-orders @@ -56,14 +56,9 @@ with mango.ContextBuilder.from_command_line_parameters(args) as context: mango.output(f"No open orders on {market_operations.market.symbol}") else: if mango.PerpMarket.isa(market_operations.market): - instruction_builder = mango.PerpMarketInstructionBuilder( - context, - wallet, - mango.PerpMarket.ensure(market_operations.market), - group, - account, - ) - cancel_all = instruction_builder.build_cancel_all_orders_instructions() + cancel_all = mango.PerpMarketOperations.ensure( + market_operations + ).market_instruction_builder.build_cancel_all_orders_instructions() signers: mango.CombinableInstructions = ( mango.CombinableInstructions.from_wallet(wallet) diff --git a/bin/close-wrapped-sol-account b/bin/close-wrapped-sol-account index d654eda..3397dce 100755 --- a/bin/close-wrapped-sol-account +++ b/bin/close-wrapped-sol-account @@ -28,10 +28,7 @@ args: argparse.Namespace = mango.parse_args(parser) with mango.ContextBuilder.from_command_line_parameters(args) as context: wallet = mango.Wallet.from_command_line_parameters_or_raise(args) - wrapped_sol: mango.Token = mango.Token.ensure( - context.instrument_lookup.find_by_symbol_or_raise("SOL") - ) - + wrapped_sol: mango.Token = mango.token(context, "SOL") token_account: typing.Optional[mango.TokenAccount] = mango.TokenAccount.load( context, args.address ) diff --git a/bin/deposit b/bin/deposit index 19a8174..997782b 100755 --- a/bin/deposit +++ b/bin/deposit @@ -41,7 +41,7 @@ with mango.ContextBuilder.from_command_line_parameters(args) as context: context, wallet.address, group, args.account_address ) - deposit_value = mango.InstrumentValue(context.token(args.symbol), args.quantity) + deposit_value = mango.instrument_value(context, args.symbol, args.quantity) signatures = account.deposit(context, wallet, deposit_value) if args.wait: diff --git a/bin/ensure-account b/bin/ensure-account index ce67a51..e899b91 100755 --- a/bin/ensure-account +++ b/bin/ensure-account @@ -23,7 +23,6 @@ args: argparse.Namespace = mango.parse_args(parser) 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) accounts = mango.Account.load_all_for_owner(context, wallet.address, group) diff --git a/bin/ensure-associated-token-account b/bin/ensure-associated-token-account index bfe1e4a..87910dd 100755 --- a/bin/ensure-associated-token-account +++ b/bin/ensure-associated-token-account @@ -30,11 +30,7 @@ args: argparse.Namespace = mango.parse_args(parser) with mango.ContextBuilder.from_command_line_parameters(args) as context: wallet = mango.Wallet.from_command_line_parameters_or_raise(args) - - instrument = context.instrument_lookup.find_by_symbol(args.symbol) - if instrument is None: - raise Exception(f"Could not find instrument with symbol '{args.symbol}'.") - token: mango.Token = mango.Token.ensure(instrument) + token: mango.Token = mango.token(context, args.symbol) associated_token_address = spl_token.get_associated_token_address( wallet.address, token.mint diff --git a/bin/ensure-open-orders b/bin/ensure-open-orders index 88ad5cc..fe03eed 100755 --- a/bin/ensure-open-orders +++ b/bin/ensure-open-orders @@ -43,6 +43,4 @@ with mango.ContextBuilder.from_command_line_parameters(args) as context: context, wallet, account, args.market, args.dry_run ) open_orders = market_operations.ensure_openorders() - mango.output( - f"OpenOrders account for {market_operations.market.symbol} is {open_orders}" - ) + mango.output(f"OpenOrders account for {market_operations.symbol} is {open_orders}") diff --git a/bin/liquidate-single-account b/bin/liquidate-single-account index 8d0a5a0..bed991a 100755 --- a/bin/liquidate-single-account +++ b/bin/liquidate-single-account @@ -12,8 +12,6 @@ from solana.publickey import PublicKey sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) import mango # nopep8 -# We explicitly want argument parsing to be outside the main try-except block because some arguments -# (like --help) will cause an exit, which our except: block traps. parser = argparse.ArgumentParser(description="Liquidate a single margin account.") mango.ContextBuilder.add_command_line_parameters(parser) mango.Wallet.add_command_line_parameters(parser) diff --git a/bin/liquidator b/bin/liquidator index 82a9de1..62d9542 100755 --- a/bin/liquidator +++ b/bin/liquidator @@ -16,8 +16,6 @@ from decimal import Decimal sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) import mango # nopep8 -# We explicitly want argument parsing to be outside the main try-except block because some arguments -# (like --help) will cause an exit, which our except: block traps. parser = argparse.ArgumentParser( description="Run a liquidator for a Mango Markets group." ) diff --git a/bin/liquidator-single-run b/bin/liquidator-single-run index 0b74811..5a335bc 100755 --- a/bin/liquidator-single-run +++ b/bin/liquidator-single-run @@ -10,8 +10,6 @@ import time sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) import mango # nopep8 -# We explicitly want argument parsing to be outside the main try-except block because some arguments -# (like --help) will cause an exit, which our except: block traps. parser = argparse.ArgumentParser( description="Run a single pass of the liquidator for a Mango Markets group." ) diff --git a/bin/market-buy b/bin/market-buy index f93f659..29b006a 100755 --- a/bin/market-buy +++ b/bin/market-buy @@ -52,9 +52,7 @@ with mango.ContextBuilder.from_command_line_parameters(args) as context: context, wallet.address, group, args.account_address ) - ops: mango.MarketOperations = mango.operations( - context, wallet, account, args.symbol, args.dry_run - ) + ops = mango.operations(context, wallet, account, args.symbol, args.dry_run) signatures = ops.market_buy(args.quantity, args.max_slippage) if args.wait: diff --git a/bin/market-sell b/bin/market-sell index 492655c..baecb8b 100755 --- a/bin/market-sell +++ b/bin/market-sell @@ -54,9 +54,7 @@ with mango.ContextBuilder.from_command_line_parameters(args) as context: context, wallet.address, group, args.account_address ) - ops: mango.MarketOperations = mango.operations( - context, wallet, account, args.symbol, args.dry_run - ) + ops = mango.operations(context, wallet, account, args.symbol, args.dry_run) signatures = ops.market_buy(args.quantity, args.max_slippage) if args.wait: diff --git a/bin/marketmaker b/bin/marketmaker index 50fcf55..ff38020 100755 --- a/bin/marketmaker +++ b/bin/marketmaker @@ -216,7 +216,7 @@ with mango.ContextBuilder.from_command_line_parameters(args) as context: context, wallet.address, group, args.account_address ) - market = mango.load_market_by_symbol(context, args.market) + market = mango.market(context, args.market) # The market index is also the index of the base token in the group's token list. if market.quote != group.shared_quote_token: @@ -235,28 +235,28 @@ with mango.ContextBuilder.from_command_line_parameters(args) as context: underlying_market = mango.PerpMarket.ensure(market) - hedging_market_operations: mango.MarketOperations = mango.operations( + hedging_ops = mango.operations( context, wallet, account, args.hedging_market, args.dry_run ) - if not isinstance(hedging_market_operations, mango.SpotMarketOperations): + if not isinstance(hedging_ops, mango.SpotMarketOperations): raise Exception( f"MarketOperations for {args.hedging_market} is not a SpotMarketOperations." ) - logging.info(f"Hedging on {hedging_market_operations.market.symbol}") + logging.info(f"Hedging on {hedging_ops.market.symbol}") target_balance: typing.Optional[ mango.TargetBalance ] = args.hedging_target_balance if target_balance is None: target_balance = mango.FixedTargetBalance( - hedging_market_operations.market.base.symbol, Decimal(0) + hedging_ops.market.base.symbol, Decimal(0) ) hedger = mango.hedging.PerpToSpotHedger( group, underlying_market, - mango.SpotMarket.ensure(hedging_market_operations.market), - hedging_market_operations, + mango.SpotMarket.ensure(hedging_ops.market), + hedging_ops, args.hedging_max_price_slippage_factor, args.hedging_max_chunk_quantity, target_balance, @@ -305,7 +305,7 @@ with mango.ContextBuilder.from_command_line_parameters(args) as context: oracle_market: mango.LoadedMarket = ( market if args.oracle_market is None - else mango.load_market_by_symbol(context, args.oracle_market) + else mango.market(context, args.oracle_market) ) oracle = oracle_provider.oracle_for_market(context, oracle_market) if oracle is None: diff --git a/bin/mint b/bin/mint index a3acdf6..0aedc89 100755 --- a/bin/mint +++ b/bin/mint @@ -38,11 +38,7 @@ args: argparse.Namespace = mango.parse_args(parser) with mango.ContextBuilder.from_command_line_parameters(args) as context: wallet = mango.Wallet.from_command_line_parameters_or_raise(args) - - instrument = context.instrument_lookup.find_by_symbol(args.symbol) - if instrument is None: - raise Exception(f"Could not find instrument with symbol '{args.symbol}'.") - token: mango.Token = mango.Token.ensure(instrument) + token: mango.Token = mango.token(context, args.symbol) spl_token = SolanaSPLToken( context.client.compatible_client, token.mint, TOKEN_PROGRAM_ID, wallet.keypair diff --git a/bin/notify-below-minimum-sol-balance b/bin/notify-below-minimum-sol-balance index f49d061..f75eeca 100755 --- a/bin/notify-below-minimum-sol-balance +++ b/bin/notify-below-minimum-sol-balance @@ -37,11 +37,9 @@ with mango.ContextBuilder.from_command_line_parameters(args) as context: account_info = mango.AccountInfo.load(context, args.address) if account_info is None: raise Exception(f"No account at '{args.address}'") - else: - if account_info.sols < args.minimum_sol_balance: - notify: mango.NotificationTarget = mango.CompoundNotificationTarget( - args.notify - ) - report = f'Account "{args.name} [{args.address}]" on {context.client.cluster_name} has only {account_info.sols} SOL, which is below the minimum required balance of {args.minimum_sol_balance} SOL.' - notify.send(report) - mango.output(f"Notification sent: {report}") + + if account_info.sols < args.minimum_sol_balance: + notify: mango.NotificationTarget = mango.CompoundNotificationTarget(args.notify) + report = f'Account "{args.name} [{args.address}]" on {context.client.cluster_name} has only {account_info.sols} SOL, which is below the minimum required balance of {args.minimum_sol_balance} SOL.' + notify.send(report) + mango.output(f"Notification sent: {report}") diff --git a/bin/redeem-mango b/bin/redeem-mango index 6edb668..b3e77ab 100755 --- a/bin/redeem-mango +++ b/bin/redeem-mango @@ -140,14 +140,7 @@ with mango.ContextBuilder.from_command_line_parameters(args) as context: context, wallet, group, mngo, account, perp_market, basket_token ) else: - market = context.market_lookup.find_by_symbol(args.market) - if market is None: - raise Exception(f"Could not find market {args.market}") - - perp_market = mango.PerpMarket.ensure( - mango.ensure_market_loaded(context, market) - ) - + perp_market = mango.PerpMarket.ensure(mango.market(context, args.market)) basket_token = find_basket_token_in_account(account, perp_market.base) all_instructions += build_redeem_instruction_for_account( context, wallet, group, mngo, account, perp_market, basket_token diff --git a/bin/report-transactions b/bin/report-transactions index caa8d75..8fe3a6c 100755 --- a/bin/report-transactions +++ b/bin/report-transactions @@ -16,8 +16,6 @@ from solana.publickey import PublicKey sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) import mango # nopep8 -# We explicitly want argument parsing to be outside the main try-except block because some arguments -# (like --help) will cause an exit, which our except: block traps. parser = argparse.ArgumentParser( description="Run the Transaction Scout to display information about a specific transaction." ) diff --git a/bin/send-notification b/bin/send-notification index f06ff87..70a6551 100755 --- a/bin/send-notification +++ b/bin/send-notification @@ -10,8 +10,6 @@ import traceback sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) import mango # nopep8 -# We explicitly want argument parsing to be outside the main try-except block because some arguments -# (like --help) will cause an exit, which our except: block traps. parser = argparse.ArgumentParser(description="Sends SOL to a different address.") parser.add_argument( "--notification-target", diff --git a/bin/send-sols b/bin/send-sols index 655019a..9bb267b 100755 --- a/bin/send-sols +++ b/bin/send-sols @@ -14,8 +14,6 @@ from solana.transaction import Transaction sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) import mango # nopep8 -# We explicitly want argument parsing to be outside the main try-except block because some arguments -# (like --help) will cause an exit, which our except: block traps. parser = argparse.ArgumentParser(description="Sends SOL to a different address.") mango.ContextBuilder.add_command_line_parameters(parser) mango.Wallet.add_command_line_parameters(parser) diff --git a/bin/send-token b/bin/send-token index 114aebb..90233d0 100755 --- a/bin/send-token +++ b/bin/send-token @@ -1,7 +1,6 @@ #!/usr/bin/env python3 import argparse -import logging import os import os.path import sys @@ -16,8 +15,6 @@ from spl.token.constants import ACCOUNT_LEN, TOKEN_PROGRAM_ID sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) import mango # nopep8 -# We explicitly want argument parsing to be outside the main try-except block because some arguments -# (like --help) will cause an exit, which our except: block traps. parser = argparse.ArgumentParser(description="Sends SPL tokens to a different address.") mango.ContextBuilder.add_command_line_parameters(parser) mango.Wallet.add_command_line_parameters(parser) @@ -48,13 +45,7 @@ args: argparse.Namespace = mango.parse_args(parser) with mango.ContextBuilder.from_command_line_parameters(args) as context: wallet = mango.Wallet.from_command_line_parameters_or_raise(args) - - logging.info(f"Wallet address: {wallet.address}") - - instrument = context.instrument_lookup.find_by_symbol(args.symbol) - if instrument is None: - raise Exception(f"Could not find details of token with symbol {args.symbol}.") - token: mango.Token = mango.Token.ensure(instrument) + token: mango.Token = mango.token(context, args.symbol) spl_token = SolanaSPLToken( context.client.compatible_client, token.mint, TOKEN_PROGRAM_ID, wallet.keypair diff --git a/bin/settle-market b/bin/settle-market index 2c089ec..59e5efd 100755 --- a/bin/settle-market +++ b/bin/settle-market @@ -9,10 +9,8 @@ import sys from solana.publickey import PublicKey sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) -import mango # nopep8 +import mango -# We explicitly want argument parsing to be outside the main try-except block because some arguments -# (like --help) will cause an exit, which our except: block traps. parser = argparse.ArgumentParser( description="Settles all openorders transactions in the Group." ) diff --git a/bin/show-account-balances b/bin/show-account-balances index 59010a3..768c318 100755 --- a/bin/show-account-balances +++ b/bin/show-account-balances @@ -42,11 +42,10 @@ with mango.ContextBuilder.from_command_line_parameters(args) as context: balances += [mango.InstrumentValue(mango.SolToken, sol_balance)] for slot_token_bank in group.tokens: - if isinstance(slot_token_bank.token, mango.Token): - balance = mango.InstrumentValue.fetch_total_value( - context, address, slot_token_bank.token - ) - balances += [balance] + balance = mango.InstrumentValue.fetch_total_value( + context, address, slot_token_bank.token + ) + balances += [balance] mango.output(f"\nToken Balances [{address}]:") total_in_wallet: mango.InstrumentValue = mango.InstrumentValue( diff --git a/bin/show-funding-rates b/bin/show-funding-rates index 6da6e3c..1bf0ac3 100755 --- a/bin/show-funding-rates +++ b/bin/show-funding-rates @@ -22,12 +22,5 @@ parser.add_argument( args: argparse.Namespace = mango.parse_args(parser) with mango.ContextBuilder.from_command_line_parameters(args) as context: - group = mango.Group.load(context) - - market = context.market_lookup.find_by_symbol(args.market) - if market is None: - raise Exception(f"Could not find market {args.market}") - - perp_market = mango.PerpMarket.ensure(mango.ensure_market_loaded(context, market)) - + perp_market = mango.PerpMarket.ensure(mango.market(context, args.market)) mango.output(perp_market.fetch_funding(context)) diff --git a/bin/show-interest-rates b/bin/show-interest-rates index 0f06464..c7f6048 100755 --- a/bin/show-interest-rates +++ b/bin/show-interest-rates @@ -24,11 +24,7 @@ args: argparse.Namespace = mango.parse_args(parser) with mango.ContextBuilder.from_command_line_parameters(args) as context: group = mango.Group.load(context) - token = context.instrument_lookup.find_by_symbol(args.symbol) - if token is None: - raise Exception(f"Could not find token {args.symbol} in group {group.address}") - + token = mango.token(context, args.symbol) token_bank = group.token_bank_by_instrument(token) - interest_rates = token_bank.fetch_interest_rates(context) mango.output(interest_rates) diff --git a/bin/show-liquidity-mining-info b/bin/show-liquidity-mining-info index 961bf13..ce3c4d2 100755 --- a/bin/show-liquidity-mining-info +++ b/bin/show-liquidity-mining-info @@ -21,10 +21,5 @@ parser.add_argument( args: argparse.Namespace = mango.parse_args(parser) with mango.ContextBuilder.from_command_line_parameters(args) as context: - market = context.market_lookup.find_by_symbol(args.market) - if market is None: - raise Exception(f"Could not find market {args.market}") - - actual_market = mango.PerpMarket.ensure(mango.ensure_market_loaded(context, market)) - - mango.output(actual_market.underlying_perp_market.liquidity_mining_info) + perp_market = mango.PerpMarket.ensure(mango.market(context, args.market)) + mango.output(perp_market.underlying_perp_market.liquidity_mining_info) diff --git a/bin/show-market b/bin/show-market index 37ff1aa..07a4e4e 100755 --- a/bin/show-market +++ b/bin/show-market @@ -16,9 +16,5 @@ parser.add_argument( args: argparse.Namespace = mango.parse_args(parser) with mango.ContextBuilder.from_command_line_parameters(args) as context: - market = context.market_lookup.find_by_symbol(args.market) - if market is None: - raise Exception(f"Could not find market {args.market}") - - actual_market = mango.ensure_market_loaded(context, market) - mango.output(actual_market) + market = mango.market(context, args.market) + mango.output(market) diff --git a/bin/show-model-state b/bin/show-model-state index 762448d..6d2e9a9 100755 --- a/bin/show-model-state +++ b/bin/show-model-state @@ -42,11 +42,7 @@ with mango.ContextBuilder.from_command_line_parameters( context, wallet.address, group, args.account_address ) - market = context.market_lookup.find_by_symbol(args.market) - if market is None: - raise Exception(f"Could not find market {args.market}") - - market = mango.ensure_market_loaded(context, market) + market = mango.market(context, args.market) oracle_provider: mango.OracleProvider = mango.create_oracle_provider( context, args.oracle_provider diff --git a/bin/show-open-orders b/bin/show-open-orders index 2e3b53b..c7c4a57 100755 --- a/bin/show-open-orders +++ b/bin/show-open-orders @@ -26,12 +26,12 @@ parser.add_argument( ) args: argparse.Namespace = mango.parse_args(parser) -with mango.ContextBuilder.from_command_line_parameters(args) as context: - address: typing.Optional[PublicKey] = args.address - if address is None: - wallet = mango.Wallet.from_command_line_parameters_or_raise(args) - address = wallet.address +address: typing.Optional[PublicKey] = args.address +if address is None: + wallet = mango.Wallet.from_command_line_parameters_or_raise(args) + address = wallet.address +with mango.ContextBuilder.from_command_line_parameters(args) as context: group = mango.Group.load(context) account = mango.Account.load_for_owner_by_address( context, wallet.address, group, args.account_address diff --git a/bin/show-orders b/bin/show-orderbook similarity index 83% rename from bin/show-orders rename to bin/show-orderbook index 0ed6fb5..785930a 100755 --- a/bin/show-orders +++ b/bin/show-orderbook @@ -21,12 +21,6 @@ parser.add_argument( 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", -) args: argparse.Namespace = mango.parse_args(parser) with mango.ContextBuilder.from_command_line_parameters(args) as context: @@ -36,7 +30,7 @@ with mango.ContextBuilder.from_command_line_parameters(args) as context: context, wallet.address, group, args.account_address ) - market = mango.load_market_by_symbol(context, args.market) + market = mango.market(context, args.market) orderbook = market.fetch_orderbook(context) mango.output(orderbook) diff --git a/bin/show-price b/bin/show-price index f95a3ac..25248b0 100755 --- a/bin/show-price +++ b/bin/show-price @@ -34,10 +34,7 @@ with mango.ContextBuilder.from_command_line_parameters(args) as context: context, args.provider ) - market = context.market_lookup.find_by_symbol(args.market) - if market is None: - raise Exception(f"Could not find market {args.market}.") - + market = mango.market(context, args.market) oracle = oracle_provider.oracle_for_market(context, market) if oracle is None: mango.output( diff --git a/bin/show-serum-open-orders b/bin/show-serum-open-orders index 7cecfa4..df376cb 100755 --- a/bin/show-serum-open-orders +++ b/bin/show-serum-open-orders @@ -30,11 +30,7 @@ with mango.ContextBuilder.from_command_line_parameters(args) as context: wallet = mango.Wallet.from_command_line_parameters_or_raise(args) address = wallet.address - stub = context.market_lookup.find_by_symbol(args.market) - if stub is None: - raise Exception(f"Could not find market {args.market}") - - market = mango.SerumMarket.ensure(mango.ensure_market_loaded(context, stub)) + market = mango.SerumMarket.ensure(mango.market(context, args.market)) all_open_orders_for_market = mango.OpenOrders.load_for_market_and_owner( context, diff --git a/bin/show-token-balance b/bin/show-token-balance index 4411d15..1707983 100755 --- a/bin/show-token-balance +++ b/bin/show-token-balance @@ -42,10 +42,7 @@ with mango.ContextBuilder.from_command_line_parameters(args) as context: if args.mint is not None: token = mango.Token(args.symbol, args.symbol, args.decimals, args.mint) else: - instrument: mango.Instrument = ( - context.instrument_lookup.find_by_symbol_or_raise(args.symbol) - ) - token = mango.Token.ensure(instrument) + token = mango.token(context, args.symbol) token_accounts: typing.Sequence[ mango.TokenAccount ] = mango.TokenAccount.fetch_all_for_owner_and_token(context, owner_address, token) diff --git a/bin/show-wrapped-sol b/bin/show-wrapped-sol index 7d86313..6f120e5 100755 --- a/bin/show-wrapped-sol +++ b/bin/show-wrapped-sol @@ -16,11 +16,7 @@ args: argparse.Namespace = mango.parse_args(parser) with mango.ContextBuilder.from_command_line_parameters(args) as context: wallet = mango.Wallet.from_command_line_parameters_or_raise(args) - - wrapped_sol: mango.Token = mango.Token.ensure( - context.instrument_lookup.find_by_symbol_or_raise("SOL") - ) - + wrapped_sol: mango.Token = mango.token(context, "SOL") token_accounts = mango.TokenAccount.fetch_all_for_owner_and_token( context, wallet.address, wrapped_sol ) diff --git a/bin/simple-marketmaker b/bin/simple-marketmaker index 058fec6..ee89ec1 100755 --- a/bin/simple-marketmaker +++ b/bin/simple-marketmaker @@ -74,10 +74,6 @@ try: context, wallet.address, group, args.account_address ) - market_stub = context.market_lookup.find_by_symbol(args.market) - if market_stub is None: - raise Exception(f"Could not find serum market {args.market}") - market_operations = mango.operations( context, wallet, account, args.market, args.dry_run ) diff --git a/bin/transaction-scout b/bin/transaction-scout deleted file mode 100755 index 994f429..0000000 --- a/bin/transaction-scout +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env python3 - -import argparse -import logging -import os -import os.path -import sys - -sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) -import mango # nopep8 - -# We explicitly want argument parsing to be outside the main try-except block because some arguments -# (like --help) will cause an exit, which our except: block traps. -parser = argparse.ArgumentParser( - description="Run the Transaction Scout to display information about a specific transaction." -) -mango.ContextBuilder.add_command_line_parameters(parser) -parser.add_argument( - "--signature", - type=str, - required=True, - help="The signature of the transaction to look up", -) -args: argparse.Namespace = mango.parse_args(parser) - -with mango.ContextBuilder.from_command_line_parameters(args) as context: - signature = args.signature - logging.info(f"Signature: {signature}") - - report = mango.TransactionScout.load(context, signature) - mango.output(report) diff --git a/bin/unwrap-sol b/bin/unwrap-sol index 96c53bd..3291676 100755 --- a/bin/unwrap-sol +++ b/bin/unwrap-sol @@ -27,11 +27,7 @@ args: argparse.Namespace = mango.parse_args(parser) with mango.ContextBuilder.from_command_line_parameters(args) as context: wallet = mango.Wallet.from_command_line_parameters_or_raise(args) - - wrapped_sol: mango.Token = mango.Token.ensure( - context.instrument_lookup.find_by_symbol_or_raise("SOL") - ) - + wrapped_sol: mango.Token = mango.token(context, "SOL") largest_token_account = mango.TokenAccount.fetch_largest_for_owner_and_token( context, wallet.address, wrapped_sol ) diff --git a/bin/withdraw b/bin/withdraw index 2b77d5a..5011a77 100755 --- a/bin/withdraw +++ b/bin/withdraw @@ -47,7 +47,7 @@ with mango.ContextBuilder.from_command_line_parameters(args) as context: context, wallet.address, group, args.account_address ) - withdrawal_value = mango.InstrumentValue(context.token(args.symbol), args.quantity) + withdrawal_value = mango.instrument_value(context, args.symbol, args.quantity) signatures = account.withdraw(context, wallet, withdrawal_value, args.allow_borrow) if args.wait: diff --git a/bin/wrap-sol b/bin/wrap-sol index 652e872..6262236 100755 --- a/bin/wrap-sol +++ b/bin/wrap-sol @@ -29,10 +29,7 @@ args: argparse.Namespace = mango.parse_args(parser) with mango.ContextBuilder.from_command_line_parameters(args) as context: wallet = mango.Wallet.from_command_line_parameters_or_raise(args) - - wrapped_sol: mango.Token = mango.Token.ensure( - context.instrument_lookup.find_by_symbol_or_raise("SOL") - ) + wrapped_sol: mango.Token = mango.token(context, "SOL") amount_to_transfer = int(args.quantity * mango.SOL_DECIMAL_DIVISOR) signers: mango.CombinableInstructions = mango.CombinableInstructions.from_signers( diff --git a/mango/__init__.py b/mango/__init__.py index 8b43308..d1099ec 100644 --- a/mango/__init__.py +++ b/mango/__init__.py @@ -66,8 +66,6 @@ from .encoding import decode_binary as decode_binary from .encoding import encode_binary as encode_binary from .encoding import encode_key as encode_key from .encoding import encode_int as encode_int -from .ensuremarketloaded import ensure_market_loaded as ensure_market_loaded -from .ensuremarketloaded import load_market_by_symbol as load_market_by_symbol from .group import Group as Group from .group import GroupSlot as GroupSlot from .group import GroupSlotPerpMarket as GroupSlotPerpMarket @@ -170,9 +168,9 @@ from .logmessages import expand_log_messages as expand_log_messages from .lotsizeconverter import LotSizeConverter as LotSizeConverter from .mangoinstruction import MangoInstruction as MangoInstruction from .lotsizeconverter import NullLotSizeConverter as NullLotSizeConverter -from .market import InventorySource as InventorySource -from .market import MarketType as MarketType -from .market import Market as Market +from .markets import InventorySource as InventorySource +from .markets import MarketType as MarketType +from .markets import Market as Market from .marketlookup import CompoundMarketLookup as CompoundMarketLookup from .marketlookup import MarketLookup as MarketLookup from .marketlookup import NullMarketLookup as NullMarketLookup @@ -253,9 +251,12 @@ from .perpmarketdetails import PerpMarketDetails as PerpMarketDetails from .perpopenorders import PerpOpenOrders as PerpOpenOrders from .placedorder import PlacedOrder as PlacedOrder from .placedorder import PlacedOrdersContainer as PlacedOrdersContainer -from .porcelain import market as market from .porcelain import instruction_builder as instruction_builder +from .porcelain import instrument as instrument +from .porcelain import instrument_value as instrument_value +from .porcelain import market as market from .porcelain import operations as operations +from .porcelain import token as token from .publickey import encode_public_key_for_sorting as encode_public_key_for_sorting from .reconnectingwebsocket import ReconnectingWebsocket as ReconnectingWebsocket from .retrier import RetryWithPauses as RetryWithPauses @@ -275,9 +276,9 @@ from .spotmarket import SpotMarketOperations as SpotMarketOperations from .spotmarket import SpotMarketStub as SpotMarketStub from .text import indent_collection_as_str as indent_collection_as_str from .text import indent_item_by as indent_item_by -from .token import Instrument as Instrument -from .token import SolToken as SolToken -from .token import Token as Token +from .tokens import Instrument as Instrument +from .tokens import SolToken as SolToken +from .tokens import Token as Token from .tokenaccount import TokenAccount as TokenAccount from .tokenbank import BankBalances as BankBalances from .tokenbank import InterestRates as InterestRates diff --git a/mango/account.py b/mango/account.py index 7e8d212..9c7d414 100644 --- a/mango/account.py +++ b/mango/account.py @@ -36,7 +36,7 @@ from .orders import Side from .perpaccount import PerpAccount from .perpopenorders import PerpOpenOrders from .placedorder import PlacedOrder -from .token import Instrument, Token +from .tokens import Instrument, Token from .tokenaccount import TokenAccount from .tokenbank import TokenBank from .version import Version diff --git a/mango/accountinfoconverter.py b/mango/accountinfoconverter.py index 3d4d799..39b42e1 100644 --- a/mango/accountinfoconverter.py +++ b/mango/accountinfoconverter.py @@ -33,7 +33,7 @@ from .orderbookside import PerpOrderBookSide from .perpeventqueue import PerpEvent, PerpEventQueue, UnseenPerpEventChangesTracker from .perpmarketdetails import PerpMarketDetails from .serumeventqueue import SerumEvent, SerumEventQueue, UnseenSerumEventChangesTracker -from .token import Instrument, Token +from .tokens import Instrument, Token from .tokenbank import NodeBank, RootBank, TokenBank diff --git a/mango/accountscout.py b/mango/accountscout.py index d5aeb17..337bb96 100644 --- a/mango/accountscout.py +++ b/mango/accountscout.py @@ -23,7 +23,7 @@ from .accountinfo import AccountInfo from .constants import SYSTEM_PROGRAM_ADDRESS from .context import Context from .group import Group -from .token import Token +from .tokens import Token from .tokenaccount import TokenAccount from .wallet import Wallet diff --git a/mango/balancesheet.py b/mango/balancesheet.py index dec3380..9e3729a 100644 --- a/mango/balancesheet.py +++ b/mango/balancesheet.py @@ -20,7 +20,7 @@ import typing from decimal import Decimal from .output import output -from .token import Token +from .tokens import Token # # 🥭 BalanceSheet class diff --git a/mango/cache.py b/mango/cache.py index 370fb35..bbef52c 100644 --- a/mango/cache.py +++ b/mango/cache.py @@ -25,7 +25,7 @@ from .context import Context from .instrumentvalue import InstrumentValue from .layouts import layouts from .metadata import Metadata -from .token import Instrument, Token +from .tokens import Instrument, Token from .version import Version diff --git a/mango/context.py b/mango/context.py index f251e6f..c6b2c27 100644 --- a/mango/context.py +++ b/mango/context.py @@ -36,7 +36,7 @@ from .instructionreporter import InstructionReporter, CompoundInstructionReporte from .instrumentlookup import InstrumentLookup from .marketlookup import MarketLookup from .text import indent_collection_as_str, indent_item_by -from .token import Instrument, Token +from .tokens import Instrument, Token # # 🥭 Context class diff --git a/mango/ensuremarketloaded.py b/mango/ensuremarketloaded.py deleted file mode 100644 index 61a8495..0000000 --- a/mango/ensuremarketloaded.py +++ /dev/null @@ -1,58 +0,0 @@ -# # ⚠ Warning -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT -# LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -# NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# -# [🥭 Mango Markets](https://mango.markets/) support is available at: -# [Docs](https://docs.mango.markets/) -# [Discord](https://discord.gg/67jySBhxrg) -# [Twitter](https://twitter.com/mangomarkets) -# [Github](https://github.com/blockworks-foundation) -# [Email](mailto:hello@blockworks.foundation) - - -from .context import Context -from .group import Group -from .loadedmarket import LoadedMarket -from .market import Market -from .perpmarket import PerpMarketStub -from .serummarket import SerumMarketStub -from .spotmarket import SpotMarketStub - - -# # 🥭 ensure_market_loaded function -# -# This function ensures that a `Market` is 'loaded' and not a 'stub'. Stubs are handy for laoding in -# bulk, for instance in a market lookup, but real processing usually requires a fully loaded `Market`. -# -# This function simplifies turning a stub into a fully-loaded, usable market. -# -def ensure_market_loaded(context: Context, market: Market) -> LoadedMarket: - if isinstance(market, LoadedMarket): - return market - elif isinstance(market, SerumMarketStub): - return market.load(context) - elif isinstance(market, SpotMarketStub): - group: Group = Group.load(context, market.group_address) - return market.load(context, group) - elif isinstance(market, PerpMarketStub): - group = Group.load(context, market.group_address) - return market.load(context, group) - - raise Exception(f"Market {market} could not be loaded.") - - -# # 🥭 load_market_by_symbol -# -# This function takes a `Context` and a market symbol string (like "ETH/USDC") and returns a loaded market. It -# throws if anything goes wrong rather than return None. -# -def load_market_by_symbol(context: Context, symbol: str) -> LoadedMarket: - market = context.market_lookup.find_by_symbol(symbol) - if market is None: - raise Exception(f"Could not find market {symbol}") - - return ensure_market_loaded(context, market) diff --git a/mango/group.py b/mango/group.py index 95c23ae..d974060 100644 --- a/mango/group.py +++ b/mango/group.py @@ -30,7 +30,7 @@ from .layouts import layouts from .lotsizeconverter import LotSizeConverter, RaisingLotSizeConverter from .marketlookup import MarketLookup from .metadata import Metadata -from .token import Instrument, Token +from .tokens import Instrument, Token from .tokenbank import TokenBank from .version import Version diff --git a/mango/idsjsonmarketlookup.py b/mango/idsjsonmarketlookup.py index 09bc3aa..f11bef9 100644 --- a/mango/idsjsonmarketlookup.py +++ b/mango/idsjsonmarketlookup.py @@ -20,11 +20,11 @@ from solana.publickey import PublicKey from .constants import MangoConstants from .instrumentlookup import InstrumentLookup -from .market import Market +from .markets import Market from .marketlookup import MarketLookup from .perpmarket import PerpMarketStub from .spotmarket import SpotMarketStub -from .token import Instrument, Token +from .tokens import Instrument, Token class IdsJsonMarketType(enum.Enum): diff --git a/mango/instructions.py b/mango/instructions.py index 54fd9cc..b4d953f 100644 --- a/mango/instructions.py +++ b/mango/instructions.py @@ -56,7 +56,7 @@ from .orders import Order, OrderType, Side from .perpmarketdetails import PerpMarketDetails # from .spotmarket import SpotMarket -from .token import Token +from .tokens import Token from .tokenaccount import TokenAccount from .tokenbank import TokenBank, NodeBank, RootBank from .wallet import Wallet diff --git a/mango/instrumentlookup.py b/mango/instrumentlookup.py index 616c451..10c48f4 100644 --- a/mango/instrumentlookup.py +++ b/mango/instrumentlookup.py @@ -23,7 +23,7 @@ from decimal import Decimal from solana.publickey import PublicKey from .constants import DATA_PATH, MangoConstants -from .token import Instrument, Token +from .tokens import Instrument, Token # # 🥭 InstrumentLookup class diff --git a/mango/instrumentvalue.py b/mango/instrumentvalue.py index f26da19..a892f0e 100644 --- a/mango/instrumentvalue.py +++ b/mango/instrumentvalue.py @@ -24,7 +24,7 @@ from solana.rpc.types import TokenAccountOpts from .context import Context from .output import output -from .token import Instrument, Token +from .tokens import Instrument, Token def _decimal_from_number(value: numbers.Number) -> Decimal: diff --git a/mango/inventory.py b/mango/inventory.py index 2094b21..8273389 100644 --- a/mango/inventory.py +++ b/mango/inventory.py @@ -23,7 +23,7 @@ from .account import Account from .cache import Cache from .group import Group from .instrumentvalue import InstrumentValue -from .market import InventorySource, Market +from .markets import InventorySource, Market from .openorders import OpenOrders from .watcher import Watcher diff --git a/mango/loadedmarket.py b/mango/loadedmarket.py index 7398708..0dea890 100644 --- a/mango/loadedmarket.py +++ b/mango/loadedmarket.py @@ -21,10 +21,10 @@ from solana.publickey import PublicKey from .accountinfo import AccountInfo from .context import Context from .lotsizeconverter import LotSizeConverter -from .market import InventorySource, MarketType, Market +from .markets import InventorySource, MarketType, Market from .observables import Disposable from .orders import Order, OrderBook -from .token import Instrument, Token +from .tokens import Instrument, Token from .websocketsubscription import ( SharedWebSocketSubscriptionManager, WebSocketAccountSubscription, diff --git a/mango/loadmarketbysymbol.py b/mango/loadmarketbysymbol.py deleted file mode 100644 index 340ec54..0000000 --- a/mango/loadmarketbysymbol.py +++ /dev/null @@ -1,32 +0,0 @@ -# # ⚠ Warning -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT -# LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -# NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# -# [🥭 Mango Markets](https://mango.markets/) support is available at: -# [Docs](https://docs.mango.markets/) -# [Discord](https://discord.gg/67jySBhxrg) -# [Twitter](https://twitter.com/mangomarkets) -# [Github](https://github.com/blockworks-foundation) -# [Email](mailto:hello@blockworks.foundation) - -from .context import Context -from .ensuremarketloaded import ensure_market_loaded -from .loadedmarket import LoadedMarket - - -# # 🥭 load_market_by_symbol -# -# This function takes a `Context` and a market symbol string (like "ETH/USDC") and returns a loaded market. It -# throws if anything goes wrong rather than return None. -# -def load_market_by_symbol(context: Context, symbol: str) -> LoadedMarket: - market_symbol = symbol - market = context.market_lookup.find_by_symbol(market_symbol) - if market is None: - raise Exception(f"Could not find market {market_symbol}") - - return ensure_market_loaded(context, market) diff --git a/mango/lotsizeconverter.py b/mango/lotsizeconverter.py index 0d30825..ab26779 100644 --- a/mango/lotsizeconverter.py +++ b/mango/lotsizeconverter.py @@ -17,7 +17,7 @@ import jsons from decimal import Decimal -from .token import Instrument +from .tokens import Instrument # # 🥭 LotSizeConverter class diff --git a/mango/marketlookup.py b/mango/marketlookup.py index 79c09c1..861f418 100644 --- a/mango/marketlookup.py +++ b/mango/marketlookup.py @@ -20,7 +20,7 @@ import typing from solana.publickey import PublicKey -from .market import Market +from .markets import Market # # 🥭 MarketLookup class diff --git a/mango/marketmaking/modelstatebuilder.py b/mango/marketmaking/modelstatebuilder.py index 4fce366..efd7924 100644 --- a/mango/marketmaking/modelstatebuilder.py +++ b/mango/marketmaking/modelstatebuilder.py @@ -24,7 +24,7 @@ from solana.publickey import PublicKey from ..instrumentvalue import InstrumentValue from ..modelstate import ModelState -from ..token import Token +from ..tokens import Token # # 🥭 ModelStateBuilder class diff --git a/mango/marketmaking/modelstatebuilderfactory.py b/mango/marketmaking/modelstatebuilderfactory.py index b1ce78b..c1160c9 100644 --- a/mango/marketmaking/modelstatebuilderfactory.py +++ b/mango/marketmaking/modelstatebuilderfactory.py @@ -20,7 +20,6 @@ import typing from solana.publickey import PublicKey from ..constants import SYSTEM_PROGRAM_ADDRESS -from ..ensuremarketloaded import ensure_market_loaded from ..modelstate import ModelState from .modelstatebuilder import ( ModelStateBuilder, @@ -56,7 +55,7 @@ def model_state_builder_factory( wallet: mango.Wallet, group: mango.Group, account: mango.Account, - market: mango.Market, + market: mango.LoadedMarket, oracle: mango.Oracle, ) -> ModelStateBuilder: if mode == ModelUpdateMode.WEBSOCKET: @@ -204,10 +203,9 @@ def __load_all_openorders_watchers( for basket_token in account.base_slots: if basket_token.spot_open_orders is not None: spot_market_symbol: str = f"spot:{basket_token.base_instrument.symbol}/{account.shared_quote_token.symbol}" - stub = context.market_lookup.find_by_symbol(spot_market_symbol) - if stub is None: - raise Exception(f"Could not find spot market {spot_market_symbol}") - spot_market = mango.SpotMarket.ensure(ensure_market_loaded(context, stub)) + spot_market = mango.SpotMarket.ensure( + mango.market(context, spot_market_symbol) + ) oo_watcher = mango.build_spot_open_orders_watcher( context, websocket_manager, @@ -230,7 +228,7 @@ def _websocket_model_state_builder_factory( wallet: mango.Wallet, group: mango.Group, account: mango.Account, - market: mango.Market, + market: mango.LoadedMarket, oracle: mango.Oracle, ) -> ModelStateBuilder: group_watcher = mango.build_group_watcher( @@ -251,7 +249,6 @@ def _websocket_model_state_builder_factory( disposer.add_disposable(price_disposable) health_check.add("price_subscription", price_feed) - market = mango.ensure_market_loaded(context, market) if mango.SerumMarket.isa(market): serum_market = mango.SerumMarket.ensure(market) order_owner: PublicKey = ( diff --git a/mango/marketoperations.py b/mango/marketoperations.py index b85aa3a..8c23205 100644 --- a/mango/marketoperations.py +++ b/mango/marketoperations.py @@ -21,16 +21,12 @@ import typing from decimal import Decimal from solana.publickey import PublicKey -from .accountinfo import AccountInfo from .combinableinstructions import CombinableInstructions from .constants import SYSTEM_PROGRAM_ADDRESS -from .context import Context -from .loadedmarket import Event, FillEvent, LoadedMarket -from .lotsizeconverter import LotSizeConverter, NullLotSizeConverter -from .market import InventorySource -from .observables import Disposable +from .loadedmarket import LoadedMarket +from .lotsizeconverter import NullLotSizeConverter +from .markets import InventorySource from .orders import Order, OrderBook, OrderType, Side -from .token import Instrument, Token # # 🥭 MarketOperations @@ -126,66 +122,10 @@ class MarketOperations(metaclass=abc.ABCMeta): def symbol(self) -> str: return self.market.symbol - @property - def program_address(self) -> PublicKey: - return self.market.program_address - - @property - def address(self) -> PublicKey: - return self.market.address - @property def inventory_source(self) -> InventorySource: return self.market.inventory_source - @property - def base(self) -> Instrument: - return self.market.base - - @property - def quote(self) -> Token: - return self.market.quote - - @property - def lot_size_converter(self) -> LotSizeConverter: - return self.market.lot_size_converter - - @property - def bids_address(self) -> PublicKey: - return self.market.bids_address - - @property - def asks_address(self) -> PublicKey: - return self.market.asks_address - - def parse_account_info_to_orders( - self, account_info: AccountInfo - ) -> typing.Sequence[Order]: - return self.market.parse_account_info_to_orders(account_info) - - def parse_account_infos_to_orderbook( - self, bids_account_info: AccountInfo, asks_account_info: AccountInfo - ) -> OrderBook: - return self.market.parse_account_infos_to_orderbook( - bids_account_info, asks_account_info - ) - - def fetch_orderbook(self, context: Context) -> OrderBook: - [bids_info, asks_info] = AccountInfo.load_multiple( - context, [self.bids_address, self.asks_address] - ) - return self.parse_account_infos_to_orderbook(bids_info, asks_info) - - def on_fill( - self, context: Context, handler: typing.Callable[[FillEvent], None] - ) -> Disposable: - return self.market.on_fill(context, handler) - - def on_event( - self, context: Context, handler: typing.Callable[[Event], None] - ) -> Disposable: - return self.market.on_event(context, handler) - @abc.abstractmethod def cancel_order( self, order: Order, ok_if_missing: bool = False diff --git a/mango/market.py b/mango/markets.py similarity index 98% rename from mango/market.py rename to mango/markets.py index 3c8ea5e..97a54aa 100644 --- a/mango/market.py +++ b/mango/markets.py @@ -21,7 +21,7 @@ import logging from solana.publickey import PublicKey from .lotsizeconverter import LotSizeConverter -from .token import Instrument, Token +from .tokens import Instrument, Token class MarketType(enum.Enum): diff --git a/mango/modelstate.py b/mango/modelstate.py index 57a7ad6..95d0849 100644 --- a/mango/modelstate.py +++ b/mango/modelstate.py @@ -23,7 +23,7 @@ from solana.publickey import PublicKey from .account import Account from .group import Group from .inventory import Inventory -from .market import Market +from .markets import Market from .oracle import Price from .orders import Order, OrderBook from .placedorder import PlacedOrdersContainer diff --git a/mango/oracle.py b/mango/oracle.py index fe102e0..6162f1e 100644 --- a/mango/oracle.py +++ b/mango/oracle.py @@ -23,7 +23,7 @@ from datetime import datetime from decimal import Decimal from .context import Context -from .market import Market +from .markets import Market # # 🥭 Oracles diff --git a/mango/oracles/ftx/ftx.py b/mango/oracles/ftx/ftx.py index bec5540..00ddb0a 100644 --- a/mango/oracles/ftx/ftx.py +++ b/mango/oracles/ftx/ftx.py @@ -26,7 +26,7 @@ from rx.subject.subject import Subject from ...context import Context from ...datetimes import utc_now -from ...market import Market +from ...markets import Market from ...observables import Disposable, DisposeWrapper from ...oracle import ( Oracle, diff --git a/mango/oracles/market/market.py b/mango/oracles/market/market.py index d8fa9ff..55fa14c 100644 --- a/mango/oracles/market/market.py +++ b/mango/oracles/market/market.py @@ -22,9 +22,8 @@ from decimal import Decimal from ...context import Context from ...datetimes import utc_now -from ...ensuremarketloaded import ensure_market_loaded from ...loadedmarket import LoadedMarket -from ...market import Market +from ...markets import Market from ...observables import observable_pipeline_error_reporter from ...oracle import ( Oracle, @@ -34,6 +33,7 @@ from ...oracle import ( SupportedOracleFeature, ) from ...orders import OrderBook +from ...porcelain import market as porcelain_market # # 🥭 Market @@ -118,7 +118,7 @@ class MarketOracleProvider(OracleProvider): def oracle_for_market( self, context: Context, market: Market ) -> typing.Optional[Oracle]: - loaded_market: LoadedMarket = ensure_market_loaded(context, market) + loaded_market: LoadedMarket = porcelain_market(context, market.symbol) return MarketOracle(loaded_market) def all_available_symbols(self, context: Context) -> typing.Sequence[str]: diff --git a/mango/oracles/pythnetwork/pythnetwork.py b/mango/oracles/pythnetwork/pythnetwork.py index c3abc9a..dfa48dd 100644 --- a/mango/oracles/pythnetwork/pythnetwork.py +++ b/mango/oracles/pythnetwork/pythnetwork.py @@ -25,7 +25,7 @@ from solana.publickey import PublicKey from ...accountinfo import AccountInfo from ...context import Context from ...datetimes import utc_now -from ...market import Market +from ...markets import Market from ...observables import observable_pipeline_error_reporter from ...oracle import ( Oracle, diff --git a/mango/oracles/stub/stub.py b/mango/oracles/stub/stub.py index 9ea3954..8e2d822 100644 --- a/mango/oracles/stub/stub.py +++ b/mango/oracles/stub/stub.py @@ -24,8 +24,8 @@ from solana.publickey import PublicKey from ...cache import Cache from ...context import Context from ...datetimes import utc_now -from ...ensuremarketloaded import ensure_market_loaded -from ...market import Market +from ...loadedmarket import LoadedMarket +from ...markets import Market from ...observables import observable_pipeline_error_reporter from ...oracle import ( Oracle, @@ -35,6 +35,7 @@ from ...oracle import ( SupportedOracleFeature, ) from ...perpmarket import PerpMarket +from ...porcelain import market as porcelain_market from ...spotmarket import SpotMarket @@ -117,7 +118,7 @@ class StubOracleProvider(OracleProvider): def oracle_for_market( self, context: Context, market: Market ) -> typing.Optional[Oracle]: - loaded_market: Market = ensure_market_loaded(context, market) + loaded_market: LoadedMarket = porcelain_market(context, market.symbol) if SpotMarket.isa(loaded_market): spot_market = SpotMarket.ensure(loaded_market) spot_index: int = spot_market.group.slot_by_spot_market_address( diff --git a/mango/perpaccount.py b/mango/perpaccount.py index f213335..0ac5679 100644 --- a/mango/perpaccount.py +++ b/mango/perpaccount.py @@ -21,7 +21,7 @@ from .cache import PerpMarketCache from .instrumentvalue import InstrumentValue from .lotsizeconverter import LotSizeConverter from .perpopenorders import PerpOpenOrders -from .token import Instrument, Token +from .tokens import Instrument, Token # # 🥭 PerpAccount class diff --git a/mango/perpmarket.py b/mango/perpmarket.py index 6995958..3143a26 100644 --- a/mango/perpmarket.py +++ b/mango/perpmarket.py @@ -38,7 +38,7 @@ from .instructions import ( ) from .loadedmarket import LoadedMarket from .lotsizeconverter import LotSizeConverter, RaisingLotSizeConverter -from .market import InventorySource, MarketType, Market +from .markets import InventorySource, MarketType, Market from .marketoperations import MarketInstructionBuilder, MarketOperations from .observables import Disposable from .orderbookside import PerpOrderBookSide @@ -51,7 +51,7 @@ from .perpeventqueue import ( ) from .perpmarketdetails import PerpMarketDetails from .publickey import encode_public_key_for_sorting -from .token import Instrument, Token +from .tokens import Instrument, Token from .tokenbank import TokenBank from .wallet import Wallet from .websocketsubscription import ( @@ -418,6 +418,14 @@ class PerpMarketOperations(MarketOperations): ) self.account: Account = account + @staticmethod + def ensure(market_ops: MarketOperations) -> "PerpMarketOperations": + if not isinstance(market_ops, PerpMarketOperations): + raise Exception( + f"MarketOperations for {market_ops.symbol} is not a PerpMarketOperations" + ) + return market_ops + @property def perp_market(self) -> PerpMarket: return self.market_instruction_builder.perp_market diff --git a/mango/perpmarketdetails.py b/mango/perpmarketdetails.py index 2fb2972..2da21e7 100644 --- a/mango/perpmarketdetails.py +++ b/mango/perpmarketdetails.py @@ -27,7 +27,7 @@ from .group import GroupSlot, Group from .instrumentvalue import InstrumentValue from .layouts import layouts from .metadata import Metadata -from .token import Instrument, Token +from .tokens import Instrument, Token from .tokenbank import TokenBank from .version import Version diff --git a/mango/porcelain.py b/mango/porcelain.py index 39d8420..4ea3404 100644 --- a/mango/porcelain.py +++ b/mango/porcelain.py @@ -13,9 +13,12 @@ # [Github](https://github.com/blockworks-foundation) # [Email](mailto:hello@blockworks.foundation) +from decimal import Decimal + from .account import Account from .context import Context from .group import Group +from .instrumentvalue import InstrumentValue from .loadedmarket import LoadedMarket from .marketoperations import ( MarketInstructionBuilder, @@ -41,10 +44,45 @@ from .spotmarket import ( SpotMarketInstructionBuilder, SpotMarketOperations, ) +from .tokens import Instrument, Token from .wallet import Wallet -# # 🥭 load_market +# # 🥭 instrument +# +# This function takes a `Context` and an instrument symbol string (like "ETH") and returns a +# properly loaded `Instrument` object. It throws if anything goes wrong rather than return None. +# +# An Instrument can represent a Perp or an SPL token. +# +def instrument(context: Context, symbol: str) -> Instrument: + return context.instrument(symbol) + + +# # 🥭 token +# +# This function takes a `Context` and a token symbol string (like "ETH") and returns a +# properly loaded `Token` object. It throws if anything goes wrong rather than return None. +# +# An Token can only represent an SPL token. It cannot represent a Perp. +# +def token(context: Context, symbol: str) -> Token: + return context.token(symbol) + + +# # 🥭 instrument_value +# +# This function takes a `Context` and an instrument symbol string (like "ETH") and returns a +# properly loaded `Instrument` object. It throws if anything goes wrong rather than return None. +# +# An Instrument can represent a Perp or an SPL token. +# +def instrument_value(context: Context, symbol: str, value: Decimal) -> InstrumentValue: + ins = context.instrument(symbol) + return InstrumentValue(ins, value) + + +# # 🥭 market # # This function takes a `Context` and a market symbol string (like "ETH/USDC") and returns a # properly loaded market. It throws if anything goes wrong rather than return None. diff --git a/mango/serummarket.py b/mango/serummarket.py index bbdb251..a0e9041 100644 --- a/mango/serummarket.py +++ b/mango/serummarket.py @@ -33,14 +33,14 @@ from .instructions import ( ) from .loadedmarket import LoadedMarket from .lotsizeconverter import LotSizeConverter, RaisingLotSizeConverter -from .market import InventorySource, Market, MarketType +from .markets import InventorySource, Market, MarketType from .marketoperations import MarketInstructionBuilder, MarketOperations from .openorders import OpenOrders from .observables import Disposable from .orders import Order, OrderBook, Side from .publickey import encode_public_key_for_sorting from .serumeventqueue import SerumEvent, SerumEventQueue, UnseenSerumEventChangesTracker -from .token import Instrument, Token +from .tokens import Instrument, Token from .tokenaccount import TokenAccount from .wallet import Wallet from .websocketsubscription import ( @@ -411,6 +411,14 @@ class SerumMarketOperations(MarketOperations): market_instruction_builder ) + @staticmethod + def ensure(market_ops: MarketOperations) -> "SerumMarketOperations": + if not isinstance(market_ops, SerumMarketOperations): + raise Exception( + f"MarketOperations for {market_ops.symbol} is not a SerumMarketOperations" + ) + return market_ops + @property def serum_market(self) -> SerumMarket: return self.market_instruction_builder.serum_market diff --git a/mango/serummarketlookup.py b/mango/serummarketlookup.py index daefb6d..f450d06 100644 --- a/mango/serummarketlookup.py +++ b/mango/serummarketlookup.py @@ -20,10 +20,10 @@ import typing from decimal import Decimal from solana.publickey import PublicKey -from .market import Market +from .markets import Market from .marketlookup import MarketLookup from .serummarket import SerumMarketStub -from .token import Instrument, Token +from .tokens import Instrument, Token # # 🥭 SerumMarketLookup class diff --git a/mango/spotmarket.py b/mango/spotmarket.py index 45ed6cb..85d6623 100644 --- a/mango/spotmarket.py +++ b/mango/spotmarket.py @@ -37,13 +37,13 @@ from .instructions import ( ) from .loadedmarket import LoadedMarket from .lotsizeconverter import LotSizeConverter, RaisingLotSizeConverter -from .market import InventorySource, MarketType, Market +from .markets import InventorySource, MarketType, Market from .marketoperations import MarketInstructionBuilder, MarketOperations from .observables import Disposable from .orders import Order, OrderBook from .publickey import encode_public_key_for_sorting from .serumeventqueue import SerumEvent, SerumEventQueue, UnseenSerumEventChangesTracker -from .token import Token +from .tokens import Token from .wallet import Wallet from .websocketsubscription import ( IndividualWebSocketSubscriptionManager, @@ -440,6 +440,14 @@ class SpotMarketOperations(MarketOperations): PublicKey ] = self.account.spot_open_orders_by_index[self.market_index] + @staticmethod + def ensure(market_ops: MarketOperations) -> "SpotMarketOperations": + if not isinstance(market_ops, SpotMarketOperations): + raise Exception( + f"MarketOperations for {market_ops.symbol} is not a SpotMarketOperations" + ) + return market_ops + @property def spot_market(self) -> SpotMarket: return self.market_instruction_builder.spot_market diff --git a/mango/tokenaccount.py b/mango/tokenaccount.py index e120de7..dfb058c 100644 --- a/mango/tokenaccount.py +++ b/mango/tokenaccount.py @@ -30,7 +30,7 @@ from .context import Context from .instrumentlookup import InstrumentLookup from .instrumentvalue import InstrumentValue from .layouts import layouts -from .token import Instrument, Token +from .tokens import Instrument, Token from .version import Version from .wallet import Wallet diff --git a/mango/tokenbank.py b/mango/tokenbank.py index 39689e2..b2fcc11 100644 --- a/mango/tokenbank.py +++ b/mango/tokenbank.py @@ -28,7 +28,7 @@ from .context import Context from .instrumentlookup import InstrumentLookup from .layouts import layouts from .metadata import Metadata -from .token import Instrument, Token +from .tokens import Instrument, Token from .version import Version diff --git a/mango/token.py b/mango/tokens.py similarity index 100% rename from mango/token.py rename to mango/tokens.py diff --git a/mango/walletbalancer.py b/mango/walletbalancer.py index 94cf726..b7dba6b 100644 --- a/mango/walletbalancer.py +++ b/mango/walletbalancer.py @@ -25,7 +25,7 @@ from .context import Context from .group import Group from .marketoperations import MarketOperations from .porcelain import operations -from .token import Instrument, Token +from .tokens import Instrument, Token from .instrumentvalue import InstrumentValue from .wallet import Wallet diff --git a/mango/watchers.py b/mango/watchers.py index 3802d22..80cc18d 100644 --- a/mango/watchers.py +++ b/mango/watchers.py @@ -31,7 +31,7 @@ from .instructions import build_create_serum_open_orders_instructions from .instrumentvalue import InstrumentValue from .inventory import Inventory from .loadedmarket import LoadedMarket -from .market import Market, InventorySource +from .markets import Market, InventorySource from .modelstate import EventQueue from .observables import Disposable, LatestItemObserverSubscriber from .openorders import OpenOrders @@ -46,7 +46,7 @@ from .serumeventqueue import SerumEventQueue from .serummarket import SerumMarket from .spotmarket import SpotMarket, SpotMarketInstructionBuilder, SpotMarketOperations from .tokenaccount import TokenAccount -from .token import Instrument, Token +from .tokens import Instrument, Token from .wallet import Wallet from .watcher import Watcher, LamdaUpdateWatcher from .websocketsubscription import (