|
| 1 | +use { |
| 2 | + crate::{ |
| 3 | + chain::ethereum::SignablePythContract, |
| 4 | + config::{ |
| 5 | + Config, |
| 6 | + WithdrawFeesOptions, |
| 7 | + }, |
| 8 | + }, |
| 9 | + anyhow::{ |
| 10 | + anyhow, |
| 11 | + Result, |
| 12 | + }, |
| 13 | + ethers::{ |
| 14 | + signers::Signer, |
| 15 | + types::Address, |
| 16 | + }, |
| 17 | +}; |
| 18 | + |
| 19 | + |
| 20 | +pub async fn withdraw_fees(opts: &WithdrawFeesOptions) -> Result<()> { |
| 21 | + let config = Config::load(&opts.config.config)?; |
| 22 | + |
| 23 | + let private_key_string = if opts.keeper { |
| 24 | + config.keeper.private_key.load()?.ok_or(anyhow!("Please specify a keeper private key in the config or omit the --keeper option to use the provider private key"))? |
| 25 | + } else { |
| 26 | + config.provider.private_key.load()?.ok_or(anyhow!( |
| 27 | + "Please specify a provider private key in the config or provide the --keeper option to use the keeper private key instead." |
| 28 | + ))? |
| 29 | + }; |
| 30 | + |
| 31 | + match opts.chain_id.clone() { |
| 32 | + Some(chain_id) => { |
| 33 | + let chain_config = &config.get_chain_config(&chain_id)?; |
| 34 | + let contract = |
| 35 | + SignablePythContract::from_config(&chain_config, &private_key_string).await?; |
| 36 | + |
| 37 | + withdraw_fees_for_chain( |
| 38 | + contract, |
| 39 | + config.provider.address.clone(), |
| 40 | + opts.keeper, |
| 41 | + opts.retain_balance_wei, |
| 42 | + ) |
| 43 | + .await?; |
| 44 | + } |
| 45 | + None => { |
| 46 | + for (chain_id, chain_config) in config.chains.iter() { |
| 47 | + tracing::info!("Withdrawing fees for chain: {}", chain_id); |
| 48 | + let contract = |
| 49 | + SignablePythContract::from_config(&chain_config, &private_key_string).await?; |
| 50 | + |
| 51 | + withdraw_fees_for_chain( |
| 52 | + contract, |
| 53 | + config.provider.address.clone(), |
| 54 | + opts.keeper, |
| 55 | + opts.retain_balance_wei, |
| 56 | + ) |
| 57 | + .await?; |
| 58 | + } |
| 59 | + } |
| 60 | + } |
| 61 | + Ok(()) |
| 62 | +} |
| 63 | + |
| 64 | +pub async fn withdraw_fees_for_chain( |
| 65 | + contract: SignablePythContract, |
| 66 | + provider_address: Address, |
| 67 | + is_fee_manager: bool, |
| 68 | + retained_balance: u128, |
| 69 | +) -> Result<()> { |
| 70 | + tracing::info!("Fetching fees for provider: {:?}", provider_address); |
| 71 | + let provider_info = contract.get_provider_info(provider_address).call().await?; |
| 72 | + let fees = provider_info.accrued_fees_in_wei; |
| 73 | + tracing::info!("Accrued fees: {} wei", fees); |
| 74 | + |
| 75 | + let withdrawal_amount_wei = fees.saturating_sub(retained_balance); |
| 76 | + if withdrawal_amount_wei > 0 { |
| 77 | + tracing::info!( |
| 78 | + "Withdrawing {} wei to {}...", |
| 79 | + withdrawal_amount_wei, |
| 80 | + contract.wallet().address() |
| 81 | + ); |
| 82 | + |
| 83 | + let call = match is_fee_manager { |
| 84 | + true => contract.withdraw_as_fee_manager(provider_address, withdrawal_amount_wei), |
| 85 | + false => contract.withdraw(withdrawal_amount_wei), |
| 86 | + }; |
| 87 | + let tx_result = call.send().await?.await?; |
| 88 | + |
| 89 | + match &tx_result { |
| 90 | + Some(receipt) => { |
| 91 | + tracing::info!("Withdrawal transaction hash {:?}", receipt.transaction_hash); |
| 92 | + } |
| 93 | + None => { |
| 94 | + tracing::warn!("No transaction receipt. Unclear what happened to the transaction"); |
| 95 | + } |
| 96 | + } |
| 97 | + } |
| 98 | + |
| 99 | + Ok(()) |
| 100 | +} |
0 commit comments