1use {
2 crate::{
3 accounts,
4 instruction,
5 ExpressRelayMetadata,
6 FeeToken,
7 SubmitBidArgs,
8 SwapV2Args,
9 SEED_CONFIG_ROUTER,
10 SEED_METADATA,
11 },
12 anchor_lang::{
13 prelude::*,
14 solana_program::{
15 instruction::Instruction,
16 sysvar::instructions as sysvar_instructions,
17 },
18 system_program,
19 InstructionData,
20 },
21 anchor_spl::associated_token::{
22 self,
23 get_associated_token_address_with_program_id,
24 },
25};
26
27#[allow(clippy::too_many_arguments)]
29pub fn add_submit_bid_instruction(
30 ixs: &mut Vec<Instruction>,
31 express_relay_pid: Pubkey,
32 searcher: Pubkey,
33 relayer_signer: Pubkey,
34 fee_receiver_relayer: Pubkey,
35 permission: Pubkey,
36 router: Pubkey,
37 bid_amount: u64,
38 deadline: i64,
39) -> Vec<Instruction> {
40 let ix_submit_bid = create_submit_bid_instruction(
41 express_relay_pid,
42 searcher,
43 relayer_signer,
44 fee_receiver_relayer,
45 permission,
46 router,
47 deadline,
48 bid_amount,
49 );
50 ixs.push(ix_submit_bid);
51
52 ixs.to_vec()
53}
54
55#[allow(clippy::too_many_arguments)]
56pub fn create_submit_bid_instruction(
57 express_relay_pid: Pubkey,
58 searcher: Pubkey,
59 relayer_signer: Pubkey,
60 fee_receiver_relayer: Pubkey,
61 permission: Pubkey,
62 router: Pubkey,
63 deadline: i64,
64 bid_amount: u64,
65) -> Instruction {
66 let config_router =
67 Pubkey::find_program_address(&[SEED_CONFIG_ROUTER, router.as_ref()], &express_relay_pid).0;
68 let express_relay_metadata =
69 Pubkey::find_program_address(&[SEED_METADATA], &express_relay_pid).0;
70
71 let accounts_submit_bid = accounts::SubmitBid {
72 searcher,
73 relayer_signer,
74 permission,
75 router,
76 config_router,
77 fee_receiver_relayer,
78 express_relay_metadata,
79 system_program: system_program::ID,
80 sysvar_instructions: sysvar_instructions::ID,
81 }
82 .to_account_metas(None);
83 let data_submit_bid = instruction::SubmitBid {
84 data: SubmitBidArgs {
85 deadline,
86 bid_amount,
87 },
88 }
89 .data();
90
91 Instruction {
92 program_id: express_relay_pid,
93 accounts: accounts_submit_bid,
94 data: data_submit_bid,
95 }
96}
97
98#[allow(clippy::too_many_arguments)]
99pub fn create_swap_instruction(
100 express_relay_pid: Pubkey,
101 searcher: Pubkey,
102 user: Pubkey,
103 searcher_ta_mint_searcher: Option<Pubkey>,
104 searcher_ta_mint_user: Option<Pubkey>,
105 router_fee_receiver_ta: Pubkey,
106 fee_receiver_relayer: Pubkey,
107 mint_searcher: Pubkey,
108 mint_user: Pubkey,
109 token_program_searcher: Pubkey,
110 token_program_user: Pubkey,
111 swap_args: SwapV2Args,
112 relayer_signer: Pubkey,
113) -> Instruction {
114 let express_relay_metadata =
115 Pubkey::find_program_address(&[SEED_METADATA], &express_relay_pid).0;
116
117 let (mint_fee, token_program_fee) = match swap_args.fee_token {
118 FeeToken::Searcher => (mint_searcher, token_program_searcher),
119 FeeToken::User => (mint_user, token_program_user),
120 };
121
122 let accounts_swap = accounts::Swap {
123 searcher,
124 user,
125 searcher_ta_mint_searcher: searcher_ta_mint_searcher.unwrap_or(
126 get_associated_token_address_with_program_id(
127 &searcher,
128 &mint_searcher,
129 &token_program_searcher,
130 ),
131 ),
132 searcher_ta_mint_user: searcher_ta_mint_user.unwrap_or(
133 get_associated_token_address_with_program_id(
134 &searcher,
135 &mint_user,
136 &token_program_user,
137 ),
138 ),
139 user_ata_mint_searcher: get_associated_token_address_with_program_id(
140 &user,
141 &mint_searcher,
142 &token_program_searcher,
143 ),
144 user_ata_mint_user: get_associated_token_address_with_program_id(
145 &user,
146 &mint_user,
147 &token_program_user,
148 ),
149 router_fee_receiver_ta,
150 relayer_fee_receiver_ata: get_associated_token_address_with_program_id(
151 &fee_receiver_relayer,
152 &mint_fee,
153 &token_program_fee,
154 ),
155 express_relay_fee_receiver_ata: get_associated_token_address_with_program_id(
156 &express_relay_metadata,
157 &mint_fee,
158 &token_program_fee,
159 ),
160 mint_searcher,
161 mint_user,
162 mint_fee,
163 token_program_searcher,
164 token_program_user,
165 token_program_fee,
166 express_relay_metadata,
167 relayer_signer,
168 }
169 .to_account_metas(None);
170 let data_submit_bid = instruction::SwapV2 { data: swap_args }.data();
171
172 Instruction {
173 program_id: express_relay_pid,
174 accounts: accounts_swap,
175 data: data_submit_bid,
176 }
177}
178
179pub fn deserialize_metadata(data: Vec<u8>) -> Result<ExpressRelayMetadata> {
180 let buf = &mut &data[..];
181 match ExpressRelayMetadata::try_deserialize(buf) {
182 Ok(metadata) => Ok(metadata),
183 Err(_) => Err(ProgramError::InvalidAccountData.into()),
184 }
185}
186
187pub fn create_associated_token_account_idempotent(
189 funding_address: &Pubkey,
190 wallet_address: &Pubkey,
191 token_mint_address: &Pubkey,
192 token_program_id: &Pubkey,
193) -> Instruction {
194 build_associated_token_account_instruction(
195 funding_address,
196 wallet_address,
197 token_mint_address,
198 token_program_id,
199 1, )
201}
202
203fn build_associated_token_account_instruction(
204 funding_address: &Pubkey,
205 wallet_address: &Pubkey,
206 token_mint_address: &Pubkey,
207 token_program_id: &Pubkey,
208 instruction: u8,
209) -> Instruction {
210 let associated_account_address = get_associated_token_address_with_program_id(
211 wallet_address,
212 token_mint_address,
213 token_program_id,
214 );
215 assert!(instruction <= 1);
217 Instruction {
218 program_id: associated_token::ID,
219 accounts: vec![
220 AccountMeta::new(*funding_address, true),
221 AccountMeta::new(associated_account_address, false),
222 AccountMeta::new_readonly(*wallet_address, false),
223 AccountMeta::new_readonly(*token_mint_address, false),
224 AccountMeta::new_readonly(system_program::ID, false),
225 AccountMeta::new_readonly(*token_program_id, false),
226 ],
227 data: vec![instruction],
228 }
229}