nautilus_dydx/grpc/
mod.rs

1// -------------------------------------------------------------------------------------------------
2//  Copyright (C) 2015-2025 Nautech Systems Pty Ltd. All rights reserved.
3//  https://nautechsystems.io
4//
5//  Licensed under the GNU Lesser General Public License Version 3.0 (the "License");
6//  You may not use this file except in compliance with the License.
7//  You may obtain a copy of the License at https://www.gnu.org/licenses/lgpl-3.0.en.html
8//
9//  Unless required by applicable law or agreed to in writing, software
10//  distributed under the License is distributed on an "AS IS" BASIS,
11//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//  See the License for the specific language governing permissions and
13//  limitations under the License.
14// -------------------------------------------------------------------------------------------------
15
16//! gRPC client implementation for the dYdX v4 protocol.
17//!
18//! This module provides gRPC client functionality for interacting with the dYdX v4 protocol
19//! via the Cosmos SDK. It handles:
20//!
21//! - Transaction signing and broadcasting using `cosmrs`.
22//! - gRPC communication with validator nodes.
23//! - Protocol Buffer message encoding/decoding.
24//! - Cosmos SDK account management.
25//!
26//! The client supports dYdX trading operations including:
27//!
28//! - Order placement, modification, and cancellation.
29//! - Transfer operations between subaccounts.
30//! - Subaccount management.
31//! - Transaction signing with secp256k1 keys.
32//!
33//! # Architecture
34//!
35//! dYdX v4 is built on the Cosmos SDK and uses gRPC for all state-changing operations
36//! (placing orders, transfers, etc.). The HTTP/REST API (Indexer) is read-only and used
37//! for querying market data and historical information.
38
39// TODO: Enable when proto is generated
40// pub mod builder;
41// pub mod client;
42// pub mod order;
43pub mod types;
44pub mod wallet;
45
46// Re-exports
47// TODO: Enable when proto is generated
48// pub use builder::TxBuilder;
49// pub use client::{DydxGrpcClient, Height, TxHash};
50// pub use order::{
51//     DEFAULT_RUST_CLIENT_METADATA, OrderBuilder, OrderFlags, OrderGoodUntil, OrderMarketParams,
52//     SHORT_TERM_ORDER_MAXIMUM_LIFETIME,
53// };
54pub use types::ChainId;
55pub use wallet::{Account, Subaccount, Wallet};
56
57// Temporary stubs until proto is generated
58#[derive(Debug, Clone)]
59pub struct DydxGrpcClient;
60
61impl DydxGrpcClient {
62    /// Creates a new dYdX gRPC client.
63    ///
64    /// # Errors
65    ///
66    /// This is a stub that currently never fails. Will return connection errors when implemented.
67    pub async fn new(endpoint: String) -> anyhow::Result<Self> {
68        tracing::info!("Initialized stub dYdX gRPC client for endpoint: {endpoint}");
69        Ok(Self)
70    }
71
72    /// Creates a new dYdX gRPC client with fallback endpoints.
73    ///
74    /// # Errors
75    ///
76    /// This is a stub that currently never fails. Will return connection errors when implemented.
77    pub async fn new_with_fallback(endpoints: &[String]) -> anyhow::Result<Self> {
78        if endpoints.is_empty() {
79            anyhow::bail!("No dYdX gRPC endpoints provided");
80        }
81
82        // In stub mode we don't perform real network connections, but we still
83        // honour the fallback configuration and log which node would be used.
84        for (idx, url) in endpoints.iter().enumerate() {
85            tracing::info!(
86                "Attempting to initialize dYdX gRPC client (attempt {}/{}) with endpoint: {url}",
87                idx + 1,
88                endpoints.len()
89            );
90
91            // Treat the first endpoint as successful to mirror the real client's
92            // behaviour where the first reachable node is selected.
93            if idx == 0 {
94                tracing::info!("Selected dYdX gRPC endpoint: {url}");
95                return Self::new(url.clone()).await;
96            }
97        }
98
99        // Fallback (should not be reached with non-empty endpoints).
100        Self::new(endpoints[0].clone()).await
101    }
102}
103
104#[derive(Debug, Clone, Copy)]
105pub struct Height(pub u32);
106
107pub type TxHash = String;
108
109#[derive(Debug, Clone)]
110pub struct OrderBuilder;
111
112#[derive(Debug, Clone)]
113pub struct OrderFlags;
114
115#[derive(Debug, Clone)]
116pub enum OrderGoodUntil {
117    Block(u32),
118    Time(chrono::DateTime<chrono::Utc>),
119}
120
121#[derive(Debug, Clone)]
122pub struct OrderMarketParams {
123    pub atomic_resolution: i32,
124    pub clob_pair_id: u32,
125    pub oracle_price: Option<u64>,
126    pub quantum_conversion_exponent: i32,
127    pub step_base_quantums: u64,
128    pub subticks_per_tick: u32,
129}
130
131pub const SHORT_TERM_ORDER_MAXIMUM_LIFETIME: u32 = 20;
132pub const DEFAULT_RUST_CLIENT_METADATA: u32 = 4;