Skip to content

Commit 92b9d51

Browse files
authored
Add solana api skeleton (#125)
1 parent a5c91c8 commit 92b9d51

File tree

6 files changed

+228
-10
lines changed

6 files changed

+228
-10
lines changed

auction-server/Cargo.lock

Lines changed: 126 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

auction-server/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "auction-server"
3-
version = "0.9.8"
3+
version = "0.10.0"
44
edition = "2021"
55
license-file = "license.txt"
66

@@ -39,3 +39,5 @@ opentelemetry = "0.23.0"
3939
opentelemetry_sdk = { version = "0.23.0", features = ["rt-tokio"]}
4040
opentelemetry-otlp = { version = "0.16.0" }
4141
gas-oracle = { path = "../gas-oracle" }
42+
serde_with = { version = "3.9.0", features = ["base64"] }
43+
serde_path_to_error = "0.1.16"

auction-server/src/api.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@ use {
1515
ServerUpdateResponse,
1616
},
1717
},
18-
auction::Bid,
18+
auction::{
19+
Bid,
20+
BidEvm,
21+
BidSvm,
22+
},
1923
config::{
2024
ChainId,
2125
RunOptions,
@@ -130,6 +134,8 @@ pub enum RestError {
130134
TemporarilyUnavailable,
131135
/// Invalid auth token
132136
InvalidToken,
137+
/// Not implemented
138+
NotImplemented,
133139
}
134140

135141
impl RestError {
@@ -166,6 +172,10 @@ impl RestError {
166172
StatusCode::UNAUTHORIZED,
167173
"Invalid authorization token".to_string(),
168174
),
175+
RestError::NotImplemented => (
176+
StatusCode::NOT_IMPLEMENTED,
177+
"This feature is not implemented".to_string(),
178+
),
169179
}
170180
}
171181
}
@@ -312,6 +322,8 @@ pub async fn start_api(run_options: RunOptions, store: Arc<Store>) -> Result<()>
312322
schemas(
313323
APIResponse,
314324
Bid,
325+
BidSvm,
326+
BidEvm,
315327
BidStatus,
316328
BidStatusWithId,
317329
BidResult,

auction-server/src/api/bid.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use {
77
},
88
auction::{
99
handle_bid,
10+
svm_handle_bid,
1011
Bid,
1112
},
1213
state::{
@@ -47,8 +48,8 @@ pub struct BidResult {
4748

4849
/// Bid on a specific permission key for a specific chain.
4950
///
50-
/// Your bid will be simulated and verified by the server. Depending on the outcome of the auction, a transaction
51-
/// containing the contract call will be sent to the blockchain expecting the bid amount to be paid after the call.
51+
/// Your bid will be verified by the server. Depending on the outcome of the auction, a transaction
52+
/// containing your bid will be sent to the blockchain expecting the bid amount to be paid in the transaction.
5253
#[utoipa::path(post, path = "/v1/bids", request_body = Bid, responses(
5354
(status = 200, description = "Bid was placed successfully", body = BidResult,
5455
example = json!({"status": "OK", "id": "beedbeed-b346-4fa1-8fab-2541a9e1872d"})),
@@ -68,7 +69,11 @@ pub async fn process_bid(
6869
bid: Bid,
6970
auth: Auth,
7071
) -> Result<Json<BidResult>, RestError> {
71-
match handle_bid(store, bid, OffsetDateTime::now_utc(), auth).await {
72+
let result = match bid {
73+
Bid::Evm(evm_bid) => handle_bid(store, evm_bid, OffsetDateTime::now_utc(), auth).await,
74+
Bid::Svm(svm_bid) => svm_handle_bid(store, svm_bid, OffsetDateTime::now_utc(), auth).await,
75+
};
76+
match result {
7277
Ok(id) => Ok(BidResult {
7378
status: "OK".to_string(),
7479
id,

auction-server/src/auction.rs

Lines changed: 76 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,13 @@ use {
7676
gas_oracle::EthProviderOracle,
7777
serde::{
7878
Deserialize,
79+
Deserializer,
7980
Serialize,
8081
},
82+
serde_with::{
83+
base64::Base64,
84+
serde_as,
85+
},
8186
sqlx::types::time::OffsetDateTime,
8287
std::{
8388
result,
@@ -606,7 +611,7 @@ pub async fn run_submission_loop(store: Arc<Store>, chain_id: String) -> Result<
606611
}
607612

608613
#[derive(Serialize, Deserialize, ToSchema, Clone, Debug)]
609-
pub struct Bid {
614+
pub struct BidEvm {
610615
/// The permission key to bid on.
611616
#[schema(example = "0xdeadbeef", value_type = String)]
612617
pub permission_key: Bytes,
@@ -625,6 +630,60 @@ pub struct Bid {
625630
pub amount: BidAmount,
626631
}
627632

633+
#[serde_as]
634+
#[derive(Serialize, Deserialize, ToSchema, Clone, Debug)]
635+
pub struct BidSvm {
636+
/// The permission key to bid on.
637+
#[schema(example = "SGVsbG8sIFdvcmxkIQ==", value_type = String)]
638+
#[serde_as(as = "Base64")]
639+
pub permission_key: Bytes,
640+
/// The chain id to bid on.
641+
#[schema(example = "solana", value_type = String)]
642+
pub chain_id: ChainId,
643+
/// Bid amount in lamports.
644+
#[schema(example = 10, value_type = u64)]
645+
pub amount: u64,
646+
/// The transaction for bid.
647+
#[schema(example = "SGVsbG8sIFdvcmxkIQ==", value_type = String)]
648+
#[serde_as(as = "Base64")]
649+
pub transaction: Vec<u8>,
650+
}
651+
652+
#[derive(Serialize, ToSchema, Debug, Clone)]
653+
#[serde(untagged)] // Remove tags to avoid key-value wrapping
654+
pub enum Bid {
655+
Evm(BidEvm),
656+
Svm(BidSvm),
657+
}
658+
659+
impl<'de> Deserialize<'de> for Bid {
660+
fn deserialize<D>(d: D) -> Result<Self, D::Error>
661+
where
662+
D: Deserializer<'de>,
663+
{
664+
#[derive(Deserialize)]
665+
struct BidChainId {
666+
chain_id: ChainId,
667+
}
668+
669+
let value: serde_json::Value = Deserialize::deserialize(d)?;
670+
let bid_id: BidChainId =
671+
serde_path_to_error::deserialize(&value).map_err(serde::de::Error::custom)?;
672+
match bid_id.chain_id.as_str() {
673+
"solana" => {
674+
let svm_bid: BidSvm =
675+
serde_path_to_error::deserialize(&value).map_err(serde::de::Error::custom)?;
676+
Ok(Bid::Svm(svm_bid))
677+
}
678+
_ => {
679+
let evm_bid: BidEvm =
680+
serde_path_to_error::deserialize(&value).map_err(serde::de::Error::custom)?;
681+
Ok(Bid::Evm(evm_bid))
682+
}
683+
}
684+
}
685+
}
686+
628687
// For now, we are only supporting the EIP1559 enabled networks
629688
async fn verify_bid_exceeds_gas_cost<G>(
630689
estimated_gas: U256,
@@ -690,7 +749,7 @@ async fn verify_bid_under_gas_limit(
690749
#[tracing::instrument(skip_all)]
691750
pub async fn handle_bid(
692751
store: Arc<Store>,
693-
bid: Bid,
752+
bid: BidEvm,
694753
initiation_time: OffsetDateTime,
695754
auth: Auth,
696755
) -> result::Result<Uuid, RestError> {
@@ -831,3 +890,18 @@ pub async fn run_tracker_loop(store: Arc<Store>, chain_id: String) -> Result<()>
831890
tracing::info!("Shutting down tracker...");
832891
Ok(())
833892
}
893+
894+
#[tracing::instrument(skip_all)]
895+
pub async fn svm_handle_bid(
896+
_store: Arc<Store>,
897+
bid: BidSvm,
898+
_initiation_time: OffsetDateTime,
899+
_auth: Auth,
900+
) -> result::Result<Uuid, RestError> {
901+
if bid.chain_id != "solana" {
902+
return Err(RestError::InvalidChainId);
903+
}
904+
905+
// TODO implement this
906+
Err(RestError::NotImplemented)
907+
}

0 commit comments

Comments
 (0)