@@ -1077,10 +1077,199 @@ pub fn update_orderbook(
10771077/// Account context: MatchOrdersAccounts (7 accounts)
10781078/// Args: MatchOrdersArgs
10791079pub fn match_orders (
1080- _program_id : & Address ,
1081- _accounts : & mut [ AccountView ] ,
1080+ program_id : & Address ,
1081+ accounts : & mut [ AccountView ] ,
10821082 _instruction_data : & [ u8 ] ,
10831083) -> ProgramResult {
1084+ let ctx = crate :: instruction:: MatchOrdersAccounts :: try_from ( & * accounts) ?;
1085+
1086+ if !ctx. market . owned_by ( program_id) {
1087+ return Err ( FluxDexError :: InvalidAccountOwner . into ( ) ) ;
1088+ }
1089+
1090+ let ( m_authority, m_base_mint, m_quote_mint, m_bump, m_fee_bps) = {
1091+ let data = ctx
1092+ . market
1093+ . try_borrow ( )
1094+ . map_err ( |_| FluxDexError :: InvalidInstructionData ) ?;
1095+ let market = Market :: from_account ( & data) ?;
1096+ (
1097+ market. authority ,
1098+ market. base_mint ,
1099+ market. quote_mint ,
1100+ market. bump ,
1101+ market. fee_bps ( ) ,
1102+ )
1103+ } ;
1104+
1105+ if ctx. crank_authority . address ( ) . to_bytes ( ) != m_authority {
1106+ return Err ( FluxDexError :: UnauthorizedCrank . into ( ) ) ;
1107+ }
1108+
1109+ let market_pda = Address :: create_program_address (
1110+ & [ b"market" , & m_base_mint, & m_quote_mint, & [ m_bump] ] ,
1111+ program_id,
1112+ )
1113+ . map_err ( |_| FluxDexError :: InvalidPdaSeeds ) ?;
1114+ if & market_pda != ctx. market . address ( ) {
1115+ return Err ( FluxDexError :: InvalidPdaSeeds . into ( ) ) ;
1116+ }
1117+
1118+ let market_bytes = ctx. market . address ( ) . to_bytes ( ) ;
1119+ let ( orderbook_pda, _) =
1120+ Address :: find_program_address ( & [ b"orderbook" , & market_bytes] , program_id) ;
1121+ if & orderbook_pda != ctx. orderbook . address ( ) {
1122+ return Err ( FluxDexError :: InvalidPdaSeeds . into ( ) ) ;
1123+ }
1124+
1125+ if !ctx. buyer_order . owned_by ( program_id) || !ctx. seller_order . owned_by ( program_id) {
1126+ return Err ( FluxDexError :: InvalidAccountOwner . into ( ) ) ;
1127+ }
1128+
1129+ let ( b_side, b_status, b_price, b_quantity, b_filled, b_trader, b_id, b_bump, b_market) = {
1130+ let data = ctx
1131+ . buyer_order
1132+ . try_borrow ( )
1133+ . map_err ( |_| FluxDexError :: InvalidInstructionData ) ?;
1134+ let o = Order :: from_account ( & data) ?;
1135+ (
1136+ o. side ( ) ?,
1137+ o. status ( ) ?,
1138+ o. price ( ) ,
1139+ o. quantity ( ) ,
1140+ o. filled ( ) ,
1141+ o. trader ,
1142+ o. client_order_id ( ) ,
1143+ o. bump ,
1144+ o. market ,
1145+ )
1146+ } ;
1147+
1148+ let ( s_side, s_status, s_price, s_quantity, s_filled, s_trader, s_id, s_bump, s_market) = {
1149+ let data = ctx
1150+ . seller_order
1151+ . try_borrow ( )
1152+ . map_err ( |_| FluxDexError :: InvalidInstructionData ) ?;
1153+ let o = Order :: from_account ( & data) ?;
1154+ (
1155+ o. side ( ) ?,
1156+ o. status ( ) ?,
1157+ o. price ( ) ,
1158+ o. quantity ( ) ,
1159+ o. filled ( ) ,
1160+ o. trader ,
1161+ o. client_order_id ( ) ,
1162+ o. bump ,
1163+ o. market ,
1164+ )
1165+ } ;
1166+
1167+ if b_market != market_bytes || s_market != market_bytes {
1168+ return Err ( FluxDexError :: InvalidArgument . into ( ) ) ;
1169+ }
1170+
1171+ let b_order_pda = Address :: create_program_address (
1172+ & [
1173+ b"order" ,
1174+ & market_bytes,
1175+ & b_trader,
1176+ & b_id. to_le_bytes ( ) ,
1177+ & [ b_bump] ,
1178+ ] ,
1179+ program_id,
1180+ )
1181+ . map_err ( |_| FluxDexError :: InvalidPdaSeeds ) ?;
1182+ if & b_order_pda != ctx. buyer_order . address ( ) {
1183+ return Err ( FluxDexError :: InvalidPdaSeeds . into ( ) ) ;
1184+ }
1185+
1186+ let s_order_pda = Address :: create_program_address (
1187+ & [
1188+ b"order" ,
1189+ & market_bytes,
1190+ & s_trader,
1191+ & s_id. to_le_bytes ( ) ,
1192+ & [ s_bump] ,
1193+ ] ,
1194+ program_id,
1195+ )
1196+ . map_err ( |_| FluxDexError :: InvalidPdaSeeds ) ?;
1197+ if & s_order_pda != ctx. seller_order . address ( ) {
1198+ return Err ( FluxDexError :: InvalidPdaSeeds . into ( ) ) ;
1199+ }
1200+
1201+ if b_status != OrderStatus :: Open || s_status != OrderStatus :: Open {
1202+ return Err ( FluxDexError :: OrderNotOpen . into ( ) ) ;
1203+ }
1204+
1205+ if b_side != Side :: Buy || s_side != Side :: Sell {
1206+ return Err ( FluxDexError :: InvalidArgument . into ( ) ) ;
1207+ }
1208+
1209+ if b_price != s_price {
1210+ return Err ( FluxDexError :: InvalidArgument . into ( ) ) ;
1211+ }
1212+
1213+ if b_trader == s_trader {
1214+ return Err ( FluxDexError :: InvalidArgument . into ( ) ) ;
1215+ }
1216+
1217+ let b_remaining = b_quantity
1218+ . checked_sub ( b_filled)
1219+ . ok_or ( FluxDexError :: ArithmeticOverflow ) ?;
1220+ let s_remaining = s_quantity
1221+ . checked_sub ( s_filled)
1222+ . ok_or ( FluxDexError :: ArithmeticOverflow ) ?;
1223+
1224+ if b_remaining == 0 || s_remaining == 0 {
1225+ return Err ( FluxDexError :: InvalidArgument . into ( ) ) ;
1226+ }
1227+
1228+ let fill_quantity = b_remaining. min ( s_remaining) ;
1229+ let fill_price = b_price;
1230+
1231+ let _fee = fill_price
1232+ . checked_mul ( fill_quantity)
1233+ . ok_or ( FluxDexError :: ArithmeticOverflow ) ?
1234+ . checked_mul ( m_fee_bps as u64 )
1235+ . ok_or ( FluxDexError :: ArithmeticOverflow ) ?
1236+ . checked_div ( 10000 )
1237+ . ok_or ( FluxDexError :: ArithmeticOverflow ) ?;
1238+
1239+ let new_b_filled = b_filled
1240+ . checked_add ( fill_quantity)
1241+ . ok_or ( FluxDexError :: ArithmeticOverflow ) ?;
1242+ let new_s_filled = s_filled
1243+ . checked_add ( fill_quantity)
1244+ . ok_or ( FluxDexError :: ArithmeticOverflow ) ?;
1245+
1246+ let b_fully_filled = new_b_filled == b_quantity;
1247+ let s_fully_filled = new_s_filled == s_quantity;
1248+
1249+ {
1250+ let buyer_account = & mut accounts[ 5 ] ; // MatchOrdersAccounts buyer_order index
1251+ let mut buyer_data = buyer_account
1252+ . try_borrow_mut ( )
1253+ . map_err ( |_| FluxDexError :: InvalidInstructionData ) ?;
1254+ let order = Order :: from_account_mut ( & mut buyer_data) ?;
1255+ order. filled = new_b_filled. to_le_bytes ( ) ;
1256+ if b_fully_filled {
1257+ order. status = u8:: from ( OrderStatus :: Filled ) ;
1258+ }
1259+ }
1260+
1261+ {
1262+ let seller_account = & mut accounts[ 6 ] ; // MatchOrdersAccounts seller_order index
1263+ let mut seller_data = seller_account
1264+ . try_borrow_mut ( )
1265+ . map_err ( |_| FluxDexError :: InvalidInstructionData ) ?;
1266+ let order = Order :: from_account_mut ( & mut seller_data) ?;
1267+ order. filled = new_s_filled. to_le_bytes ( ) ;
1268+ if s_fully_filled {
1269+ order. status = u8:: from ( OrderStatus :: Filled ) ;
1270+ }
1271+ }
1272+
10841273 Ok ( ( ) )
10851274}
10861275
0 commit comments