From 58024ac8facef1f1462908e5de9a88c19a450201 Mon Sep 17 00:00:00 2001 From: Joey Kraut Date: Wed, 31 Jul 2024 19:34:04 -0700 Subject: [PATCH] funds-manager: Add internal wallet id mapping & use internal transaction --- funds-manager/funds-manager-api/src/lib.rs | 2 ++ .../src/custody_client/hot_wallets.rs | 12 ++++++++---- .../src/custody_client/mod.rs | 2 -- .../src/custody_client/queries.rs | 9 ++++++++- .../src/custody_client/withdraw.rs | 17 +++++++++-------- .../funds-manager-server/src/db/models.rs | 10 ++++++++-- .../funds-manager-server/src/db/schema.rs | 1 + .../funds-manager-server/src/handlers.rs | 2 +- .../down.sql | 2 ++ .../up.sql | 11 +++++++++++ 10 files changed, 50 insertions(+), 18 deletions(-) create mode 100644 funds-manager/migrations/2024-08-01-021728_add_internal_wallet_id/down.sql create mode 100644 funds-manager/migrations/2024-08-01-021728_add_internal_wallet_id/up.sql diff --git a/funds-manager/funds-manager-api/src/lib.rs b/funds-manager/funds-manager-api/src/lib.rs index 9e664c9..f901861 100644 --- a/funds-manager/funds-manager-api/src/lib.rs +++ b/funds-manager/funds-manager-api/src/lib.rs @@ -96,6 +96,8 @@ pub struct WithdrawGasRequest { pub struct CreateHotWalletRequest { /// The name of the vault backing the hot wallet pub vault: String, + /// The internal wallet ID to associate with the hot wallet + pub internal_wallet_id: Uuid, } /// The response containing the hot wallet's address diff --git a/funds-manager/funds-manager-server/src/custody_client/hot_wallets.rs b/funds-manager/funds-manager-server/src/custody_client/hot_wallets.rs index 32ccdde..a10cf04 100644 --- a/funds-manager/funds-manager-server/src/custody_client/hot_wallets.rs +++ b/funds-manager/funds-manager-server/src/custody_client/hot_wallets.rs @@ -14,6 +14,7 @@ use ethers::{ use funds_manager_api::{TokenBalance, WalletWithBalances}; use rand::thread_rng; use tracing::info; +use uuid::Uuid; use super::{CustodyClient, ERC20}; use crate::{ @@ -30,7 +31,11 @@ impl CustodyClient { /// Create a new hot wallet /// /// Returns the Arbitrum address of the hot wallet - pub async fn create_hot_wallet(&self, vault: String) -> Result { + pub async fn create_hot_wallet( + &self, + vault: String, + internal_wallet_id: Uuid, + ) -> Result { // Generate a new Ethereum keypair let wallet = LocalWallet::new(&mut thread_rng()); let address = wallet.address().encode_hex(); @@ -49,7 +54,7 @@ impl CustodyClient { .await?; // Insert the wallet metadata into the database - self.insert_hot_wallet(&address, &vault, &secret_name).await?; + self.insert_hot_wallet(&address, &vault, &secret_name, &internal_wallet_id).await?; info!("Created hot wallet with address: {} for vault: {}", address, vault); Ok(address) } @@ -111,9 +116,8 @@ impl CustodyClient { amount: f64, ) -> Result<(), FundsManagerError> { // Fetch the wallet info, then withdraw - let wallet = self.get_hot_wallet_by_vault(vault).await?; let source = DepositWithdrawSource::from_vault_name(vault)?; - self.withdraw_from_fireblocks(source, &wallet.address, mint, amount).await + self.withdraw_from_fireblocks(source, mint, amount).await } // ------------ diff --git a/funds-manager/funds-manager-server/src/custody_client/mod.rs b/funds-manager/funds-manager-server/src/custody_client/mod.rs index 225ab7e..6ff940a 100644 --- a/funds-manager/funds-manager-server/src/custody_client/mod.rs +++ b/funds-manager/funds-manager-server/src/custody_client/mod.rs @@ -118,8 +118,6 @@ impl CustodyClient { /// Get a fireblocks client pub fn get_fireblocks_client(&self) -> Result { FireblocksClientBuilder::new(&self.fireblocks_api_key, &self.fireblocks_api_secret) - // TODO: Remove the sandbox config - .with_sandbox() .build() .map_err(FundsManagerError::fireblocks) } diff --git a/funds-manager/funds-manager-server/src/custody_client/queries.rs b/funds-manager/funds-manager-server/src/custody_client/queries.rs index b8994d9..5983194 100644 --- a/funds-manager/funds-manager-server/src/custody_client/queries.rs +++ b/funds-manager/funds-manager-server/src/custody_client/queries.rs @@ -3,6 +3,7 @@ use diesel::{ExpressionMethods, QueryDsl}; use diesel_async::RunQueryDsl; use renegade_util::err_str; +use uuid::Uuid; use crate::db::models::HotWallet; use crate::db::schema::hot_wallets; @@ -27,9 +28,15 @@ impl CustodyClient { address: &str, vault: &str, secret_id: &str, + internal_wallet_id: &Uuid, ) -> Result<(), FundsManagerError> { let mut conn = self.get_db_conn().await?; - let entry = HotWallet::new(secret_id.to_string(), vault.to_string(), address.to_string()); + let entry = HotWallet::new( + secret_id.to_string(), + vault.to_string(), + address.to_string(), + *internal_wallet_id, + ); diesel::insert_into(hot_wallets::table) .values(entry) .execute(&mut conn) diff --git a/funds-manager/funds-manager-server/src/custody_client/withdraw.rs b/funds-manager/funds-manager-server/src/custody_client/withdraw.rs index 6acf5e1..00e7e7a 100644 --- a/funds-manager/funds-manager-server/src/custody_client/withdraw.rs +++ b/funds-manager/funds-manager-server/src/custody_client/withdraw.rs @@ -3,7 +3,7 @@ use std::str::FromStr; use crate::{error::FundsManagerError, helpers::get_secret}; use bigdecimal::{BigDecimal, FromPrimitive}; use ethers::signers::LocalWallet; -use fireblocks_sdk::types::TransactionStatus; +use fireblocks_sdk::types::{PeerType, TransactionStatus}; use tracing::info; use super::{CustodyClient, DepositWithdrawSource}; @@ -44,15 +44,16 @@ impl CustodyClient { pub(crate) async fn withdraw_from_fireblocks( &self, source: DepositWithdrawSource, - destination_address: &str, mint: &str, amount: f64, ) -> Result<(), FundsManagerError> { + let vault_name = source.vault_name(); let client = self.get_fireblocks_client()?; + let hot_wallet = self.get_hot_wallet_by_vault(vault_name).await?; // Get the vault account and asset to transfer from let vault = self - .get_vault_account(source.vault_name()) + .get_vault_account(vault_name) .await? .ok_or_else(|| FundsManagerError::Custom("Vault not found".to_string()))?; let asset_id = self.get_asset_id_for_address(mint).await?.ok_or_else(|| { @@ -76,14 +77,14 @@ impl CustodyClient { } // Transfer - let vault_name = source.vault_name(); - let note = - format!("Withdraw {amount} {asset_id} from {vault_name} to {destination_address}"); + let wallet_id = hot_wallet.internal_wallet_id.to_string(); + let note = format!("Withdraw {amount} {asset_id} from {vault_name} to {wallet_id}"); let (resp, _rid) = client - .create_transaction_external( + .create_transaction_peer( vault.id, - destination_address, + &wallet_id, + PeerType::INTERNAL_WALLET, asset_id, withdraw_amount, Some(¬e), diff --git a/funds-manager/funds-manager-server/src/db/models.rs b/funds-manager/funds-manager-server/src/db/models.rs index c74f415..ffcd650 100644 --- a/funds-manager/funds-manager-server/src/db/models.rs +++ b/funds-manager/funds-manager-server/src/db/models.rs @@ -86,11 +86,17 @@ pub struct HotWallet { pub secret_id: String, pub vault: String, pub address: String, + pub internal_wallet_id: Uuid, } impl HotWallet { /// Construct a new hot wallet entry - pub fn new(secret_id: String, vault: String, address: String) -> Self { - HotWallet { id: Uuid::new_v4(), secret_id, vault, address } + pub fn new( + secret_id: String, + vault: String, + address: String, + internal_wallet_id: Uuid, + ) -> Self { + HotWallet { id: Uuid::new_v4(), secret_id, vault, address, internal_wallet_id } } } diff --git a/funds-manager/funds-manager-server/src/db/schema.rs b/funds-manager/funds-manager-server/src/db/schema.rs index 69d2b2a..b1b86dd 100644 --- a/funds-manager/funds-manager-server/src/db/schema.rs +++ b/funds-manager/funds-manager-server/src/db/schema.rs @@ -18,6 +18,7 @@ diesel::table! { secret_id -> Text, vault -> Text, address -> Text, + internal_wallet_id -> Uuid, } } diff --git a/funds-manager/funds-manager-server/src/handlers.rs b/funds-manager/funds-manager-server/src/handlers.rs index c87f3c8..88155d9 100644 --- a/funds-manager/funds-manager-server/src/handlers.rs +++ b/funds-manager/funds-manager-server/src/handlers.rs @@ -129,7 +129,7 @@ pub(crate) async fn create_hot_wallet_handler( ) -> Result { let address = server .custody_client - .create_hot_wallet(req.vault) + .create_hot_wallet(req.vault, req.internal_wallet_id) .await .map_err(|e| warp::reject::custom(ApiError::InternalError(e.to_string())))?; diff --git a/funds-manager/migrations/2024-08-01-021728_add_internal_wallet_id/down.sql b/funds-manager/migrations/2024-08-01-021728_add_internal_wallet_id/down.sql new file mode 100644 index 0000000..b96e9df --- /dev/null +++ b/funds-manager/migrations/2024-08-01-021728_add_internal_wallet_id/down.sql @@ -0,0 +1,2 @@ +-- Drop the internal_wallet_id column from the hot_wallets table +ALTER TABLE hot_wallets DROP COLUMN internal_wallet_id; \ No newline at end of file diff --git a/funds-manager/migrations/2024-08-01-021728_add_internal_wallet_id/up.sql b/funds-manager/migrations/2024-08-01-021728_add_internal_wallet_id/up.sql new file mode 100644 index 0000000..e5c2d5d --- /dev/null +++ b/funds-manager/migrations/2024-08-01-021728_add_internal_wallet_id/up.sql @@ -0,0 +1,11 @@ +-- Add internal_wallet_id column as UUID +ALTER TABLE hot_wallets ADD COLUMN internal_wallet_id UUID; + +-- Generate default UUID values for existing rows +UPDATE hot_wallets +SET internal_wallet_id = gen_random_uuid() +WHERE internal_wallet_id IS NULL; + +-- Make the column NOT NULL +ALTER TABLE hot_wallets +ALTER COLUMN internal_wallet_id SET NOT NULL; \ No newline at end of file