Added compound instruction builder for placing Serum orders, cranking and settling all in one go.
This commit is contained in:
parent
e61a3806ba
commit
857d033572
|
@ -183,6 +183,37 @@ def build_serum_settle_instructions(context: Context, wallet: Wallet, market: Ma
|
|||
return [instruction]
|
||||
|
||||
|
||||
# # 🥭 build_serum_place_order_instructions function
|
||||
#
|
||||
# This function puts a trade on the Serum orderbook and then cranks and settles.
|
||||
# It follows the pattern described here:
|
||||
# https://solanadev.blogspot.com/2021/05/order-techniques-with-project-serum.html
|
||||
#
|
||||
# Here's an example (Raydium?) transaction that does this:
|
||||
# https://solanabeach.io/transaction/3Hb2h7QMM3BbJCK42BUDuVEYwwaiqfp2oQUZMDJvUuoyCRJD5oBmA3B8oAGkB9McdCFtwdT2VrSKM2GCKhJ92FpY
|
||||
#
|
||||
# Basically, it tries to send to a 'buy/sell' and settle all in one transaction.
|
||||
#
|
||||
# It does this by:
|
||||
# * Sending a Place Order (V3) instruction
|
||||
# * Sending a Consume Events (crank) instruction
|
||||
# * Sending a Settle Funds instruction
|
||||
# all in the same transaction. With V3 Serum, this should consistently settle funds to the wallet
|
||||
# immediately if the order is filled (either because it's IOC or because it matches an order on the
|
||||
# orderbook).
|
||||
#
|
||||
|
||||
def build_compound_serum_place_order_instructions(context: Context, wallet: Wallet, market: Market, source: PublicKey, open_orders_address: PublicKey, all_open_orders_addresses: typing.Sequence[PublicKey], order_type: OrderType, side: Side, price: Decimal, quantity: Decimal, client_id: int, base_token_account_address: PublicKey, quote_token_account_address: PublicKey, fee_discount_address: typing.Optional[PublicKey], consume_limit: int = 32) -> typing.Sequence[TransactionInstruction]:
|
||||
place_order = build_serum_place_order_instructions(
|
||||
context, wallet, market, source, open_orders_address, order_type, side, price, quantity, client_id, fee_discount_address)
|
||||
consume_events = build_serum_consume_events_instructions(
|
||||
context, wallet, market, all_open_orders_addresses, consume_limit)
|
||||
settle = build_serum_settle_instructions(
|
||||
context, wallet, market, open_orders_address, base_token_account_address, quote_token_account_address)
|
||||
|
||||
return [*place_order, *consume_events, *settle]
|
||||
|
||||
|
||||
# # 🥭 build_cancel_perp_order_instruction function
|
||||
#
|
||||
# Builds the instructions necessary for cancelling a perp order.
|
||||
|
|
|
@ -28,7 +28,7 @@ from solana.publickey import PublicKey
|
|||
from solana.transaction import Transaction
|
||||
|
||||
from .context import Context
|
||||
from .instructions import build_create_serum_open_orders_instructions, build_serum_place_order_instructions, build_serum_consume_events_instructions, build_serum_settle_instructions
|
||||
from .instructions import build_compound_serum_place_order_instructions, build_create_serum_open_orders_instructions
|
||||
from .retrier import retry_context
|
||||
from .spotmarket import SpotMarket
|
||||
from .tokenaccount import TokenAccount
|
||||
|
@ -96,21 +96,12 @@ class NullTradeExecutor(TradeExecutor):
|
|||
# # 🥭 SerumImmediateTradeExecutor class
|
||||
#
|
||||
# This class puts an IOC trade on the Serum orderbook with the expectation it will be filled
|
||||
# immediately. It follows the pattern described here:
|
||||
# immediately. It uses the build_compound_serum_place_order_instructions function which follows
|
||||
# the pattern described here:
|
||||
# https://solanadev.blogspot.com/2021/05/order-techniques-with-project-serum.html
|
||||
#
|
||||
# Here's an example (Raydium?) transaction that does this:
|
||||
# https://solanabeach.io/transaction/3Hb2h7QMM3BbJCK42BUDuVEYwwaiqfp2oQUZMDJvUuoyCRJD5oBmA3B8oAGkB9McdCFtwdT2VrSKM2GCKhJ92FpY
|
||||
#
|
||||
# Basically, it tries to send to a 'market buy/sell' and settle all in one transaction.
|
||||
#
|
||||
# It does this by:
|
||||
# * Sending a Place Order (V3) instruction
|
||||
# * Sending a Consume Events (crank) instruction
|
||||
# * Sending a Settle Funds instruction
|
||||
# all in the same transaction. With V3 Serum, this should work (assuming the IOC order
|
||||
# is filled).
|
||||
#
|
||||
# It also creates the Serum OpenOrders account for the transaction if it doesn't
|
||||
# already exist.
|
||||
#
|
||||
|
@ -259,20 +250,9 @@ class SerumImmediateTradeExecutor(TradeExecutor):
|
|||
open_orders_addresses = list(oo.address for oo in open_order_accounts)
|
||||
|
||||
client_id = self.context.random_client_id()
|
||||
new_order = build_serum_place_order_instructions(self.context, self.wallet, market,
|
||||
source_token_account_address,
|
||||
open_orders_address, OrderType.IOC,
|
||||
side, price, quantity, client_id,
|
||||
self.serum_fee_discount_token_address)
|
||||
transaction.instructions.extend(new_order)
|
||||
|
||||
consume_events = build_serum_consume_events_instructions(
|
||||
self.context, self.wallet, market, open_orders_addresses)
|
||||
transaction.instructions.extend(consume_events)
|
||||
|
||||
settle = build_serum_settle_instructions(self.context, self.wallet, market,
|
||||
open_orders_address, base_token_account_address, quote_token_account_address)
|
||||
transaction.instructions.extend(settle)
|
||||
place_order_instructions = build_compound_serum_place_order_instructions(self.context, self.wallet, market, source_token_account_address, open_orders_address,
|
||||
open_orders_addresses, OrderType.IOC, side, price, quantity, client_id, base_token_account_address, quote_token_account_address, self.serum_fee_discount_token_address)
|
||||
transaction.instructions.extend(place_order_instructions)
|
||||
|
||||
with retry_context("Place Serum Order And Settle", self.context.client.send_transaction, self.context.retry_pauses) as retrier:
|
||||
response = retrier.run(transaction, *signers, opts=self.context.transaction_options)
|
||||
|
|
Loading…
Reference in New Issue