Skip to content

Commit

Permalink
funds-manager: Add internal wallet id mapping & use internal transaction
Browse files Browse the repository at this point in the history
  • Loading branch information
joeykraut committed Aug 1, 2024
1 parent 7f2fcc5 commit 58024ac
Show file tree
Hide file tree
Showing 10 changed files with 50 additions and 18 deletions.
2 changes: 2 additions & 0 deletions funds-manager/funds-manager-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand All @@ -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<String, FundsManagerError> {
pub async fn create_hot_wallet(
&self,
vault: String,
internal_wallet_id: Uuid,
) -> Result<String, FundsManagerError> {
// Generate a new Ethereum keypair
let wallet = LocalWallet::new(&mut thread_rng());
let address = wallet.address().encode_hex();
Expand All @@ -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)
}
Expand Down Expand Up @@ -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
}

// ------------
Expand Down
2 changes: 0 additions & 2 deletions funds-manager/funds-manager-server/src/custody_client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,6 @@ impl CustodyClient {
/// Get a fireblocks client
pub fn get_fireblocks_client(&self) -> Result<FireblocksClient, FundsManagerError> {
FireblocksClientBuilder::new(&self.fireblocks_api_key, &self.fireblocks_api_secret)
// TODO: Remove the sandbox config
.with_sandbox()
.build()
.map_err(FundsManagerError::fireblocks)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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(|| {
Expand All @@ -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(&note),
Expand Down
10 changes: 8 additions & 2 deletions funds-manager/funds-manager-server/src/db/models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
}
}
1 change: 1 addition & 0 deletions funds-manager/funds-manager-server/src/db/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ diesel::table! {
secret_id -> Text,
vault -> Text,
address -> Text,
internal_wallet_id -> Uuid,
}
}

Expand Down
2 changes: 1 addition & 1 deletion funds-manager/funds-manager-server/src/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ pub(crate) async fn create_hot_wallet_handler(
) -> Result<Json, warp::Rejection> {
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())))?;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-- Drop the internal_wallet_id column from the hot_wallets table
ALTER TABLE hot_wallets DROP COLUMN internal_wallet_id;
Original file line number Diff line number Diff line change
@@ -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;

0 comments on commit 58024ac

Please sign in to comment.