take_offer.rs 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. use escrow_api::prelude::*;
  2. use steel::*;
  3. pub fn process_take_offer(accounts: &[AccountInfo<'_>], _data: &[u8]) -> ProgramResult {
  4. // Load accounts.
  5. let [taker_info, maker_info, mint_a_info, mint_b_info, taker_token_account_a_info, taker_token_account_b_info, maker_token_account_b_info, offer_info, vault_info, token_program, system_program, associated_token_program] =
  6. accounts
  7. else {
  8. return Err(ProgramError::NotEnoughAccountKeys);
  9. };
  10. taker_info.is_signer()?;
  11. token_program.is_program(&spl_token::ID)?;
  12. system_program.is_program(&system_program::ID)?;
  13. associated_token_program.is_program(&ASSOCIATED_TOKEN_PROGRAM_ID)?;
  14. let vaul = vault_info.as_associated_token_account(offer_info.key, mint_a_info.key)?;
  15. // validate mint
  16. let _mint_a = mint_a_info.as_mint()?;
  17. let _mint_b = mint_b_info.as_mint()?;
  18. if taker_token_account_a_info.data_is_empty() {
  19. create_associated_token_account(
  20. taker_info,
  21. taker_info,
  22. taker_token_account_a_info,
  23. mint_a_info,
  24. system_program,
  25. token_program,
  26. associated_token_program,
  27. )?;
  28. }
  29. let _taker_token_account_b = taker_token_account_b_info
  30. .is_writable()?
  31. .as_associated_token_account(taker_info.key, mint_b_info.key)?;
  32. if maker_token_account_b_info.data_is_empty() {
  33. create_associated_token_account(
  34. taker_info,
  35. maker_info,
  36. maker_token_account_b_info,
  37. mint_b_info,
  38. system_program,
  39. token_program,
  40. associated_token_program,
  41. )?;
  42. }
  43. offer_info.is_writable()?;
  44. let offer: &mut Offer = offer_info.as_account_mut::<Offer>(&escrow_api::ID)?;
  45. offer_info.has_seeds(
  46. &[OFFER_SEED, offer.maker.as_ref(), offer.id.as_ref()],
  47. &escrow_api::ID,
  48. )?;
  49. // transfer wanted token from taker to maker
  50. let token_b_wanted_amount = u64::from_le_bytes(offer.token_b_wanted_amount);
  51. transfer(
  52. taker_info,
  53. taker_token_account_b_info,
  54. maker_token_account_b_info,
  55. token_program,
  56. token_b_wanted_amount,
  57. )?;
  58. // // widthdraw token A from vault
  59. transfer_signed_with_bump(
  60. offer_info,
  61. vault_info,
  62. taker_token_account_a_info,
  63. token_program,
  64. vaul.amount,
  65. &[OFFER_SEED, offer.maker.as_ref(), offer.id.as_ref()],
  66. offer.bump,
  67. )?;
  68. let seeds = &[
  69. OFFER_SEED,
  70. offer.maker.as_ref(),
  71. offer.id.as_ref(),
  72. &[offer.bump],
  73. ];
  74. let signer_seeds = &[&seeds[..]];
  75. // close vault account
  76. solana_program::program::invoke_signed(
  77. &spl_token::instruction::close_account(
  78. &spl_token::ID,
  79. vault_info.key,
  80. taker_info.key,
  81. offer_info.key,
  82. &[&offer_info.key],
  83. )?,
  84. &[
  85. token_program.clone(),
  86. vault_info.clone(),
  87. taker_info.clone(),
  88. offer_info.clone(),
  89. ],
  90. signer_seeds,
  91. )?;
  92. // close offer account
  93. offer_info.close(maker_info)?;
  94. Ok(())
  95. }