acta_maker_sdk/orders/
spreads.rs1use sha2::{Digest, Sha256};
2
3use super::{ORDER_DOMAIN_TAG, ORDER_ID_LEN, SignerLike, sign_order_id_with_signer};
4use crate::spreads::{SpreadError, SpreadType, validate_premium};
5use crate::types::TakerSide;
6
7pub const SPREAD_ORDER_PREIMAGE_LEN: usize = 190;
9
10#[derive(Debug, Clone)]
11pub struct SpreadOrderPreimageArgs {
12 pub chain_id: u64,
13 pub program_id: [u8; 32],
14 pub side: TakerSide,
15 pub position_type: SpreadType,
16 pub market: [u8; 32],
17 pub lower_strike: u64,
18 pub upper_strike: u64,
19 pub quantity: u64,
20 pub gross_price: u64,
21 pub valid_until: u64,
22 pub maker: [u8; 32],
23 pub taker: [u8; 32],
24 pub nonce: u64,
25}
26
27pub fn build_spread_order_preimage(
28 args: &SpreadOrderPreimageArgs,
29) -> Result<[u8; SPREAD_ORDER_PREIMAGE_LEN], SpreadError> {
30 validate_premium(
31 args.position_type,
32 args.lower_strike,
33 args.upper_strike,
34 args.quantity,
35 args.gross_price,
36 )?;
37 let mut bytes = [0; SPREAD_ORDER_PREIMAGE_LEN];
38 bytes[..4].copy_from_slice(&ORDER_DOMAIN_TAG);
39 bytes[4..12].copy_from_slice(&args.chain_id.to_le_bytes());
40 bytes[12..44].copy_from_slice(&args.program_id);
41 bytes[44] = u8::from(args.side.is_taker_buy());
42 bytes[45] = args.position_type as u8;
43 bytes[46..78].copy_from_slice(&args.market);
44 for (offset, value) in [
45 (78, args.lower_strike),
46 (86, args.quantity),
47 (94, args.gross_price),
48 (102, args.valid_until),
49 (174, args.nonce),
50 (182, args.upper_strike),
51 ] {
52 bytes[offset..offset + 8].copy_from_slice(&value.to_le_bytes());
53 }
54 bytes[110..142].copy_from_slice(&args.maker);
55 bytes[142..174].copy_from_slice(&args.taker);
56 Ok(bytes)
57}
58
59pub fn compute_spread_order_id(
60 args: &SpreadOrderPreimageArgs,
61) -> Result<[u8; ORDER_ID_LEN], SpreadError> {
62 Ok(Sha256::digest(build_spread_order_preimage(args)?).into())
63}
64
65pub fn sign_spread_order<S: SignerLike + ?Sized>(
66 args: &SpreadOrderPreimageArgs,
67 signer: &S,
68) -> Result<([u8; ORDER_ID_LEN], [u8; 64]), SpreadError> {
69 if args.side.is_taker_buy() {
70 return Err(SpreadError::TakerBuyUnsupported);
71 }
72 let order_id = compute_spread_order_id(args)?;
73 Ok((order_id, sign_order_id_with_signer(&order_id, signer)))
74}