dex.rs 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. use anchor_lang::solana_program::account_info::AccountInfo;
  2. use anchor_lang::solana_program::program_error::ProgramError;
  3. use anchor_lang::solana_program::pubkey::Pubkey;
  4. use anchor_lang::{context::CpiContext, Accounts, Result, ToAccountInfos};
  5. use serum_dex::instruction::SelfTradeBehavior;
  6. use serum_dex::matching::{OrderType, Side};
  7. use std::num::NonZeroU64;
  8. pub use serum_dex;
  9. #[cfg(not(feature = "devnet"))]
  10. anchor_lang::solana_program::declare_id!("9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin");
  11. #[cfg(feature = "devnet")]
  12. anchor_lang::solana_program::declare_id!("DESVgJVGajEgKGXhb6XmqDHGz3VjdgP7rEVESBgxmroY");
  13. #[allow(clippy::too_many_arguments)]
  14. pub fn new_order_v3<'info>(
  15. ctx: CpiContext<'_, '_, '_, 'info, NewOrderV3<'info>>,
  16. side: Side,
  17. limit_price: NonZeroU64,
  18. max_coin_qty: NonZeroU64,
  19. max_native_pc_qty_including_fees: NonZeroU64,
  20. self_trade_behavior: SelfTradeBehavior,
  21. order_type: OrderType,
  22. client_order_id: u64,
  23. limit: u16,
  24. ) -> Result<()> {
  25. let referral = ctx.remaining_accounts.get(0);
  26. let ix = serum_dex::instruction::new_order(
  27. ctx.accounts.market.key,
  28. ctx.accounts.open_orders.key,
  29. ctx.accounts.request_queue.key,
  30. ctx.accounts.event_queue.key,
  31. ctx.accounts.market_bids.key,
  32. ctx.accounts.market_asks.key,
  33. ctx.accounts.order_payer_token_account.key,
  34. ctx.accounts.open_orders_authority.key,
  35. ctx.accounts.coin_vault.key,
  36. ctx.accounts.pc_vault.key,
  37. ctx.accounts.token_program.key,
  38. ctx.accounts.rent.key,
  39. referral.map(|r| r.key),
  40. &ID,
  41. side,
  42. limit_price,
  43. max_coin_qty,
  44. order_type,
  45. client_order_id,
  46. self_trade_behavior,
  47. limit,
  48. max_native_pc_qty_including_fees,
  49. )
  50. .map_err(|pe| ProgramError::from(pe))?;
  51. solana_program::program::invoke_signed(
  52. &ix,
  53. &ToAccountInfos::to_account_infos(&ctx),
  54. ctx.signer_seeds,
  55. )?;
  56. Ok(())
  57. }
  58. pub fn cancel_order_v2<'info>(
  59. ctx: CpiContext<'_, '_, '_, 'info, CancelOrderV2<'info>>,
  60. side: Side,
  61. order_id: u128,
  62. ) -> Result<()> {
  63. let ix = serum_dex::instruction::cancel_order(
  64. &ID,
  65. ctx.accounts.market.key,
  66. ctx.accounts.market_bids.key,
  67. ctx.accounts.market_asks.key,
  68. ctx.accounts.open_orders.key,
  69. ctx.accounts.open_orders_authority.key,
  70. ctx.accounts.event_queue.key,
  71. side,
  72. order_id,
  73. )
  74. .map_err(|pe| ProgramError::from(pe))?;
  75. solana_program::program::invoke_signed(
  76. &ix,
  77. &ToAccountInfos::to_account_infos(&ctx),
  78. ctx.signer_seeds,
  79. )?;
  80. Ok(())
  81. }
  82. pub fn settle_funds<'info>(ctx: CpiContext<'_, '_, '_, 'info, SettleFunds<'info>>) -> Result<()> {
  83. let referral = ctx.remaining_accounts.get(0);
  84. let ix = serum_dex::instruction::settle_funds(
  85. &ID,
  86. ctx.accounts.market.key,
  87. ctx.accounts.token_program.key,
  88. ctx.accounts.open_orders.key,
  89. ctx.accounts.open_orders_authority.key,
  90. ctx.accounts.coin_vault.key,
  91. ctx.accounts.coin_wallet.key,
  92. ctx.accounts.pc_vault.key,
  93. ctx.accounts.pc_wallet.key,
  94. referral.map(|r| r.key),
  95. ctx.accounts.vault_signer.key,
  96. )
  97. .map_err(|pe| ProgramError::from(pe))?;
  98. solana_program::program::invoke_signed(
  99. &ix,
  100. &ToAccountInfos::to_account_infos(&ctx),
  101. ctx.signer_seeds,
  102. )?;
  103. Ok(())
  104. }
  105. pub fn init_open_orders<'info>(
  106. ctx: CpiContext<'_, '_, '_, 'info, InitOpenOrders<'info>>,
  107. ) -> Result<()> {
  108. let ix = serum_dex::instruction::init_open_orders(
  109. &ID,
  110. ctx.accounts.open_orders.key,
  111. ctx.accounts.authority.key,
  112. ctx.accounts.market.key,
  113. ctx.remaining_accounts.first().map(|acc| acc.key),
  114. )
  115. .map_err(|pe| ProgramError::from(pe))?;
  116. solana_program::program::invoke_signed(
  117. &ix,
  118. &ToAccountInfos::to_account_infos(&ctx),
  119. ctx.signer_seeds,
  120. )?;
  121. Ok(())
  122. }
  123. pub fn close_open_orders<'info>(
  124. ctx: CpiContext<'_, '_, '_, 'info, CloseOpenOrders<'info>>,
  125. ) -> Result<()> {
  126. let ix = serum_dex::instruction::close_open_orders(
  127. &ID,
  128. ctx.accounts.open_orders.key,
  129. ctx.accounts.authority.key,
  130. ctx.accounts.destination.key,
  131. ctx.accounts.market.key,
  132. )
  133. .map_err(|pe| ProgramError::from(pe))?;
  134. solana_program::program::invoke_signed(
  135. &ix,
  136. &ToAccountInfos::to_account_infos(&ctx),
  137. ctx.signer_seeds,
  138. )?;
  139. Ok(())
  140. }
  141. pub fn sweep_fees<'info>(ctx: CpiContext<'_, '_, '_, 'info, SweepFees<'info>>) -> Result<()> {
  142. let ix = serum_dex::instruction::sweep_fees(
  143. &ID,
  144. ctx.accounts.market.key,
  145. ctx.accounts.pc_vault.key,
  146. ctx.accounts.sweep_authority.key,
  147. ctx.accounts.sweep_receiver.key,
  148. ctx.accounts.vault_signer.key,
  149. ctx.accounts.token_program.key,
  150. )
  151. .map_err(|pe| ProgramError::from(pe))?;
  152. solana_program::program::invoke_signed(
  153. &ix,
  154. &ToAccountInfos::to_account_infos(&ctx),
  155. ctx.signer_seeds,
  156. )?;
  157. Ok(())
  158. }
  159. pub fn initialize_market<'info>(
  160. ctx: CpiContext<'_, '_, '_, 'info, InitializeMarket<'info>>,
  161. coin_lot_size: u64,
  162. pc_lot_size: u64,
  163. vault_signer_nonce: u64,
  164. pc_dust_threshold: u64,
  165. ) -> Result<()> {
  166. let authority = ctx.remaining_accounts.get(0);
  167. let prune_authority = ctx.remaining_accounts.get(1);
  168. let ix = serum_dex::instruction::initialize_market(
  169. ctx.accounts.market.key,
  170. &ID,
  171. ctx.accounts.coin_mint.key,
  172. ctx.accounts.pc_mint.key,
  173. ctx.accounts.coin_vault.key,
  174. ctx.accounts.pc_vault.key,
  175. authority.map(|r| r.key),
  176. prune_authority.map(|r| r.key),
  177. ctx.accounts.bids.key,
  178. ctx.accounts.asks.key,
  179. ctx.accounts.req_q.key,
  180. ctx.accounts.event_q.key,
  181. coin_lot_size,
  182. pc_lot_size,
  183. vault_signer_nonce,
  184. pc_dust_threshold,
  185. )
  186. .map_err(|pe| ProgramError::from(pe))?;
  187. solana_program::program::invoke_signed(
  188. &ix,
  189. &ToAccountInfos::to_account_infos(&ctx),
  190. ctx.signer_seeds,
  191. )?;
  192. Ok(())
  193. }
  194. #[derive(Accounts)]
  195. pub struct NewOrderV3<'info> {
  196. pub market: AccountInfo<'info>,
  197. pub open_orders: AccountInfo<'info>,
  198. pub request_queue: AccountInfo<'info>,
  199. pub event_queue: AccountInfo<'info>,
  200. pub market_bids: AccountInfo<'info>,
  201. pub market_asks: AccountInfo<'info>,
  202. // Token account where funds are transferred from for the order. If
  203. // posting a bid market A/B, then this is the SPL token account for B.
  204. pub order_payer_token_account: AccountInfo<'info>,
  205. pub open_orders_authority: AccountInfo<'info>,
  206. // Also known as the "base" currency. For a given A/B market,
  207. // this is the vault for the A mint.
  208. pub coin_vault: AccountInfo<'info>,
  209. // Also known as the "quote" currency. For a given A/B market,
  210. // this is the vault for the B mint.
  211. pub pc_vault: AccountInfo<'info>,
  212. pub token_program: AccountInfo<'info>,
  213. pub rent: AccountInfo<'info>,
  214. }
  215. #[derive(Accounts)]
  216. pub struct CancelOrderV2<'info> {
  217. pub market: AccountInfo<'info>,
  218. pub market_bids: AccountInfo<'info>,
  219. pub market_asks: AccountInfo<'info>,
  220. pub open_orders: AccountInfo<'info>,
  221. pub open_orders_authority: AccountInfo<'info>,
  222. pub event_queue: AccountInfo<'info>,
  223. }
  224. #[derive(Accounts)]
  225. pub struct SettleFunds<'info> {
  226. pub market: AccountInfo<'info>,
  227. pub open_orders: AccountInfo<'info>,
  228. pub open_orders_authority: AccountInfo<'info>,
  229. pub coin_vault: AccountInfo<'info>,
  230. pub pc_vault: AccountInfo<'info>,
  231. pub coin_wallet: AccountInfo<'info>,
  232. pub pc_wallet: AccountInfo<'info>,
  233. pub vault_signer: AccountInfo<'info>,
  234. pub token_program: AccountInfo<'info>,
  235. }
  236. /// To use an (optional) market authority, add it as the first account of the
  237. /// CpiContext's `remaining_accounts` Vec.
  238. #[derive(Accounts)]
  239. pub struct InitOpenOrders<'info> {
  240. pub open_orders: AccountInfo<'info>,
  241. pub authority: AccountInfo<'info>,
  242. pub market: AccountInfo<'info>,
  243. pub rent: AccountInfo<'info>,
  244. }
  245. #[derive(Accounts)]
  246. pub struct CloseOpenOrders<'info> {
  247. pub open_orders: AccountInfo<'info>,
  248. pub authority: AccountInfo<'info>,
  249. pub destination: AccountInfo<'info>,
  250. pub market: AccountInfo<'info>,
  251. }
  252. #[derive(Accounts)]
  253. pub struct SweepFees<'info> {
  254. pub market: AccountInfo<'info>,
  255. pub pc_vault: AccountInfo<'info>,
  256. pub sweep_authority: AccountInfo<'info>,
  257. pub sweep_receiver: AccountInfo<'info>,
  258. pub vault_signer: AccountInfo<'info>,
  259. pub token_program: AccountInfo<'info>,
  260. }
  261. #[derive(Accounts)]
  262. pub struct InitializeMarket<'info> {
  263. pub market: AccountInfo<'info>,
  264. pub coin_mint: AccountInfo<'info>,
  265. pub pc_mint: AccountInfo<'info>,
  266. pub coin_vault: AccountInfo<'info>,
  267. pub pc_vault: AccountInfo<'info>,
  268. pub bids: AccountInfo<'info>,
  269. pub asks: AccountInfo<'info>,
  270. pub req_q: AccountInfo<'info>,
  271. pub event_q: AccountInfo<'info>,
  272. pub rent: AccountInfo<'info>,
  273. }
  274. #[derive(Clone)]
  275. pub struct Dex;
  276. impl anchor_lang::Id for Dex {
  277. fn id() -> Pubkey {
  278. ID
  279. }
  280. }