Skip to main content

acta_maker_sdk/orders/
spreads.rs

1use 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
7/// Spread layout: the physical layout under the shared `ACTA` domain, then upper strike.
8pub 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    let order_id = compute_spread_order_id(args)?;
70    Ok((order_id, sign_order_id_with_signer(&order_id, signer)))
71}