proxy.rs 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. use crate::dex;
  2. use crate::dex::middleware::{Context, ErrorCode, MarketMiddleware};
  3. use anchor_lang::prelude::*;
  4. use anchor_lang::solana_program::program;
  5. use anchor_lang::solana_program::pubkey::Pubkey;
  6. use serum_dex::instruction::*;
  7. /// MarketProxy provides an abstraction for implementing proxy programs to the
  8. /// Serum orderbook, allowing one to implement a middleware for the purposes
  9. /// of intercepting and modifying requests before being relayed to the
  10. /// orderbook.
  11. ///
  12. /// The only requirement for a middleware is that, when all are done processing,
  13. /// a valid DEX instruction--accounts and instruction data--must be left to
  14. /// forward to the orderbook program.
  15. #[derive(Default)]
  16. pub struct MarketProxy<'a> {
  17. middlewares: Vec<&'a mut dyn MarketMiddleware>,
  18. }
  19. impl<'a> MarketProxy<'a> {
  20. /// Constructs a new `MarketProxy`.
  21. pub fn new() -> Self {
  22. Self {
  23. middlewares: Vec::new(),
  24. }
  25. }
  26. /// Builder method for adding a middleware to the proxy.
  27. pub fn middleware(mut self, mw: &'a mut dyn MarketMiddleware) -> Self {
  28. self.middlewares.push(mw);
  29. self
  30. }
  31. /// Entrypoint to the program.
  32. pub fn run(
  33. mut self,
  34. program_id: &Pubkey,
  35. accounts: &[AccountInfo],
  36. data: &[u8],
  37. ) -> ProgramResult {
  38. let mut ix_data = data;
  39. // First account is the Serum DEX executable--used for CPI.
  40. let dex = &accounts[0];
  41. require!(dex.key == &dex::ID, ErrorCode::InvalidTargetProgram);
  42. let acc_infos = (&accounts[1..]).to_vec();
  43. // Process the instruction data.
  44. for mw in &mut self.middlewares {
  45. mw.instruction(&mut ix_data)?;
  46. }
  47. // Request context.
  48. let mut ctx = Context::new(program_id, dex.key, acc_infos);
  49. // Decode instruction.
  50. let ix = MarketInstruction::unpack(ix_data);
  51. // Method dispatch.
  52. match ix {
  53. Some(MarketInstruction::InitOpenOrders) => {
  54. require!(ctx.accounts.len() >= 4, ErrorCode::NotEnoughAccounts);
  55. for mw in &self.middlewares {
  56. mw.init_open_orders(&mut ctx)?;
  57. }
  58. }
  59. Some(MarketInstruction::NewOrderV3(ix)) => {
  60. require!(ctx.accounts.len() >= 12, ErrorCode::NotEnoughAccounts);
  61. for mw in &self.middlewares {
  62. mw.new_order_v3(&mut ctx, &ix)?;
  63. }
  64. }
  65. Some(MarketInstruction::CancelOrderV2(ix)) => {
  66. require!(ctx.accounts.len() >= 6, ErrorCode::NotEnoughAccounts);
  67. for mw in &self.middlewares {
  68. mw.cancel_order_v2(&mut ctx, &ix)?;
  69. }
  70. }
  71. Some(MarketInstruction::CancelOrderByClientIdV2(ix)) => {
  72. require!(ctx.accounts.len() >= 6, ErrorCode::NotEnoughAccounts);
  73. for mw in &self.middlewares {
  74. mw.cancel_order_by_client_id_v2(&mut ctx, ix)?;
  75. }
  76. }
  77. Some(MarketInstruction::SettleFunds) => {
  78. require!(ctx.accounts.len() >= 10, ErrorCode::NotEnoughAccounts);
  79. for mw in &self.middlewares {
  80. mw.settle_funds(&mut ctx)?;
  81. }
  82. }
  83. Some(MarketInstruction::CloseOpenOrders) => {
  84. require!(ctx.accounts.len() >= 4, ErrorCode::NotEnoughAccounts);
  85. for mw in &self.middlewares {
  86. mw.close_open_orders(&mut ctx)?;
  87. }
  88. }
  89. Some(MarketInstruction::Prune(limit)) => {
  90. require!(ctx.accounts.len() >= 7, ErrorCode::NotEnoughAccounts);
  91. for mw in &self.middlewares {
  92. mw.prune(&mut ctx, limit)?;
  93. }
  94. }
  95. _ => {
  96. for mw in &self.middlewares {
  97. mw.fallback(&mut ctx)?;
  98. }
  99. return Ok(());
  100. }
  101. };
  102. // Extract the middleware adjusted context.
  103. let Context {
  104. seeds,
  105. accounts,
  106. pre_instructions,
  107. post_instructions,
  108. ..
  109. } = ctx;
  110. // Execute pre instructions.
  111. for (ix, acc_infos, seeds) in pre_instructions {
  112. let tmp_signers: Vec<Vec<&[u8]>> = seeds
  113. .iter()
  114. .map(|seeds| {
  115. let seeds: Vec<&[u8]> = seeds.iter().map(|seed| &seed[..]).collect();
  116. seeds
  117. })
  118. .collect();
  119. let signers: Vec<&[&[u8]]> = tmp_signers.iter().map(|seeds| &seeds[..]).collect();
  120. program::invoke_signed(&ix, &acc_infos, &signers)?;
  121. }
  122. // Execute the main dex relay.
  123. {
  124. let tmp_signers: Vec<Vec<&[u8]>> = seeds
  125. .iter()
  126. .map(|seeds| {
  127. let seeds: Vec<&[u8]> = seeds.iter().map(|seed| &seed[..]).collect();
  128. seeds
  129. })
  130. .collect();
  131. let signers: Vec<&[&[u8]]> = tmp_signers.iter().map(|seeds| &seeds[..]).collect();
  132. // CPI to the DEX.
  133. let dex_accounts = accounts
  134. .iter()
  135. .map(|acc| AccountMeta {
  136. pubkey: *acc.key,
  137. is_signer: acc.is_signer,
  138. is_writable: acc.is_writable,
  139. })
  140. .collect();
  141. let ix = anchor_lang::solana_program::instruction::Instruction {
  142. data: ix_data.to_vec(),
  143. accounts: dex_accounts,
  144. program_id: dex::ID,
  145. };
  146. program::invoke_signed(&ix, &accounts, &signers)?;
  147. }
  148. // Execute post instructions.
  149. for (ix, acc_infos, seeds) in post_instructions {
  150. let tmp_signers: Vec<Vec<&[u8]>> = seeds
  151. .iter()
  152. .map(|seeds| {
  153. let seeds: Vec<&[u8]> = seeds.iter().map(|seed| &seed[..]).collect();
  154. seeds
  155. })
  156. .collect();
  157. let signers: Vec<&[&[u8]]> = tmp_signers.iter().map(|seeds| &seeds[..]).collect();
  158. program::invoke_signed(&ix, &acc_infos, &signers)?;
  159. }
  160. Ok(())
  161. }
  162. }