use df_hyperliquid_core::client::Http;
use df_hyperliquid_core::utils::Address;
use crate::account::store::{Slot, Store};
use crate::account::wallet::{Purpose, SignRequest, Wallet};
use crate::client::{Accepted, Client, Error};
use crate::trade::{Intent, Signed};
use crate::utils::{Lane, nonce};
impl<H: Http + Clone> Client<H> {
pub async fn take_nonce(&self, store: &impl Store, owner: Address, lane: Lane) -> Result<u128, Error> {
let held = store.get(owner, Slot::Nonce(lane)).await?;
let next = match held.as_deref().and_then(|bytes| <[u8; 16]>::try_from(bytes).ok()) {
Some(bytes) => u128::from_be_bytes(bytes),
None => nonce::first(self.random::<3>()?),
};
store.put(owner, Slot::Nonce(lane), next.saturating_add(1).to_be_bytes().to_vec(), None).await?;
Ok(next)
}
pub(crate) async fn wallet_sign(
&self,
wallet: &impl Wallet,
owner: Address,
intent: Intent,
purpose: Purpose,
) -> Result<Signed, Error> {
if wallet.address() != owner {
return Err(Error::WrongWallet { wallet: wallet.address().to_hex(), owner: owner.to_hex() });
}
if intent.user() != owner {
return Err(Error::WrongWallet { wallet: intent.user().to_hex(), owner: owner.to_hex() });
}
let request = SignRequest { purpose, json: intent.wallet_json(), digest: intent.digest() };
let signature = wallet.sign(&request).await?;
Signed::recover(intent, signature, owner).map_err(|e| Error::Signature(e.to_string()))
}
pub(crate) async fn submit(&self, signed: &Signed) -> Result<Accepted, Error> {
let accepted = self.relayer().submit(signed).await?;
if accepted.kept() { Ok(accepted) } else { Err(Error::NotKept(accepted)) }
}
}
#[cfg(test)]
#[path = "tests/submit.rs"]
mod tests;