@@ -14,9 +14,10 @@ use crate::{
1414 market:: Market ,
1515 resolution:: MarketResult ,
1616 storage:: {
17- get_bet as load_bet, get_market as load_market, get_market_count,
18- get_market_pool as load_market_pool, get_market_result as load_market_result,
19- get_next_market_id, save_bet, save_market, save_market_pool, save_market_result,
17+ add_market_bettor, get_bet as load_bet, get_market as load_market, get_market_bettors,
18+ get_market_count, get_market_pool as load_market_pool,
19+ get_market_result as load_market_result, get_next_market_id, is_reward_claimed,
20+ mark_reward_claimed, save_bet, save_market, save_market_pool, save_market_result,
2021 } ,
2122} ;
2223use soroban_sdk:: { contract, contractimpl, Address , Env , String , Vec } ;
@@ -128,6 +129,7 @@ impl PredictXContract {
128129 . ok_or ( PredictXError :: MarketPoolOverflow ) ?;
129130
130131 save_bet ( & env, & bet) ;
132+ add_market_bettor ( & env, market_id, & bet. bettor ) ;
131133 save_market_pool ( & env, market_id, market_pool) ;
132134
133135 Ok ( ( ) )
@@ -184,6 +186,64 @@ impl PredictXContract {
184186 resolved : market. resolved ,
185187 } )
186188 }
189+
190+ pub fn calculate_reward (
191+ env : Env ,
192+ market_id : u64 ,
193+ bettor : Address ,
194+ ) -> Result < i128 , PredictXError > {
195+ let market = load_market ( & env, market_id) . ok_or ( PredictXError :: MarketNotFound ) ?;
196+
197+ if !market. resolved {
198+ return Err ( PredictXError :: MarketNotResolved ) ;
199+ }
200+
201+ let result = load_market_result ( & env, market_id) . ok_or ( PredictXError :: MarketNotResolved ) ?;
202+ let winning_outcome = result
203+ . winning_outcome
204+ . ok_or ( PredictXError :: MarketNotResolved ) ?;
205+ let user_bet = load_bet ( & env, market_id, & bettor) . ok_or ( PredictXError :: BetNotFound ) ?;
206+
207+ if user_bet. outcome_index != winning_outcome {
208+ return Err ( PredictXError :: NotWinningBet ) ;
209+ }
210+
211+ let bettors = get_market_bettors ( & env, market_id) ;
212+ let mut total_winning_pool = 0_i128 ;
213+
214+ for index in 0 ..bettors. len ( ) {
215+ let market_bettor = bettors. get ( index) . unwrap ( ) ;
216+ if let Some ( bet) = load_bet ( & env, market_id, & market_bettor) {
217+ if bet. outcome_index == winning_outcome {
218+ total_winning_pool = total_winning_pool
219+ . checked_add ( bet. amount )
220+ . ok_or ( PredictXError :: RewardCalculationOverflow ) ?;
221+ }
222+ }
223+ }
224+
225+ let total_market_pool = load_market_pool ( & env, market_id) ;
226+
227+ user_bet
228+ . amount
229+ . checked_mul ( total_market_pool)
230+ . ok_or ( PredictXError :: RewardCalculationOverflow )
231+ . map ( |weighted_bet| weighted_bet / total_winning_pool)
232+ }
233+
234+ pub fn claim_reward ( env : Env , market_id : u64 , bettor : Address ) -> Result < i128 , PredictXError > {
235+ if is_reward_claimed ( & env, market_id, & bettor) {
236+ return Err ( PredictXError :: RewardAlreadyClaimed ) ;
237+ }
238+
239+ bettor. require_auth ( ) ;
240+
241+ let reward = Self :: calculate_reward ( env. clone ( ) , market_id, bettor. clone ( ) ) ?;
242+
243+ mark_reward_claimed ( & env, market_id, & bettor) ;
244+
245+ Ok ( reward)
246+ }
187247}
188248
189249#[ cfg( test) ]
0 commit comments