Skip to content
Open
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
11 changes: 8 additions & 3 deletions pkg/bungee-interface/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ the Bungee integration:
public request / response types, and the wire-stable client error enum used by
Guild and wallet clients.
- `bungee_interface::api` contains the upstream REST API calque, including the
`BungeeApi` trait, transport error surface, response wrapper, and per-endpoint
DTOs.
`BungeeV1Api` and `SocketSwapV3Api` traits, transport error surface, response
wrapper, and per-endpoint DTOs.

## Stack Layout

Expand All @@ -21,7 +21,8 @@ The shipped Bungee integration is split across three crates:
- `bungee-interface` is the leaf crate that owns the shared domain contract and
upstream API calque.
- `bungee-client-http` depends only on `bungee-interface` and implements
`bungee_interface::api::BungeeApi` with reqwest transport.
`bungee_interface::api::BungeeV1Api` and
`bungee_interface::api::SocketSwapV3Api` with reqwest transport.
- `bungee` depends only on `bungee-interface` and implements
`bungee_interface::client::BungeeClient` with quote-selection and response
normalization logic.
Expand All @@ -39,6 +40,10 @@ tests in this crate cover request / response encoding and the public error
payloads so schema drift is caught before it reaches downstream clients that
roll out independently.

The only additive quote-output field introduced for Socket Swap v3 is optional
`min_output_amount`. It defaults to `None` when old persisted rows or old Guild
responses omit it.

## Testing

The crate keeps wire-compat snapshot coverage for the public domain types and
Expand Down
6 changes: 6 additions & 0 deletions pkg/bungee-interface/src/api/endpoints/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
pub mod build_tx;
/// Quote endpoint types.
pub mod quote;
/// Socket Swap v3 quote endpoint types.
pub mod socket_swap_quote;
/// Socket Swap v3 status endpoint types.
pub mod socket_swap_status;
/// Socket Swap v3 token-list endpoint types.
pub mod socket_swap_tokens_list;
/// Status endpoint types.
pub mod status;
/// Token-list endpoint types.
Expand Down
194 changes: 194 additions & 0 deletions pkg/bungee-interface/src/api/endpoints/socket_swap_quote.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
// lint-long-file-override allow-max-lines=300
use bytes::Bytes;
use serde::{Deserialize, Serialize};

/// Request headers for `GET /v3/swap/quote`.
#[derive(Debug, Clone, Default, Serialize)]
pub struct Headers {}

/// Query parameters for `GET /v3/swap/quote`.
#[derive(Debug, Clone, Serialize)]
pub struct Query {
/// `userOps`
#[serde(rename = "userOps")]
pub user_ops: String,
/// `originChainId`
#[serde(rename = "originChainId")]
pub origin_chain_id: String,
/// `destinationChainId`
#[serde(rename = "destinationChainId")]
pub destination_chain_id: String,
/// `inputToken`
#[serde(rename = "inputToken")]
pub input_token: String,
/// `outputToken`
#[serde(rename = "outputToken")]
pub output_token: String,
/// `inputAmount`
#[serde(rename = "inputAmount")]
pub input_amount: String,
/// `receiverAddress`
#[serde(rename = "receiverAddress")]
pub receiver_address: String,
/// `userAddress`
#[serde(rename = "userAddress")]
pub user_address: String,
/// `slippage`
pub slippage: String,
}

/// Response body variants for `GET /v3/swap/quote`.
#[allow(clippy::large_enum_variant)]
#[derive(Debug, Clone)]
pub enum ResponseEnum {
/// Successful 200 response.
Ok200(QuoteResponse),
/// Any non-200 response with raw body bytes.
Unknown(u16, Bytes),
}

/// Wrapped Socket Swap v3 quote response.
#[derive(Debug, Clone, Deserialize)]
pub struct QuoteResponse {
/// Success flag returned by the API.
pub success: bool,
/// HTTP-style status code reported by Socket.
#[serde(rename = "statusCode")]
pub status_code: u64,
/// Wrapped quote payload.
pub result: QuoteResult,
/// Optional upstream message.
pub message: Option<String>,
}

/// Quote result payload.
#[derive(Debug, Clone, Deserialize)]
pub struct QuoteResult {
/// Origin chain id.
#[serde(rename = "originChainId")]
pub origin_chain_id: u128,
/// Destination chain id.
#[serde(rename = "destinationChainId")]
pub destination_chain_id: u128,
/// User wallet address on the source chain.
#[serde(rename = "userAddress")]
pub user_address: String,
/// Receiver wallet address on the destination chain.
#[serde(rename = "receiverAddress")]
pub receiver_address: String,
/// Input amount and token details echoed by Socket.
pub input: Input,
/// Candidate routes.
#[serde(default)]
pub routes: Vec<Route>,
}

/// Input amount and token details echoed by Socket.
#[derive(Debug, Clone, Deserialize)]
pub struct Input {
/// Input token details.
pub token: Token,
/// Input token amount.
pub amount: String,
/// USD value of the input amount.
#[serde(rename = "valueInUsd")]
pub value_in_usd: Option<f64>,
/// Price per unit in USD.
#[serde(rename = "priceInUsd")]
pub price_in_usd: Option<f64>,
}

/// Token chain and address details.
#[derive(Debug, Clone, Deserialize)]
pub struct Token {
/// Token chain id.
#[serde(rename = "chainId")]
pub chain_id: u128,
/// Token contract address.
pub address: String,
}

/// Socket Swap v3 route candidate.
#[derive(Debug, Clone, Deserialize)]
pub struct Route {
/// Route user operation type.
#[serde(rename = "userOp")]
pub user_op: String,
/// Socket quote id.
#[serde(rename = "quoteId")]
pub quote_id: String,
/// Unix timestamp after which the route should not be submitted.
#[serde(rename = "expiresAt")]
pub expires_at: Option<u64>,
/// Output amount information.
pub output: Output,
/// Estimated time to complete, in seconds. Socket returns this as a JSON
/// number that may be fractional (e.g. `9.5`), so it must be `f64`.
#[serde(rename = "estimatedTime")]
pub estimated_time: Option<f64>,
/// Route tags used for tie-break ranking.
#[serde(rename = "routeTags", default)]
pub route_tags: Vec<String>,
/// Optional approval details required before submitting txData.
pub approval: Option<Approval>,
/// Transaction data for the Socket route.
#[serde(rename = "txData")]
pub tx_data: TxData,
}

/// Output amount wrapper.
#[derive(Debug, Clone, Deserialize)]
pub struct Output {
/// Output token details.
pub token: Token,
/// Expected output amount.
pub amount: String,
/// Guaranteed minimum output amount.
#[serde(rename = "minAmountOut")]
pub min_amount_out: String,
/// Price per unit in USD.
#[serde(rename = "priceInUsd")]
pub price_in_usd: Option<f64>,
/// USD value of the output amount.
#[serde(rename = "valueInUsd")]
pub value_in_usd: Option<f64>,
}

/// ERC-20 approval details.
#[derive(Debug, Clone, Deserialize)]
pub struct Approval {
/// Spender address to approve.
#[serde(rename = "spenderAddress")]
pub spender_address: String,
/// Allowance amount.
pub amount: String,
/// Approved token address.
#[serde(rename = "tokenAddress")]
pub token_address: String,
/// User wallet address.
#[serde(rename = "userAddress")]
pub user_address: String,
}

/// Socket route transaction data container.
#[derive(Debug, Clone, Deserialize)]
pub struct TxData {
/// Transaction data kind.
pub kind: String,
/// EVM transaction object.
pub object: TxObject,
}

/// EVM transaction object returned under `txData.object`.
#[derive(Debug, Clone, Deserialize)]
pub struct TxObject {
/// Source chain id.
#[serde(rename = "chainId")]
pub chain_id: u128,
/// Transaction target.
pub to: String,
/// Calldata.
pub data: String,
/// Native value.
pub value: String,
}
66 changes: 66 additions & 0 deletions pkg/bungee-interface/src/api/endpoints/socket_swap_status.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
use bytes::Bytes;
use serde::{Deserialize, Serialize};

/// Request headers for `GET /v3/swap/status`.
#[derive(Debug, Clone, Default, Serialize)]
pub struct Headers {}

/// Query parameters for `GET /v3/swap/status`.
#[derive(Debug, Clone, Serialize)]
pub struct Query {
/// `quoteId`
#[serde(rename = "quoteId", skip_serializing_if = "Option::is_none")]
pub quote_id: Option<String>,
/// `srcTxHash`
#[serde(rename = "srcTxHash", skip_serializing_if = "Option::is_none")]
pub src_tx_hash: Option<String>,
}

/// Response body variants for `GET /v3/swap/status`.
#[derive(Debug, Clone)]
pub enum ResponseEnum {
/// Successful 200 response.
Ok200(StatusResponse),
/// Any non-200 response with raw body bytes.
Unknown(u16, Bytes),
}

/// Wrapped Socket Swap v3 status response.
#[derive(Debug, Clone, Deserialize)]
pub struct StatusResponse {
/// Success flag returned by the API.
pub success: bool,
/// HTTP-style status code reported by Socket.
#[serde(rename = "statusCode")]
pub status_code: u64,
/// Wrapped status payload.
pub result: StatusResult,
/// Optional upstream message.
pub message: Option<String>,
}

/// Socket status result payload.
#[derive(Debug, Clone, Deserialize)]
pub struct StatusResult {
/// Socket quote id.
#[serde(rename = "quoteId")]
pub quote_id: String,
/// Route user operation type.
#[serde(rename = "userOp")]
pub user_op: String,
/// Coarse status.
pub status: String,
/// Granular status code.
#[serde(rename = "statusCode")]
pub status_code: String,
/// Destination leg data.
pub destination: Option<StatusDestination>,
}

/// Destination leg status data.
#[derive(Debug, Clone, Deserialize)]
pub struct StatusDestination {
/// Destination transaction hash, if broadcast.
#[serde(rename = "txHash")]
pub tx_hash: Option<String>,
}
Loading
Loading