use starknet::{
core::types::Felt,
core::{types::Call, utils::get_selector_from_name},
providers::Provider,
};
use crate::{
amount::Amount,
error::{Result, StarkzapError},
paymaster::FeeMode,
tokens::Token,
tx::Tx,
wallet::Wallet,
};
impl<P> Wallet<P>
where
P: Provider + Send + Sync + Clone + 'static,
{
pub async fn enter_pool(
&self,
token: &Token,
pool_contract: Felt,
amount: Amount,
reward_address: Felt,
fee_mode: FeeMode,
) -> Result<Tx<P>> {
let [amount_low, amount_high] = amount.to_u256_felts();
let staking_amount = felt_to_u128(amount_low)?;
if amount_high != Felt::ZERO {
return Err(StarkzapError::AmountOverflow);
}
let approve_call = approve_call(token.address, pool_contract, amount_low, amount_high)?;
let enter_selector = get_selector_from_name("enter_delegation_pool")
.map_err(|e| StarkzapError::Staking(e.to_string()))?;
let enter_call = Call {
to: pool_contract,
selector: enter_selector,
calldata: vec![reward_address, staking_amount],
};
self.execute(vec![approve_call, enter_call], fee_mode).await
}
pub async fn add_to_pool(
&self,
token: &Token,
pool_contract: Felt,
amount: Amount,
fee_mode: FeeMode,
) -> Result<Tx<P>> {
let [amount_low, amount_high] = amount.to_u256_felts();
let staking_amount = felt_to_u128(amount_low)?;
if amount_high != Felt::ZERO {
return Err(StarkzapError::AmountOverflow);
}
let approve_call = approve_call(token.address, pool_contract, amount_low, amount_high)?;
let add_selector = get_selector_from_name("add_to_delegation_pool")
.map_err(|e| StarkzapError::Staking(e.to_string()))?;
let add_call = Call {
to: pool_contract,
selector: add_selector,
calldata: vec![self.address, staking_amount],
};
self.execute(vec![approve_call, add_call], fee_mode).await
}
pub async fn exit_pool_intent(
&self,
pool_contract: Felt,
amount: Amount,
fee_mode: FeeMode,
) -> Result<Tx<P>> {
let [amount_low, amount_high] = amount.to_u256_felts();
let staking_amount = felt_to_u128(amount_low)?;
if amount_high != Felt::ZERO {
return Err(StarkzapError::AmountOverflow);
}
let selector = get_selector_from_name("exit_delegation_pool_intent")
.map_err(|e| StarkzapError::Staking(e.to_string()))?;
let call = Call {
to: pool_contract,
selector,
calldata: vec![staking_amount],
};
self.execute(vec![call], fee_mode).await
}
pub async fn exit_pool(&self, pool_contract: Felt, fee_mode: FeeMode) -> Result<Tx<P>> {
let selector = get_selector_from_name("exit_delegation_pool_action")
.map_err(|e| StarkzapError::Staking(e.to_string()))?;
let call = Call {
to: pool_contract,
selector,
calldata: vec![self.address],
};
self.execute(vec![call], fee_mode).await
}
}
fn approve_call(
token_address: Felt,
spender: Felt,
amount_low: Felt,
amount_high: Felt,
) -> Result<Call> {
let selector =
get_selector_from_name("approve").map_err(|e| StarkzapError::Staking(e.to_string()))?;
Ok(Call {
to: token_address,
selector,
calldata: vec![spender, amount_low, amount_high],
})
}
fn felt_to_u128(value: Felt) -> Result<Felt> {
let raw: u128 = value
.to_biguint()
.try_into()
.map_err(|_| StarkzapError::AmountOverflow)?;
Ok(Felt::from(raw))
}