Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion crates/autopilot-svm/src/domain/auction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

use {
crate::run_loop::AuctionInfo,
chain_types::solana::{IntentHash, Pubkey},
chain_types::solana::{AppData, IntentHash, Pubkey},
};

/// Whether the order sells an exact amount or buys an exact amount.
Expand All @@ -30,6 +30,10 @@ pub struct Order {
pub valid_to: u32,
pub kind: OrderKind,
pub partially_fillable: bool,
/// The 32-byte app-data hash of the on-chain intent. An input to the
/// intent hash (the uid), so the driver needs it verbatim to rebuild the
/// intent at settlement.
pub app_data: AppData,
pub order_pda: Pubkey,
}

Expand Down Expand Up @@ -71,6 +75,7 @@ mod tests {
valid_to: 42,
kind: OrderKind::Sell,
partially_fillable: false,
app_data: chain_types::solana::AppData([8; 32]),
order_pda: chain_types::solana::Pubkey([7; 32]),
}
}
Expand Down
7 changes: 5 additions & 2 deletions crates/autopilot-svm/src/infra/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use {
crate::domain::auction::{Auction, Order, OrderKind},
anyhow::{Context, Result, bail},
bigdecimal::{BigDecimal, ToPrimitive},
chain_types::solana::{IntentHash, Pubkey},
chain_types::solana::{AppData, IntentHash, Pubkey},
database::byte_array::ByteArray,
sqlx::PgExecutor,
};
Expand All @@ -23,6 +23,7 @@ pub struct OrderRow {
pub valid_to: i64,
pub kind: String,
pub partially_fillable: bool,
pub app_data: ByteArray<32>,
pub order_pda: ByteArray<32>,
}

Expand All @@ -35,7 +36,7 @@ pub async fn open_orders(ex: impl PgExecutor<'_>, now_unix: i64) -> Result<Vec<O
const QUERY: &str = r#"
SELECT o.uid, o.owner, o.sell_token, o.buy_token, o.sell_token_account,
o.buy_token_account, o.sell_amount, o.buy_amount, o.valid_to,
o.kind::text AS kind, o.partially_fillable, o.order_pda
o.kind::text AS kind, o.partially_fillable, o.app_data, o.order_pda
FROM solana.orders o
LEFT JOIN solana.order_pda p ON p.order_uid = o.uid
WHERE o.valid_to >= $1
Expand Down Expand Up @@ -145,6 +146,7 @@ impl TryFrom<OrderRow> for Order {
other => bail!("unknown order kind {other:?}"),
},
partially_fillable: row.partially_fillable,
app_data: AppData(row.app_data.0),
order_pda: Pubkey(row.order_pda.0),
})
}
Expand Down Expand Up @@ -179,6 +181,7 @@ mod tests {
valid_to: 42,
kind: "sell".to_owned(),
partially_fillable: false,
app_data: ByteArray([8; 32]),
order_pda: ByteArray([7; 32]),
}
}
Expand Down
12 changes: 11 additions & 1 deletion crates/autopilot-svm/src/infra/driver/dto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

use {
crate::domain::auction,
chain_types::solana::{IntentHash, Pubkey, Signature},
chain_types::solana::{AppData, IntentHash, Pubkey, Signature},
serde::{Deserialize, Serialize},
serde_with::{DisplayFromStr, serde_as},
std::collections::HashMap,
Expand Down Expand Up @@ -49,6 +49,10 @@ pub struct Order {
pub valid_to: u32,
pub kind: Kind,
pub partially_fillable: bool,
/// The 32-byte app-data hash of the on-chain intent, `0x`-hex on the
/// wire like the uid.
#[serde_as(as = "DisplayFromStr")]
pub app_data: AppData,
#[serde_as(as = "DisplayFromStr")]
pub order_pda: Pubkey,
}
Expand Down Expand Up @@ -78,6 +82,7 @@ impl From<&auction::Order> for Order {
auction::OrderKind::Buy => Kind::Buy,
},
partially_fillable: order.partially_fillable,
app_data: order.app_data,
order_pda: order.order_pda,
}
}
Expand Down Expand Up @@ -156,6 +161,7 @@ mod tests {
valid_to: 42,
kind: auction::OrderKind::Sell,
partially_fillable: false,
app_data: AppData([0x88; 32]),
order_pda: Pubkey([0x77; 32]),
}
}
Expand All @@ -179,6 +185,10 @@ mod tests {
// u64::MAX survives as a decimal string.
assert_eq!(json["orders"][0]["sellAmount"], "18446744073709551615");
assert_eq!(json["orders"][0]["kind"], "sell");
assert_eq!(
json["orders"][0]["appData"],
"0x8888888888888888888888888888888888888888888888888888888888888888"
);
// Base58 of 32 bytes of 0x22, precomputed so this does not just
// compare the Display impl against itself.
assert_eq!(
Expand Down
23 changes: 23 additions & 0 deletions crates/chain-types/src/solana.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,29 @@ impl FromStr for IntentHash {
}
}

/// The 32-byte app-data hash of an order intent. An input to the intent
/// hash, so settlement encoding must carry it verbatim.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct AppData(pub [u8; 32]);

/// `0x`-prefixed hex, the wire and log rendering of an app-data hash.
impl fmt::Display for AppData {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut buffer = const_hex::Buffer::<32, true>::new();
f.write_str(buffer.format(&self.0))
}
}

impl FromStr for AppData {
type Err = const_hex::FromHexError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut bytes = [0u8; 32];
const_hex::decode_to_slice(s.strip_prefix("0x").unwrap_or(s), &mut bytes)?;
Ok(Self(bytes))
}
}

/// Base58, the canonical Solana address rendering.
impl fmt::Display for Pubkey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Expand Down
Loading