1use solana_sdk::pubkey::Pubkey;
6
7use crate::program::constants::{
8 CONDITIONAL_MINT_SEED, EXCHANGE_SEED, MARKET_SEED, MINT_AUTHORITY_SEED, ORDER_STATUS_SEED,
9 POSITION_SEED, USER_NONCE_SEED, VAULT_SEED,
10};
11
12pub fn get_exchange_pda(program_id: &Pubkey) -> (Pubkey, u8) {
16 Pubkey::find_program_address(&[EXCHANGE_SEED], program_id)
17}
18
19pub fn get_market_pda(market_id: u64, program_id: &Pubkey) -> (Pubkey, u8) {
23 Pubkey::find_program_address(&[MARKET_SEED, &market_id.to_le_bytes()], program_id)
24}
25
26pub fn get_vault_pda(deposit_mint: &Pubkey, market: &Pubkey, program_id: &Pubkey) -> (Pubkey, u8) {
30 Pubkey::find_program_address(
31 &[VAULT_SEED, deposit_mint.as_ref(), market.as_ref()],
32 program_id,
33 )
34}
35
36pub fn get_mint_authority_pda(market: &Pubkey, program_id: &Pubkey) -> (Pubkey, u8) {
40 Pubkey::find_program_address(&[MINT_AUTHORITY_SEED, market.as_ref()], program_id)
41}
42
43pub fn get_conditional_mint_pda(
47 market: &Pubkey,
48 deposit_mint: &Pubkey,
49 outcome_index: u8,
50 program_id: &Pubkey,
51) -> (Pubkey, u8) {
52 Pubkey::find_program_address(
53 &[
54 CONDITIONAL_MINT_SEED,
55 market.as_ref(),
56 deposit_mint.as_ref(),
57 &[outcome_index],
58 ],
59 program_id,
60 )
61}
62
63pub fn get_all_conditional_mint_pdas(
65 market: &Pubkey,
66 deposit_mint: &Pubkey,
67 num_outcomes: u8,
68 program_id: &Pubkey,
69) -> Vec<(Pubkey, u8)> {
70 (0..num_outcomes)
71 .map(|i| get_conditional_mint_pda(market, deposit_mint, i, program_id))
72 .collect()
73}
74
75pub fn get_order_status_pda(order_hash: &[u8; 32], program_id: &Pubkey) -> (Pubkey, u8) {
79 Pubkey::find_program_address(&[ORDER_STATUS_SEED, order_hash], program_id)
80}
81
82pub fn get_user_nonce_pda(user: &Pubkey, program_id: &Pubkey) -> (Pubkey, u8) {
86 Pubkey::find_program_address(&[USER_NONCE_SEED, user.as_ref()], program_id)
87}
88
89pub fn get_position_pda(owner: &Pubkey, market: &Pubkey, program_id: &Pubkey) -> (Pubkey, u8) {
93 Pubkey::find_program_address(&[POSITION_SEED, owner.as_ref(), market.as_ref()], program_id)
94}
95
96pub struct Pda;
98
99impl Pda {
100 pub fn exchange(program_id: &Pubkey) -> (Pubkey, u8) {
102 get_exchange_pda(program_id)
103 }
104
105 pub fn market(market_id: u64, program_id: &Pubkey) -> (Pubkey, u8) {
107 get_market_pda(market_id, program_id)
108 }
109
110 pub fn vault(deposit_mint: &Pubkey, market: &Pubkey, program_id: &Pubkey) -> (Pubkey, u8) {
112 get_vault_pda(deposit_mint, market, program_id)
113 }
114
115 pub fn mint_authority(market: &Pubkey, program_id: &Pubkey) -> (Pubkey, u8) {
117 get_mint_authority_pda(market, program_id)
118 }
119
120 pub fn conditional_mint(
122 market: &Pubkey,
123 deposit_mint: &Pubkey,
124 outcome_index: u8,
125 program_id: &Pubkey,
126 ) -> (Pubkey, u8) {
127 get_conditional_mint_pda(market, deposit_mint, outcome_index, program_id)
128 }
129
130 pub fn all_conditional_mints(
132 market: &Pubkey,
133 deposit_mint: &Pubkey,
134 num_outcomes: u8,
135 program_id: &Pubkey,
136 ) -> Vec<(Pubkey, u8)> {
137 get_all_conditional_mint_pdas(market, deposit_mint, num_outcomes, program_id)
138 }
139
140 pub fn order_status(order_hash: &[u8; 32], program_id: &Pubkey) -> (Pubkey, u8) {
142 get_order_status_pda(order_hash, program_id)
143 }
144
145 pub fn user_nonce(user: &Pubkey, program_id: &Pubkey) -> (Pubkey, u8) {
147 get_user_nonce_pda(user, program_id)
148 }
149
150 pub fn position(owner: &Pubkey, market: &Pubkey, program_id: &Pubkey) -> (Pubkey, u8) {
152 get_position_pda(owner, market, program_id)
153 }
154}
155
156#[cfg(test)]
157mod tests {
158 use super::*;
159 use std::str::FromStr;
160
161 fn test_program_id() -> Pubkey {
162 Pubkey::from_str("EfRvELrn4b5aJRwddD1VUrqzsfm1pewBLPebq3iMPDp2").unwrap()
163 }
164
165 #[test]
166 fn test_exchange_pda_is_deterministic() {
167 let program_id = test_program_id();
168 let (pda1, bump1) = get_exchange_pda(&program_id);
169 let (pda2, bump2) = get_exchange_pda(&program_id);
170
171 assert_eq!(pda1, pda2);
172 assert_eq!(bump1, bump2);
173 }
174
175 #[test]
176 fn test_market_pda_is_deterministic() {
177 let program_id = test_program_id();
178 let (pda1, bump1) = get_market_pda(0, &program_id);
179 let (pda2, bump2) = get_market_pda(0, &program_id);
180
181 assert_eq!(pda1, pda2);
182 assert_eq!(bump1, bump2);
183 }
184
185 #[test]
186 fn test_different_market_ids_produce_different_pdas() {
187 let program_id = test_program_id();
188 let (pda1, _) = get_market_pda(0, &program_id);
189 let (pda2, _) = get_market_pda(1, &program_id);
190
191 assert_ne!(pda1, pda2);
192 }
193
194 #[test]
195 fn test_position_pda_is_deterministic() {
196 let program_id = test_program_id();
197 let owner = Pubkey::new_unique();
198 let market = Pubkey::new_unique();
199
200 let (pda1, bump1) = get_position_pda(&owner, &market, &program_id);
201 let (pda2, bump2) = get_position_pda(&owner, &market, &program_id);
202
203 assert_eq!(pda1, pda2);
204 assert_eq!(bump1, bump2);
205 }
206
207 #[test]
208 fn test_conditional_mint_pdas() {
209 let program_id = test_program_id();
210 let market = Pubkey::new_unique();
211 let deposit_mint = Pubkey::new_unique();
212
213 let pdas = get_all_conditional_mint_pdas(&market, &deposit_mint, 3, &program_id);
214 assert_eq!(pdas.len(), 3);
215
216 assert_ne!(pdas[0].0, pdas[1].0);
218 assert_ne!(pdas[1].0, pdas[2].0);
219 assert_ne!(pdas[0].0, pdas[2].0);
220 }
221
222 #[test]
223 fn test_order_status_pda() {
224 let program_id = test_program_id();
225 let order_hash = [42u8; 32];
226
227 let (pda1, bump1) = get_order_status_pda(&order_hash, &program_id);
228 let (pda2, bump2) = get_order_status_pda(&order_hash, &program_id);
229
230 assert_eq!(pda1, pda2);
231 assert_eq!(bump1, bump2);
232 }
233
234 #[test]
235 fn test_pda_struct_methods() {
236 let program_id = test_program_id();
237 let owner = Pubkey::new_unique();
238 let market = Pubkey::new_unique();
239
240 assert_eq!(
242 Pda::exchange(&program_id),
243 get_exchange_pda(&program_id)
244 );
245 assert_eq!(
246 Pda::market(5, &program_id),
247 get_market_pda(5, &program_id)
248 );
249 assert_eq!(
250 Pda::position(&owner, &market, &program_id),
251 get_position_pda(&owner, &market, &program_id)
252 );
253 }
254}