-
Notifications
You must be signed in to change notification settings - Fork 247
Expand file tree
/
Copy pathestimate_transaction_fee.rs
More file actions
90 lines (75 loc) · 2.98 KB
/
estimate_transaction_fee.rs
File metadata and controls
90 lines (75 loc) · 2.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
use std::sync::Arc;
use utoipa::ToSchema;
use crate::{
error::KoraError,
fee::fee::FeeConfigUtil,
state::{get_config, get_request_signer_with_signer_key},
token::token::TokenUtil,
transaction::{TransactionUtil, VersionedTransactionResolved},
};
use solana_sdk::pubkey::Pubkey;
use std::str::FromStr;
use serde::{Deserialize, Serialize};
use solana_client::nonblocking::rpc_client::RpcClient;
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct EstimateTransactionFeeRequest {
pub transaction: String, // Base64 encoded serialized transaction
#[serde(default)]
pub fee_token: Option<String>,
/// Optional signer signer_key to ensure consistency across related RPC calls
#[serde(default, skip_serializing_if = "Option::is_none")]
pub signer_key: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct EstimateTransactionFeeResponse {
pub fee_in_lamports: u64,
pub fee_in_token: Option<f64>,
/// Public key of the signer used for fee estimation (for client consistency)
pub signer_pubkey: String,
/// Public key of the payment destination
pub payment_address: String,
}
pub async fn estimate_transaction_fee(
rpc_client: &Arc<RpcClient>,
request: EstimateTransactionFeeRequest,
) -> Result<EstimateTransactionFeeResponse, KoraError> {
let transaction = TransactionUtil::decode_b64_transaction(&request.transaction)?;
let signer = get_request_signer_with_signer_key(request.signer_key.as_deref())?;
let config = get_config()?;
let payment_destination = config.kora.get_payment_address(&signer.solana_pubkey())?;
let validation_config = &config.validation;
let fee_payer = signer.solana_pubkey();
let mut resolved_transaction =
VersionedTransactionResolved::from_transaction(&transaction, rpc_client).await?;
let fee_in_lamports = FeeConfigUtil::estimate_transaction_fee(
rpc_client,
&mut resolved_transaction,
&fee_payer,
validation_config.is_payment_required(),
)
.await?;
let mut fee_in_token = None;
// If fee_token is provided, calculate the fee in that token
if let Some(fee_token) = &request.fee_token {
let token_mint = Pubkey::from_str(fee_token).map_err(|_| {
KoraError::InvalidTransaction("Invalid fee token mint address".to_string())
})?;
if !validation_config.supports_token(fee_token) {
return Err(KoraError::InvalidRequest(format!("Token {fee_token} is not supported")));
}
let fee_value_in_token = TokenUtil::calculate_lamports_value_in_token(
fee_in_lamports,
&token_mint,
&validation_config.price_source,
rpc_client,
)
.await?;
fee_in_token = Some(fee_value_in_token);
}
Ok(EstimateTransactionFeeResponse {
fee_in_lamports,
fee_in_token,
signer_pubkey: fee_payer.to_string(),
payment_address: payment_destination.to_string(),
})
}