Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

funds-manager: fee-indexer: Add endpoint to view wallet fee balances #15

Merged
merged 2 commits into from
Jul 26, 2024
Merged
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
1 change: 1 addition & 0 deletions funds-manager/funds-manager-api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ edition = "2021"

[dependencies]

renegade-api = { package = "external-api", workspace = true }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.117"
11 changes: 11 additions & 0 deletions funds-manager/funds-manager-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#![deny(missing_docs)]
#![deny(clippy::missing_docs_in_private_items)]

use renegade_api::types::ApiWallet;
use serde::{Deserialize, Serialize};

// --------------
Expand All @@ -23,6 +24,9 @@ pub const WITHDRAW_CUSTODY_ROUTE: &str = "withdraw";
/// The route to withdraw gas from custody
pub const WITHDRAW_GAS_ROUTE: &str = "withdraw-gas";

/// The route to get fee wallets
pub const GET_FEE_WALLETS_ROUTE: &str = "get-fee-wallets";

// -------------
// | Api Types |
// -------------
Expand Down Expand Up @@ -54,3 +58,10 @@ pub struct WithdrawGasRequest {
/// The address to withdraw to
pub destination_address: String,
}

/// The response containing fee wallets
#[derive(Debug, Serialize, Deserialize)]
pub struct FeeWalletsResponse {
/// The wallets managed by the funds manager
pub wallets: Vec<ApiWallet>,
}
45 changes: 45 additions & 0 deletions funds-manager/funds-manager-server/src/fee_indexer/fee_balances.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//! Fetch the balances of redeemed fees

use crate::db::models::WalletMetadata;
use crate::error::FundsManagerError;
use renegade_api::types::ApiWallet;
use renegade_common::types::wallet::derivation::derive_wallet_keychain;

use super::Indexer;

impl Indexer {
/// Fetch fee balances for wallets managed by the funds manager
pub async fn fetch_fee_wallets(&mut self) -> Result<Vec<ApiWallet>, FundsManagerError> {
// Query the wallets and fetch from the relayer
let wallet_metadata = self.get_all_wallets().await?;
let mut wallets = Vec::with_capacity(wallet_metadata.len());
for meta in wallet_metadata.into_iter() {
let wallet = self.fetch_wallet(meta).await?;
wallets.push(wallet);
}

Ok(wallets)
}

/// Fetch a wallet given its metadata
///
/// This is done by:
/// 1. Fetch the wallet's key from secrets manager
/// 2. Use the key to fetch the wallet from the relayer
async fn fetch_wallet(
&mut self,
wallet_metadata: WalletMetadata,
) -> Result<ApiWallet, FundsManagerError> {
// Get the wallet's private key from secrets manager
let eth_key = self.get_wallet_private_key(&wallet_metadata).await?;

// Derive the wallet keychain
let wallet_keychain =
derive_wallet_keychain(&eth_key, self.chain_id).map_err(FundsManagerError::custom)?;
let root_key = wallet_keychain.secret_keys.sk_root.clone().expect("root key not present");

// Fetch the wallet from the relayer
let wallet = self.relayer_client.get_wallet(wallet_metadata.id, &root_key).await?;
Ok(wallet.wallet)
}
}
1 change: 1 addition & 0 deletions funds-manager/funds-manager-server/src/fee_indexer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use renegade_util::hex::jubjub_from_hex_string;

use crate::relayer_client::RelayerClient;

pub mod fee_balances;
pub mod index_fees;
pub mod queries;
pub mod redeem_fees;
Expand Down
11 changes: 11 additions & 0 deletions funds-manager/funds-manager-server/src/fee_indexer/queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,17 @@ impl Indexer {
// | Wallets Table |
// -----------------

/// Get all wallets in the table
pub(crate) async fn get_all_wallets(
&mut self,
) -> Result<Vec<WalletMetadata>, FundsManagerError> {
let wallets = wallet_table
.load::<WalletMetadata>(&mut self.db_conn)
.await
.map_err(|e| FundsManagerError::db(format!("failed to load wallets: {}", e)))?;
Ok(wallets)
}

/// Get the wallet managing an mint, if it exists
///
/// Returns the id and secret id of the wallet
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ impl Indexer {
}

/// Get the private key for a wallet specified by its metadata
async fn get_wallet_private_key(
pub(crate) async fn get_wallet_private_key(
&mut self,
metadata: &WalletMetadata,
) -> Result<LocalWallet, FundsManagerError> {
Expand Down
15 changes: 14 additions & 1 deletion funds-manager/funds-manager-server/src/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
use crate::custody_client::DepositWithdrawSource;
use crate::error::ApiError;
use crate::Server;
use funds_manager_api::{DepositAddressResponse, WithdrawFundsRequest, WithdrawGasRequest};
use bytes::Bytes;
use funds_manager_api::{
DepositAddressResponse, FeeWalletsResponse, WithdrawFundsRequest, WithdrawGasRequest,
};
use std::collections::HashMap;
use std::sync::Arc;
use warp::reply::Json;
Expand Down Expand Up @@ -103,3 +106,13 @@ pub(crate) async fn withdraw_gas_handler(

Ok(warp::reply::json(&format!("Gas withdrawal of {} ETH complete", withdraw_request.amount)))
}

/// Handler for getting fee wallets
pub(crate) async fn get_fee_wallets_handler(
_body: Bytes, // no body
server: Arc<Server>,
) -> Result<Json, warp::Rejection> {
let mut indexer = server.build_indexer().await?;
let wallets = indexer.fetch_fee_wallets().await?;
Ok(warp::reply::json(&FeeWalletsResponse { wallets }))
}
16 changes: 12 additions & 4 deletions funds-manager/funds-manager-server/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ use error::FundsManagerError;
use ethers::signers::LocalWallet;
use fee_indexer::Indexer;
use funds_manager_api::{
WithdrawGasRequest, GET_DEPOSIT_ADDRESS_ROUTE, INDEX_FEES_ROUTE, PING_ROUTE, REDEEM_FEES_ROUTE,
WITHDRAW_CUSTODY_ROUTE, WITHDRAW_GAS_ROUTE,
WithdrawGasRequest, GET_DEPOSIT_ADDRESS_ROUTE, GET_FEE_WALLETS_ROUTE, INDEX_FEES_ROUTE,
PING_ROUTE, REDEEM_FEES_ROUTE, WITHDRAW_CUSTODY_ROUTE, WITHDRAW_GAS_ROUTE,
};
use handlers::{
get_deposit_address_handler, index_fees_handler, quoter_withdraw_handler, redeem_fees_handler,
withdraw_gas_handler,
get_deposit_address_handler, get_fee_wallets_handler, index_fees_handler,
quoter_withdraw_handler, redeem_fees_handler, withdraw_gas_handler,
};
use middleware::{identity, with_hmac_auth, with_json_body};
use relayer_client::RelayerClient;
Expand Down Expand Up @@ -299,12 +299,20 @@ async fn main() -> Result<(), Box<dyn Error>> {
.and(with_server(server.clone()))
.and_then(withdraw_gas_handler);

let get_balances = warp::get()
.and(warp::path("fees"))
.and(warp::path(GET_FEE_WALLETS_ROUTE))
.and(with_hmac_auth(server.clone()))
.and(with_server(server.clone()))
.and_then(get_fee_wallets_handler);

let routes = ping
.or(index_fees)
.or(redeem_fees)
.or(withdraw_custody)
.or(get_deposit_address)
.or(withdraw_gas)
.or(get_balances)
.recover(handle_rejection);
warp::serve(routes).run(([0, 0, 0, 0], cli.port)).await;

Expand Down
11 changes: 11 additions & 0 deletions funds-manager/funds-manager-server/src/relayer_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,17 @@ impl RelayerClient {
// | Wallet Methods |
// ------------------

/// Get the wallet for a given id
pub async fn get_wallet(
&self,
wallet_id: WalletIdentifier,
root_key: &SecretSigningKey,
) -> Result<GetWalletResponse, FundsManagerError> {
let mut path = GET_WALLET_ROUTE.to_string();
path = path.replace(":wallet_id", &wallet_id.to_string());
self.get_relayer_with_auth::<GetWalletResponse>(&path, root_key).await
}

/// Check that the relayer has a given wallet, lookup the wallet if not
pub async fn check_wallet_indexed(
&self,
Expand Down
Loading