From c70d0732a72b7f3fe9553bd84d61d87ffd1dc357 Mon Sep 17 00:00:00 2001 From: Joey Kraut Date: Thu, 25 Jul 2024 18:19:17 -0700 Subject: [PATCH] funds-manager: fee-indexer: Add endpoint to view wallet fee balances --- funds-manager/funds-manager-api/Cargo.toml | 1 + funds-manager/funds-manager-api/src/lib.rs | 11 +++++ .../src/fee_indexer/fee_balances.rs | 45 +++++++++++++++++++ .../src/fee_indexer/mod.rs | 1 + .../src/fee_indexer/queries.rs | 11 +++++ .../src/fee_indexer/redeem_fees.rs | 3 +- .../funds-manager-server/src/handlers.rs | 15 ++++++- .../funds-manager-server/src/main.rs | 16 +++++-- .../src/relayer_client.rs | 11 +++++ 9 files changed, 107 insertions(+), 7 deletions(-) create mode 100644 funds-manager/funds-manager-server/src/fee_indexer/fee_balances.rs diff --git a/funds-manager/funds-manager-api/Cargo.toml b/funds-manager/funds-manager-api/Cargo.toml index 6035ae1..51c15fa 100644 --- a/funds-manager/funds-manager-api/Cargo.toml +++ b/funds-manager/funds-manager-api/Cargo.toml @@ -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" diff --git a/funds-manager/funds-manager-api/src/lib.rs b/funds-manager/funds-manager-api/src/lib.rs index 46e1747..cc3ac6b 100644 --- a/funds-manager/funds-manager-api/src/lib.rs +++ b/funds-manager/funds-manager-api/src/lib.rs @@ -2,6 +2,7 @@ #![deny(missing_docs)] #![deny(clippy::missing_docs_in_private_items)] +use renegade_api::types::ApiWallet; use serde::{Deserialize, Serialize}; // -------------- @@ -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 | // ------------- @@ -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, +} diff --git a/funds-manager/funds-manager-server/src/fee_indexer/fee_balances.rs b/funds-manager/funds-manager-server/src/fee_indexer/fee_balances.rs new file mode 100644 index 0000000..1665619 --- /dev/null +++ b/funds-manager/funds-manager-server/src/fee_indexer/fee_balances.rs @@ -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, 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 { + // 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(ð_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) + } +} diff --git a/funds-manager/funds-manager-server/src/fee_indexer/mod.rs b/funds-manager/funds-manager-server/src/fee_indexer/mod.rs index cd37970..a447709 100644 --- a/funds-manager/funds-manager-server/src/fee_indexer/mod.rs +++ b/funds-manager/funds-manager-server/src/fee_indexer/mod.rs @@ -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; diff --git a/funds-manager/funds-manager-server/src/fee_indexer/queries.rs b/funds-manager/funds-manager-server/src/fee_indexer/queries.rs index 9295bcb..8f0bbf2 100644 --- a/funds-manager/funds-manager-server/src/fee_indexer/queries.rs +++ b/funds-manager/funds-manager-server/src/fee_indexer/queries.rs @@ -208,6 +208,17 @@ impl Indexer { // | Wallets Table | // ----------------- + /// Get all wallets in the table + pub(crate) async fn get_all_wallets( + &mut self, + ) -> Result, FundsManagerError> { + let wallets = wallet_table + .load::(&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 diff --git a/funds-manager/funds-manager-server/src/fee_indexer/redeem_fees.rs b/funds-manager/funds-manager-server/src/fee_indexer/redeem_fees.rs index 4c3862e..fa3ff4e 100644 --- a/funds-manager/funds-manager-server/src/fee_indexer/redeem_fees.rs +++ b/funds-manager/funds-manager-server/src/fee_indexer/redeem_fees.rs @@ -4,7 +4,6 @@ use std::collections::HashMap; use std::str::FromStr; use aws_sdk_secretsmanager::Client as SecretsManagerClient; -use diesel::IntoSql; use ethers::core::rand::thread_rng; use ethers::signers::LocalWallet; use ethers::types::TxHash; @@ -213,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 { diff --git a/funds-manager/funds-manager-server/src/handlers.rs b/funds-manager/funds-manager-server/src/handlers.rs index 9af4764..ab7bda2 100644 --- a/funds-manager/funds-manager-server/src/handlers.rs +++ b/funds-manager/funds-manager-server/src/handlers.rs @@ -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; @@ -96,3 +99,13 @@ pub(crate) async fn withdraw_gas_handler( Ok(warp::reply::json(&"Gas withdrawal complete")) } + +/// Handler for getting fee wallets +pub(crate) async fn get_fee_wallets_handler( + _body: Bytes, // no body + server: Arc, +) -> Result { + let mut indexer = server.build_indexer().await?; + let wallets = indexer.fetch_fee_wallets().await?; + Ok(warp::reply::json(&FeeWalletsResponse { wallets })) +} diff --git a/funds-manager/funds-manager-server/src/main.rs b/funds-manager/funds-manager-server/src/main.rs index 969c4e1..881de64 100644 --- a/funds-manager/funds-manager-server/src/main.rs +++ b/funds-manager/funds-manager-server/src/main.rs @@ -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; @@ -299,12 +299,20 @@ async fn main() -> Result<(), Box> { .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; diff --git a/funds-manager/funds-manager-server/src/relayer_client.rs b/funds-manager/funds-manager-server/src/relayer_client.rs index 9e229fd..586bc49 100644 --- a/funds-manager/funds-manager-server/src/relayer_client.rs +++ b/funds-manager/funds-manager-server/src/relayer_client.rs @@ -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 { + let mut path = GET_WALLET_ROUTE.to_string(); + path = path.replace(":wallet_id", &wallet_id.to_string()); + self.get_relayer_with_auth::(&path, root_key).await + } + /// Check that the relayer has a given wallet, lookup the wallet if not pub async fn check_wallet_indexed( &self,