Skip to content

Commit

Permalink
test: declare test with katana
Browse files Browse the repository at this point in the history
  • Loading branch information
ICavlek committed Sep 4, 2024
1 parent a8830da commit 0b1f46f
Show file tree
Hide file tree
Showing 10 changed files with 1,598 additions and 130 deletions.
1,354 changes: 1,314 additions & 40 deletions Cargo.lock

Large diffs are not rendered by default.

14 changes: 12 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,8 @@ starknet-crypto = "0.7.1"
blockifier = "=0.8.0-rc.2"
starknet_api = "0.13.0-rc.1"
cairo-vm = "=1.0.1"
starknet-types-core = "0.1.5"
cairo-lang-starknet-classes = "2.6.4"

starknet-types-core = "0.1.5"
base64 = "0.22.0"
flate2 = "1.0.28"
ureq = { version = "2.10.0", features = ["json"] }
Expand All @@ -61,4 +60,15 @@ toml = "0.8.19"
clap = { version = "4.5.13", features = ["derive"] }

[dev-dependencies]
anyhow = "1.0.86"
alloy-primitives = { version = "0.7.6", default-features = false }
katana-core = { git = "https://github.com/dojoengine/dojo", tag = "v1.0.0-alpha.9" }
katana-executor = { git = "https://github.com/dojoengine/dojo", tag = "v1.0.0-alpha.9" }
katana-node = { git = "https://github.com/dojoengine/dojo", tag = "v1.0.0-alpha.9" }
katana-primitives = { git = "https://github.com/dojoengine/dojo", tag = "v1.0.0-alpha.9" }
katana-rpc = { git = "https://github.com/dojoengine/dojo", tag = "v1.0.0-alpha.9" }
katana-rpc-api = { git = "https://github.com/dojoengine/dojo", tag = "v1.0.0-alpha.9" }
wiremock = "0.6.1"

[patch.crates-io]
starknet-core = { git = "https://github.com/kariy/starknet-rs", branch = "dojo-patch" }
72 changes: 72 additions & 0 deletions tests/account_declaration.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
use std::{thread, time};

use beerus::gen::BroadcastedDeclareTxn;
use beerus::gen::{
client::Client, Address, BlockId, BlockTag, BroadcastedTxn, Felt, Rpc,
SimulationFlagForEstimateFee,
};
use common::constants::{COMPILED_ACCOUNT_CONTRACT, DECLARE_ACCOUNT};
use common::katana::Katana;

mod common;

#[tokio::test]
async fn declare_account() {
let url = "http://127.0.0.1:5050";
let katana = Katana::init(url).await.unwrap();
let client = Client::new(url);

let res_chain_id = client.chainId().await;
assert!(res_chain_id.is_ok());
assert_eq!(res_chain_id.unwrap().as_ref(), "0x4b4154414e41");

let block_id = BlockId::BlockTag(BlockTag::Pending);
let class_hash = Felt::try_new(
"0x6b46f84b1bbb779e588a9c5f577907c3dfb66e6b13cf4c4f480d4fb1677c2ba",
)
.unwrap();
let res_class = client.getClass(block_id.clone(), class_hash).await;
assert!(res_class.is_err());
assert!(res_class.unwrap_err().message.contains("Class hash not found"));

let contract_address = Address(
Felt::try_new(
"0x6162896d1d7ab204c7ccac6dd5f8e9e7c25ecd5ae4fcb4ad32e57786bb46e03",
)
.unwrap(),
);
let res_nonce = client.getNonce(block_id, contract_address).await;
assert!(res_nonce.is_ok());
assert_eq!(res_nonce.unwrap().as_ref(), "0x0");

let res_spec_version = client.specVersion().await;
assert!(res_spec_version.is_ok());
assert_eq!(res_spec_version.unwrap().as_str(), "0.7.1");

let contract: Vec<BroadcastedTxn> =
serde_json::from_str(COMPILED_ACCOUNT_CONTRACT).unwrap();
let simulation_flags: Vec<SimulationFlagForEstimateFee> = vec![];
let block_id = BlockId::BlockTag(BlockTag::Pending);
let res_estimate_fee =
client.estimateFee(contract, simulation_flags, block_id).await;
assert!(res_estimate_fee.is_ok());

let declare_account: BroadcastedDeclareTxn =
serde_json::from_str(DECLARE_ACCOUNT).unwrap();
let res_declare_account =
client.addDeclareTransaction(declare_account).await;
assert!(res_declare_account.is_ok());

let block_mining_time = time::Duration::from_millis(1000);
thread::sleep(block_mining_time);

let block_id = BlockId::BlockTag(BlockTag::Pending);
let class_hash = Felt::try_new(
"0x6b46f84b1bbb779e588a9c5f577907c3dfb66e6b13cf4c4f480d4fb1677c2ba",
)
.unwrap();
let res_class = client.getClass(block_id.clone(), class_hash).await;
assert!(res_class.is_ok());

katana.stop().unwrap();
}
5 changes: 5 additions & 0 deletions tests/common/constants.rs

Large diffs are not rendered by default.

71 changes: 71 additions & 0 deletions tests/common/context.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
use std::sync::Arc;

use beerus::client::State;
use beerus::gen::Felt;
use beerus::{
gen::client::Client,
rpc::{serve, Server},
};
use tokio::sync::RwLock;

#[allow(dead_code)] // used in macros
pub struct Context {
pub client: Client,
pub server: Server,
}

#[allow(dead_code)] // used in macros
pub async fn ctx() -> Option<Context> {
let url = std::env::var("BEERUS_TEST_STARKNET_URL").ok()?;

let root =
"0x2a5aa70350b7d047cd3dd2f5ad01f8925409a64fc42e509e8e79c3a2c17425";
let state = State {
block_number: 652076,
block_hash: Felt::try_new("0x0").unwrap(),
root: Felt::try_new(root).unwrap(),
};
let state = Arc::new(RwLock::new(state));
let server = serve(&url, "127.0.0.1:0", state.clone()).await.ok()?;
tracing::info!(port = server.port(), "test server is up");

let url = format!("http://localhost:{}/rpc", server.port());
let client = Client::new(&url);
Some(Context { server, client })
}

#[macro_export]
macro_rules! setup {
() => {{
let run: bool = std::env::var("BEERUS_TEST_RUN")
.ok()
.map(|value| &value == "1")
.unwrap_or_default();
if !run {
return Ok(());
}
if let Some(ctx) = common::context::ctx().await {
ctx
} else {
panic!("Invalid test setup");
}
}};
}

#[macro_export]
macro_rules! client {
() => {{
let run: bool = std::env::var("BEERUS_TEST_RUN")
.ok()
.map(|value| &value == "1")
.unwrap_or_default();
if !run {
return Ok(());
}
if let Ok(url) = std::env::var("BEERUS_TEST_STARKNET_URL") {
Client::new(&url)
} else {
panic!("Invalid test setup");
}
}};
}
15 changes: 15 additions & 0 deletions tests/common/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
use thiserror::Error;

#[derive(Debug, Error)]
pub enum Error {
#[error("rpc call failed: {0:?}")]
Rpc(#[from] iamgroot::jsonrpc::Error),
#[error("missing env variable: {0:?}")]
Var(#[from] std::env::VarError),
#[error("execution failed: {0:?}")]
Exe(#[from] beerus::exe::err::Error),
#[error("serde failed: {0:?}")]
Json(#[from] serde_json::Error),
#[error("starknet api error: {0:?}")]
Api(#[from] starknet_api::StarknetApiError),
}
103 changes: 103 additions & 0 deletions tests/common/katana.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
use std::str::FromStr;

use alloy_primitives::U256;
use anyhow::Result;
use katana_core::backend::config::{Environment, StarknetConfig};
use katana_core::constants::DEFAULT_SEQUENCER_ADDRESS;
#[allow(deprecated)]
use katana_core::sequencer::SequencerConfig;
use katana_node::{start, NodeHandle};
use katana_primitives::block::GasPrices;
use katana_primitives::chain::ChainId;
use katana_primitives::genesis::{
allocation::DevAllocationsGenerator,
constant::DEFAULT_PREFUNDED_ACCOUNT_BALANCE, Genesis,
};
use katana_rpc::config::ServerConfig;
use katana_rpc_api::ApiKind;
use starknet_types_core::felt::Felt;
use url::Url;

pub struct Katana {
rpc_handle: NodeHandle,
}

impl Katana {
#[allow(dead_code)]
pub async fn init(url: &str) -> Result<Self> {
let sequencer_config = get_sequencer_config();
let server_config = get_server_config(url)?;
let starknet_config = get_starknet_config();
let (rpc_handle, _) =
start(server_config, sequencer_config, starknet_config).await?;
Ok(Katana { rpc_handle })
}

#[allow(dead_code)]
pub fn stop(&self) -> Result<()> {
self.rpc_handle.handle.stop()?;
Ok(())
}
}

#[allow(deprecated)]
#[allow(dead_code)]
fn get_sequencer_config() -> SequencerConfig {
SequencerConfig { block_time: None, no_mining: false }
}

#[allow(dead_code)]
fn get_server_config(url: &str) -> Result<ServerConfig> {
let url = Url::parse(url)?;
Ok(ServerConfig {
apis: vec![
ApiKind::Starknet,
ApiKind::Katana,
ApiKind::Torii,
ApiKind::Saya,
],
port: url.port().unwrap(),
host: url.host().unwrap().to_string(),
max_connections: 100,
allowed_origins: None,
metrics: None,
})
}

#[allow(dead_code)]
fn get_starknet_config() -> StarknetConfig {
let gas_prices = GasPrices { eth: 100000000000, strk: 100000000000 };
let accounts = DevAllocationsGenerator::new(10)
.with_seed(parse_seed("0"))
.with_balance(U256::from(DEFAULT_PREFUNDED_ACCOUNT_BALANCE))
.generate();
let mut genesis = Genesis {
gas_prices,
sequencer_address: *DEFAULT_SEQUENCER_ADDRESS,
..Default::default()
};
genesis
.extend_allocations(accounts.into_iter().map(|(k, v)| (k, v.into())));

StarknetConfig {
disable_fee: true,
disable_validate: false,
fork_rpc_url: None,
fork_block_number: None,
env: Environment {
chain_id: ChainId::Id(Felt::from_str("0x4b4154414e41").unwrap()),
invoke_max_steps: 1000000,
validate_max_steps: 1000000,
},
db_dir: None,
genesis,
}
}

#[allow(dead_code)]
fn parse_seed(seed: &str) -> [u8; 32] {
let seed = seed.as_bytes();
let mut actual_seed = [0u8; 32];
seed.iter().enumerate().for_each(|(i, b)| actual_seed[i] = *b);
actual_seed
}
90 changes: 4 additions & 86 deletions tests/common/mod.rs
Original file line number Diff line number Diff line change
@@ -1,86 +1,4 @@
use std::sync::Arc;

use beerus::client::State;
use beerus::gen::Felt;
use beerus::{
gen::client::Client,
rpc::{serve, Server},
};
use thiserror::Error;
use tokio::sync::RwLock;

#[allow(dead_code)] // used in macros
pub struct Context {
pub client: Client,
pub server: Server,
}

#[allow(dead_code)] // used in macros
pub async fn ctx() -> Option<Context> {
let url = std::env::var("BEERUS_TEST_STARKNET_URL").ok()?;

let root =
"0x2a5aa70350b7d047cd3dd2f5ad01f8925409a64fc42e509e8e79c3a2c17425";
let state = State {
block_number: 652076,
block_hash: Felt::try_new("0x0").unwrap(),
root: Felt::try_new(root).unwrap(),
};
let state = Arc::new(RwLock::new(state));
let server = serve(&url, "127.0.0.1:0", state.clone()).await.ok()?;
tracing::info!(port = server.port(), "test server is up");

let url = format!("http://localhost:{}/rpc", server.port());
let client = Client::new(&url);
Some(Context { server, client })
}

#[macro_export]
macro_rules! setup {
() => {{
let run: bool = std::env::var("BEERUS_TEST_RUN")
.ok()
.map(|value| &value == "1")
.unwrap_or_default();
if !run {
return Ok(());
}
if let Some(ctx) = common::ctx().await {
ctx
} else {
panic!("Invalid test setup");
}
}};
}

#[macro_export]
macro_rules! client {
() => {{
let run: bool = std::env::var("BEERUS_TEST_RUN")
.ok()
.map(|value| &value == "1")
.unwrap_or_default();
if !run {
return Ok(());
}
if let Ok(url) = std::env::var("BEERUS_TEST_STARKNET_URL") {
Client::new(&url)
} else {
panic!("Invalid test setup");
}
}};
}

#[derive(Debug, Error)]
pub enum Error {
#[error("rpc call failed: {0:?}")]
Rpc(#[from] iamgroot::jsonrpc::Error),
#[error("missing env variable: {0:?}")]
Var(#[from] std::env::VarError),
#[error("execution failed: {0:?}")]
Exe(#[from] beerus::exe::err::Error),
#[error("serde failed: {0:?}")]
Json(#[from] serde_json::Error),
#[error("starknet api error: {0:?}")]
Api(#[from] starknet_api::StarknetApiError),
}
pub mod constants;
pub mod context;
pub mod error;
pub mod katana;
2 changes: 1 addition & 1 deletion tests/exe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use beerus::{

mod common;

use common::Error;
use common::error::Error;

#[test]
fn test_call_deprecated_contract_class() -> Result<(), Error> {
Expand Down
Loading

0 comments on commit 0b1f46f

Please sign in to comment.