Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: account declaration test with katana #734

Merged
merged 2 commits into from
Sep 4, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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"
ICavlek marked this conversation as resolved.
Show resolved Hide resolved
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() {
ICavlek marked this conversation as resolved.
Show resolved Hide resolved
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
Loading