-
Notifications
You must be signed in to change notification settings - Fork 107
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
sn-provider: add a wrapper around starknet provider (#1366)
- Loading branch information
Showing
5 changed files
with
88 additions
and
73 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
pub mod starknet_provider; | ||
|
||
pub use starknet_provider::StarknetProvider; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
use crate::{ | ||
into_via_wrapper, | ||
models::felt::Felt252Wrapper, | ||
providers::eth_provider::{ | ||
error::ExecutionError, | ||
starknet::{ERC20Reader, STARKNET_NATIVE_TOKEN}, | ||
utils::{class_hash_not_declared, contract_not_found}, | ||
}, | ||
}; | ||
use reth_primitives::U256; | ||
use starknet::core::types::{BlockId, Felt}; | ||
use std::sync::Arc; | ||
use tracing::Instrument; | ||
|
||
/// A provider wrapper around the Starknet provider to expose utility methods. | ||
#[derive(Debug, Clone)] | ||
pub struct StarknetProvider<SP: starknet::providers::Provider + Send + Sync> { | ||
/// The underlying Starknet provider wrapped in an [`Arc`] for shared ownership across threads. | ||
provider: Arc<SP>, | ||
} | ||
|
||
impl<SP> StarknetProvider<SP> | ||
where | ||
SP: starknet::providers::Provider + Send + Sync, | ||
{ | ||
/// Creates a new [`StarknetProvider`] instance from an [`Arc`]-wrapped Starknet provider. | ||
pub const fn new(provider: Arc<SP>) -> Self { | ||
Self { provider } | ||
} | ||
|
||
/// Retrieves the balance of a Starknet address for a specified block. | ||
/// | ||
/// This method interacts with the Starknet native token contract to query the balance of the given | ||
/// address at a specific block. | ||
/// | ||
/// If the contract is not deployed or the class hash is not declared, a balance of 0 is returned | ||
/// instead of an error. | ||
pub async fn balance_at(&self, address: Felt, block_id: BlockId) -> Result<U256, ExecutionError> { | ||
// Create a new `ERC20Reader` instance for the Starknet native token | ||
let eth_contract = ERC20Reader::new(*STARKNET_NATIVE_TOKEN, &self.provider); | ||
|
||
// Call the `balanceOf` method on the contract for the given address and block ID, awaiting the result | ||
let span = tracing::span!(tracing::Level::INFO, "sn::balance"); | ||
let res = eth_contract.balanceOf(&address).block_id(block_id).call().instrument(span).await; | ||
|
||
// Check if the contract was not found or the class hash not declared, | ||
// returning a default balance of 0 if true. | ||
// The native token contract should be deployed on Kakarot, so this should not happen | ||
// We want to avoid errors in this case and return a default balance of 0 | ||
if contract_not_found(&res) || class_hash_not_declared(&res) { | ||
return Ok(Default::default()); | ||
} | ||
// Otherwise, extract the balance from the result, converting any errors to ExecutionError | ||
let balance = res.map_err(ExecutionError::from)?.balance; | ||
|
||
// Convert the low and high parts of the balance to U256 | ||
let low: U256 = into_via_wrapper!(balance.low); | ||
let high: U256 = into_via_wrapper!(balance.high); | ||
|
||
// Combine the low and high parts to form the final balance and return it | ||
Ok(low + (high << 128)) | ||
} | ||
} |