-
Notifications
You must be signed in to change notification settings - Fork 62
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add Validator/
NodeClient
MegaVault methods (#300)
Adds gRPC-based MegaVault methods. Tests and examples included. Also extends a bit the `BigIntExt` trait to convert `BigInt` into our serialized integer arrays. Closes #297.
- Loading branch information
Showing
6 changed files
with
371 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
mod support; | ||
use anyhow::{Error, Result}; | ||
use bigdecimal::num_bigint::BigInt; | ||
use dydx::config::ClientConfig; | ||
use dydx::node::{BigIntExt, NodeClient, Wallet}; | ||
use support::constants::TEST_MNEMONIC; | ||
use tokio::time::{sleep, Duration}; | ||
|
||
pub struct MegaVaulter { | ||
client: NodeClient, | ||
wallet: Wallet, | ||
} | ||
|
||
impl MegaVaulter { | ||
pub async fn connect() -> Result<Self> { | ||
let config = ClientConfig::from_file("client/tests/testnet.toml").await?; | ||
let client = NodeClient::connect(config.node).await?; | ||
let wallet = Wallet::from_mnemonic(TEST_MNEMONIC)?; | ||
Ok(Self { client, wallet }) | ||
} | ||
} | ||
|
||
#[tokio::main] | ||
async fn main() -> Result<()> { | ||
tracing_subscriber::fmt().try_init().map_err(Error::msg)?; | ||
#[cfg(feature = "telemetry")] | ||
support::telemetry::metrics_dashboard().await?; | ||
|
||
let mut vaulter = MegaVaulter::connect().await?; | ||
let mut account = vaulter.wallet.account(0, &mut vaulter.client).await?; | ||
let address = account.address().clone(); | ||
let subaccount = account.subaccount(0)?; | ||
|
||
// Deposit 1 USDC into the MegaVault | ||
let tx_hash = vaulter | ||
.client | ||
.megavault() | ||
.deposit(&mut account, subaccount.clone(), 1) | ||
.await?; | ||
tracing::info!("Deposit transaction hash: {:?}", tx_hash); | ||
|
||
sleep(Duration::from_secs(2)).await; | ||
|
||
// Withdraw 1 share from the MegaVault | ||
let number_of_shares: BigInt = 1.into(); | ||
let tx_hash = vaulter | ||
.client | ||
.megavault() | ||
.withdraw(&mut account, subaccount, 0, Some(&number_of_shares)) | ||
.await?; | ||
tracing::info!("Withdraw transaction hash: {:?}", tx_hash); | ||
|
||
// Query methods | ||
|
||
let owner_shares = vaulter | ||
.client | ||
.megavault() | ||
.get_owner_shares(&address) | ||
.await?; | ||
tracing::info!("Get owner shares: {owner_shares:?}"); | ||
|
||
// Convert serialized integer into an integer (`BigIntExt` trait) | ||
if let Some(shares) = owner_shares.shares { | ||
let nshares = BigInt::from_serializable_int(&shares.num_shares)?; | ||
tracing::info!("Number of owned shares: {}", nshares); | ||
} | ||
|
||
let withdrawal_info = vaulter | ||
.client | ||
.megavault() | ||
.get_withdrawal_info(&number_of_shares) | ||
.await?; | ||
tracing::info!("Get withdrawal info: {withdrawal_info:?}"); | ||
|
||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
use super::*; | ||
use crate::node::utils::BigIntExt; | ||
|
||
use anyhow::{anyhow as err, Error}; | ||
use dydx_proto::dydxprotocol::{ | ||
subaccounts::SubaccountId, | ||
vault::{ | ||
MsgDepositToMegavault, MsgWithdrawFromMegavault, NumShares, | ||
QueryMegavaultOwnerSharesRequest, QueryMegavaultOwnerSharesResponse, | ||
QueryMegavaultWithdrawalInfoRequest, QueryMegavaultWithdrawalInfoResponse, | ||
}, | ||
}; | ||
|
||
use bigdecimal::num_bigint::ToBigInt; | ||
|
||
/// [`NodeClient`] MegaVault requests dispatcher | ||
pub struct MegaVault<'a> { | ||
client: &'a mut NodeClient, | ||
} | ||
|
||
impl<'a> MegaVault<'a> { | ||
/// Create a new MegaVault requests dispatcher | ||
pub(crate) fn new(client: &'a mut NodeClient) -> Self { | ||
Self { client } | ||
} | ||
|
||
/// Deposit USDC into the MegaVault. | ||
/// | ||
/// Check [the example](https://github.com/dydxprotocol/v4-clients/blob/main/v4-client-rs/client/examples/validator_megavault.rs). | ||
pub async fn deposit( | ||
&mut self, | ||
account: &mut Account, | ||
subaccount: Subaccount, | ||
amount: impl Into<Usdc>, | ||
) -> Result<TxHash, NodeError> { | ||
let client = &mut self.client; | ||
|
||
let subaccount_id = SubaccountId { | ||
owner: subaccount.address.to_string(), | ||
number: subaccount.number.0, | ||
}; | ||
let quantums = amount | ||
.into() | ||
.quantize() | ||
.to_bigint() | ||
.ok_or_else(|| err!("Failed converting USDC quantums to BigInt"))? | ||
.to_serializable_vec()?; | ||
|
||
let msg = MsgDepositToMegavault { | ||
subaccount_id: Some(subaccount_id), | ||
quote_quantums: quantums, | ||
}; | ||
|
||
let tx_raw = client.create_transaction(account, msg).await?; | ||
|
||
client.broadcast_transaction(tx_raw).await | ||
} | ||
|
||
/// Withdraw shares from the MegaVault. | ||
/// The number of shares must be equal or greater to some specified minimum amount (in | ||
/// USDC-equivalent value). | ||
/// | ||
/// Check [the example](https://github.com/dydxprotocol/v4-clients/blob/main/v4-client-rs/client/examples/validator_megavault.rs). | ||
pub async fn withdraw( | ||
&mut self, | ||
account: &mut Account, | ||
subaccount: Subaccount, | ||
min_amount: impl Into<Usdc>, | ||
shares: Option<&BigInt>, | ||
) -> Result<TxHash, NodeError> { | ||
let client = &mut self.client; | ||
|
||
let subaccount_id = SubaccountId { | ||
owner: subaccount.address.to_string(), | ||
number: subaccount.number.0, | ||
}; | ||
let quantums = min_amount | ||
.into() | ||
.quantize() | ||
.to_bigint() | ||
.ok_or_else(|| err!("Failed converting USDC quantums to BigInt"))? | ||
.to_serializable_vec()?; | ||
let num_shares = shares | ||
.map(|x| x.to_serializable_vec()) | ||
.transpose()? | ||
.map(|vec| NumShares { num_shares: vec }); | ||
|
||
let msg = MsgWithdrawFromMegavault { | ||
subaccount_id: Some(subaccount_id), | ||
min_quote_quantums: quantums, | ||
shares: num_shares, | ||
}; | ||
|
||
let tx_raw = client.create_transaction(account, msg).await?; | ||
|
||
client.broadcast_transaction(tx_raw).await | ||
} | ||
|
||
/// Query the shares associated with an [`Address`]. | ||
/// | ||
/// Check [the example](https://github.com/dydxprotocol/v4-clients/blob/main/v4-client-rs/client/examples/validator_megavault.rs). | ||
pub async fn get_owner_shares( | ||
&mut self, | ||
address: &Address, | ||
) -> Result<QueryMegavaultOwnerSharesResponse, Error> { | ||
let client = &mut self.client; | ||
let req = QueryMegavaultOwnerSharesRequest { | ||
address: address.to_string(), | ||
}; | ||
|
||
let response = client.vault.megavault_owner_shares(req).await?.into_inner(); | ||
|
||
Ok(response) | ||
} | ||
|
||
/// Query the withdrawal information for a specified number of shares. | ||
/// | ||
/// Check [the example](https://github.com/dydxprotocol/v4-clients/blob/main/v4-client-rs/client/examples/validator_megavault.rs). | ||
pub async fn get_withdrawal_info( | ||
&mut self, | ||
shares: &BigInt, | ||
) -> Result<QueryMegavaultWithdrawalInfoResponse, Error> { | ||
let client = &mut self.client; | ||
let num_shares = NumShares { | ||
num_shares: shares.to_serializable_vec()?, | ||
}; | ||
let req = QueryMegavaultWithdrawalInfoRequest { | ||
shares_to_withdraw: Some(num_shares), | ||
}; | ||
|
||
let response = client | ||
.vault | ||
.megavault_withdrawal_info(req) | ||
.await? | ||
.into_inner(); | ||
|
||
Ok(response) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.