diff --git a/Cargo.lock b/Cargo.lock index 20ee2f34f..adb2121e5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -268,18 +268,6 @@ dependencies = [ "hashbrown 0.13.2", ] -[[package]] -name = "ark-rs" -version = "0.1.0" -dependencies = [ - "anyhow", - "ark-indexer", - "ark-metadata", - "ark-starknet", - "ark-storage", - "tokio", -] - [[package]] name = "ark-secp256k1" version = "0.4.0" @@ -378,6 +366,23 @@ dependencies = [ "url", ] +[[package]] +name = "arkproject" +version = "0.1.0" +dependencies = [ + "anyhow", + "ark-indexer", + "ark-metadata", + "ark-starknet", + "ark-storage", + "arkchain-indexer", + "async-trait", + "futures", + "log", + "starknet 0.5.0", + "tokio", +] + [[package]] name = "arrayvec" version = "0.7.4" diff --git a/Cargo.toml b/Cargo.toml index 09e1a453c..22b5f4717 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "ark-rs" +name = "arkproject" version = "0.1.0" edition = "2021" authors = ["Screenshot Labs", "Starknet community"] @@ -27,20 +27,26 @@ ark-starknet = { path = "./crates/ark-starknet" } ark-metadata = { path = "./crates/ark-metadata" } ark-storage = { path = "./crates/ark-storage" } ark-indexer = { path = "./crates/ark-indexer" } +arkchain-indexer = { path = "./crates/ark-chain/indexer" } async-trait = "0.1.73" starknet = "0.5.0" anyhow = "1.0" tokio = { version = "1", features = ["full"] } +log = "0.4.17" # Thoses dependencies are used by the examples + the lib.rs. [dependencies] +futures = "0.3.28" +async-trait.workspace = true +log.workspace = true anyhow.workspace = true tokio.workspace = true ark-starknet.workspace = true ark-metadata.workspace = true ark-storage.workspace = true ark-indexer.workspace = true - +arkchain-indexer.workspace = true +starknet.workspace = true [patch."https://github.com/starkware-libs/blockifier"] blockifier = { git = "https://github.com/dojoengine/blockifier", rev = "c794d1b" } diff --git a/crates/ark-chain/contracts/arkchain/Makefile b/crates/ark-chain/contracts/arkchain/Makefile new file mode 100644 index 000000000..bf9bdb974 --- /dev/null +++ b/crates/ark-chain/contracts/arkchain/Makefile @@ -0,0 +1,30 @@ +config := --account ../solis_account1.json \ + --keystore ../solis_key1.json \ + --rpc http://127.0.0.1:7070 \ + --keystore-password 1234 + +ob_cl = $(shell starkli class-hash target/dev/arkchain_orderbook.sierra.json) +ob_addr := 0x008707b3296680b4f67430509ee8655f86ce3c844d7223cb52b01412a6c45eff + +ark_executor_sn := 0x0573e38d2b37032172a1f9b370bd81954a0d44934e38154ff75a678700b73430 + +# Solis accounts +# has token 1 and 2 +solis_2 := 0x47abb77acbb2f65006a42b14fed3664bafb0d102c00a97be58618d49d5186ac +# has token 3 and 4 +solis_3 := 0x4c077c4085945fa6ea7116ec3c4579de29b10bd65aaf77cf4cf4f85af3ef609 +# collection +erc721_address := 0x044b07a8c955296dd52a9d7d31a400b16ad4f6f574aa57db79cac0e87eac48cd + +setup: + scarb build + starkli declare target/dev/arkchain_orderbook.sierra.json ${config} + starkli deploy ${ob_cl} 0x3ee9e18edc71a6df30ac3aca2e0b02a198fbce19b7480a63a0d71cbd76652e0 ${config} --salt 0x1234 + starkli invoke ${ob_addr} set_executor_sn_address ${ark_executor_sn} ${config} + + starkli invoke ${ob_addr} register_broker str:b1 1 str:starknet_testnet ${config} + + starkli invoke ${ob_addr} add_order_listing ${solis_2} ${erc721_address} u256:1 u256:77 0 str:b1 0 0 ${config} + + starkli invoke ${ob_addr} submit_order_buy 0x51a397add04213bb487668b635bedefdbbe5fb8f5b9d3aad6164031b60958b ${solis_3} str:b1 0 0 ${config} + diff --git a/crates/ark-chain/contracts/solis_account1.json b/crates/ark-chain/contracts/solis_account1.json new file mode 100644 index 000000000..5d14b451d --- /dev/null +++ b/crates/ark-chain/contracts/solis_account1.json @@ -0,0 +1,13 @@ +{ + "version": 1, + "variant": { + "type": "open_zeppelin", + "version": 1, + "public_key": "0x7f00d91354c3848de72fe99c94e07d89b61362a18a8137f4d0fc6057fded169" + }, + "deployment": { + "status": "deployed", + "class_hash": "0x4d07e40e93398ed3c76981e72dd1fd22557a78ce36c0515f679e27f0bb5bc5f", + "address": "0x3c2c23f8389cffce8f698c4f3d3d771a979ddce14de15e6ae14b56c8e4e355b" + } +} diff --git a/crates/ark-chain/contracts/solis_key1.json b/crates/ark-chain/contracts/solis_key1.json new file mode 100644 index 000000000..032017b89 --- /dev/null +++ b/crates/ark-chain/contracts/solis_key1.json @@ -0,0 +1 @@ +{"crypto":{"cipher":"aes-128-ctr","cipherparams":{"iv":"9b94bbb390d9b67ce2a52de1a2828b24"},"ciphertext":"5e2f576ed9e33eec395a96538ea1710114e85fbe7c29138360b8666883794e4e","kdf":"scrypt","kdfparams":{"dklen":32,"n":8192,"p":1,"r":8,"salt":"6a2931cfd19a5ab69874e7fe1e70c6ad12e2984e57711a30801ed1e90aa7c8e8"},"mac":"f4c42c6861134e8a2c5e43f2ede9a1f3ba23609953f46924e3b7f4eacbc2750d"},"id":"ee5ca82e-5e7a-4ae8-ac6e-8a2d178f2197","version":3} \ No newline at end of file diff --git a/crates/ark-chain/indexer/src/lib.rs b/crates/ark-chain/indexer/src/lib.rs index f27c1e70b..911377d07 100644 --- a/crates/ark-chain/indexer/src/lib.rs +++ b/crates/ark-chain/indexer/src/lib.rs @@ -26,7 +26,7 @@ const EVENT_SELECTORS: &[FieldElement; 4] = &[ EV_ORDER_BUY_FINALIZED, ]; -type IndexerResult = Result; +pub type IndexerResult = Result; #[derive(Debug, thiserror::Error)] pub enum IndexerError { diff --git a/crates/ark-chain/indexer/src/storage.rs b/crates/ark-chain/indexer/src/storage.rs index 99de155f4..e07f0ddf9 100644 --- a/crates/ark-chain/indexer/src/storage.rs +++ b/crates/ark-chain/indexer/src/storage.rs @@ -2,7 +2,7 @@ use ark_starknet::CairoU256; use async_trait::async_trait; use starknet::core::types::FieldElement; -type StorageResult = Result; +pub type StorageResult = Result; #[derive(Debug, thiserror::Error)] pub enum StorageError { @@ -31,6 +31,7 @@ pub trait ArkchainStorage { async fn set_order_finalized(&self, order: OrderFinalizedData) -> StorageResult<()>; } +#[derive(Debug)] pub struct BrokerData { pub name: FieldElement, pub chain_id: FieldElement, @@ -38,6 +39,7 @@ pub struct BrokerData { pub public_key: FieldElement, } +#[derive(Debug)] pub struct OrderListingData { pub order_hash: FieldElement, pub broker_name: FieldElement, @@ -49,6 +51,7 @@ pub struct OrderListingData { pub price: CairoU256, } +#[derive(Debug)] pub struct OrderBuyExecutingData { pub order_hash: FieldElement, pub broker_name: FieldElement, @@ -57,6 +60,7 @@ pub struct OrderBuyExecutingData { pub buyer: FieldElement, } +#[derive(Debug)] pub struct OrderFinalizedData { pub order_hash: FieldElement, pub timestamp: u64, diff --git a/crates/ark-chain/solis/src/args.rs b/crates/ark-chain/solis/src/args.rs index e07fd09fe..0f5aa5497 100644 --- a/crates/ark-chain/solis/src/args.rs +++ b/crates/ark-chain/solis/src/args.rs @@ -31,8 +31,10 @@ pub struct KatanaArgs { #[arg(long)] #[arg(value_name = "PATH")] #[arg(help = "Dump the state of chain on exit to the given file.")] - #[arg(long_help = "Dump the state of chain on exit to the given file. If the value is a \ - directory, the state will be written to `/state.bin`.")] + #[arg( + long_help = "Dump the state of chain on exit to the given file. If the value is a \ + directory, the state will be written to `/state.bin`." + )] pub dump_state: Option, #[arg(long)] @@ -55,9 +57,11 @@ pub struct KatanaArgs { #[arg(long)] #[arg(value_name = "PATH")] #[arg(help = "Configure the messaging with an other chain.")] - #[arg(long_help = "Configure the messaging to allow Katana listening/sending messages on a \ + #[arg( + long_help = "Configure the messaging to allow Katana listening/sending messages on a \ settlement chain that can be Ethereum or an other Starknet sequencer. \ - The configuration file details and examples can be found here: TODO.")] + The configuration file details and examples can be found here: TODO." + )] pub messaging: Option, #[command(flatten)] @@ -140,7 +144,11 @@ impl KatanaArgs { fork_block_number: self.fork_block_number, env: Environment { chain_id: self.starknet.environment.chain_id.clone(), - gas_price: self.starknet.environment.gas_price.unwrap_or(DEFAULT_GAS_PRICE), + gas_price: self + .starknet + .environment + .gas_price + .unwrap_or(DEFAULT_GAS_PRICE), invoke_max_steps: self .starknet .environment @@ -163,7 +171,9 @@ fn parse_seed(seed: &str) -> [u8; 32] { unsafe { *(seed[..32].as_ptr() as *const [u8; 32]) } } else { let mut actual_seed = [0u8; 32]; - seed.iter().enumerate().for_each(|(i, b)| actual_seed[i] = *b); + seed.iter() + .enumerate() + .for_each(|(i, b)| actual_seed[i] = *b); actual_seed } } @@ -178,8 +188,14 @@ mod test { let block_context = args.starknet_config().block_context(); assert_eq!(block_context.gas_price, DEFAULT_GAS_PRICE); assert_eq!(block_context.chain_id.0, "KATANA".to_string()); - assert_eq!(block_context.validate_max_n_steps, DEFAULT_VALIDATE_MAX_STEPS); - assert_eq!(block_context.invoke_tx_max_n_steps, DEFAULT_INVOKE_MAX_STEPS); + assert_eq!( + block_context.validate_max_n_steps, + DEFAULT_VALIDATE_MAX_STEPS + ); + assert_eq!( + block_context.invoke_tx_max_n_steps, + DEFAULT_INVOKE_MAX_STEPS + ); } #[test] diff --git a/crates/ark-chain/solis/src/main.rs b/crates/ark-chain/solis/src/main.rs index 03f60e6fd..c7b68012b 100644 --- a/crates/ark-chain/solis/src/main.rs +++ b/crates/ark-chain/solis/src/main.rs @@ -1,8 +1,8 @@ +use std::fs; use std::process::exit; use std::sync::Arc; -use std::{fs}; -use clap::{Parser}; +use clap::Parser; use console::Style; use katana_core::sequencer::{KatanaSequencer, Sequencer}; use katana_rpc::{spawn, KatanaApi, NodeHandle, StarknetApi}; @@ -110,4 +110,3 @@ pub async fn shutdown_handler(sequencer: Arc, config: KatanaArgs } }; } - diff --git a/crates/ark-indexer/src/managers/block_manager.rs b/crates/ark-indexer/src/managers/block_manager.rs index 72a08fe6e..417951a29 100644 --- a/crates/ark-indexer/src/managers/block_manager.rs +++ b/crates/ark-indexer/src/managers/block_manager.rs @@ -59,7 +59,7 @@ impl<'a, T: StorageManager, C: StarknetClient> BlockManager<'a, T, C> { if *do_force { return self.storage.clean_block(block_number).is_ok(); } - + match self.storage.get_block_info(block_number) { Ok(info) => { if self.indexer_version > info.indexer_version { diff --git a/crates/ark-starknet/src/client/mod.rs b/crates/ark-starknet/src/client/mod.rs index 01bf76d32..762faae99 100644 --- a/crates/ark-starknet/src/client/mod.rs +++ b/crates/ark-starknet/src/client/mod.rs @@ -12,7 +12,9 @@ use std::marker::Sized; #[async_trait] pub trait StarknetClient { /// - fn new(rpc_url: &str) -> Result where Self: Sized; + fn new(rpc_url: &str) -> Result + where + Self: Sized; /// async fn block_id_to_u64(&self, id: &BlockId) -> Result; diff --git a/crates/ark-starknet/src/lib.rs b/crates/ark-starknet/src/lib.rs index 5a7dd2436..8ed3f28ae 100644 --- a/crates/ark-starknet/src/lib.rs +++ b/crates/ark-starknet/src/lib.rs @@ -1,5 +1,6 @@ pub mod client; +#[derive(Debug)] pub struct CairoU256 { pub low: u128, pub high: u128, diff --git a/examples/arkchain_indexer.rs b/examples/arkchain_indexer.rs new file mode 100644 index 000000000..e95e72ddf --- /dev/null +++ b/examples/arkchain_indexer.rs @@ -0,0 +1,70 @@ +//! How to use arkchain indexer library. +//! +//! Can be run with `cargo run --example arkchain_indexer`. +//! +use anyhow::Result; +use arkproject::{ + arkchain::{storage::*, ArkchainIndexer}, + starknet::client::{StarknetClient, StarknetClientHttp}, +}; +use async_trait::async_trait; +use starknet::core::types::BlockId; +use std::sync::Arc; + +#[tokio::main] +async fn main() -> Result<()> { + let client = StarknetClientHttp::new("http://127.0.0.1:7070").unwrap(); + let storage = DefaultStorage {}; + + // Here, we can define any logic we want to index blocks range etc.. + // We can then use the same reference across threads to work with only one + // ArkchainIndexer instance. + let indexer = Arc::new(ArkchainIndexer::new(Arc::new(client), Arc::new(storage))); + + let mut handles = vec![]; + + for i in 0..3 { + let indexer = Arc::clone(&indexer); + let handle = tokio::spawn(async move { + let from = BlockId::Number(i * 10); + let to = BlockId::Number(i * 10 + 5); + println!("Indexer [{:?} - {:?}] started!", from, to); + match indexer.index_block_range(from, to).await { + Ok(_) => println!("Indexer [{:?} - {:?}] completed!", from, to), + Err(e) => println!("Indexer [{:?} - {:?}] failed! [{:?}]", from, to, e), + } + }); + + handles.push(handle); + } + + futures::future::join_all(handles).await; + + Ok(()) +} + +// Default storate that logs stuff. +struct DefaultStorage; + +#[async_trait] +impl ArkchainStorage for DefaultStorage { + async fn register_broker(&self, broker: BrokerData) -> StorageResult<()> { + println!("\n*** register broker\n{:?}", broker); + Ok(()) + } + + async fn add_listing_order(&self, order: OrderListingData) -> StorageResult<()> { + println!("\n*** add listing order \n{:?}", order); + Ok(()) + } + + async fn set_order_buy_executing(&self, order: OrderBuyExecutingData) -> StorageResult<()> { + println!("\n*** buy executing order \n{:?}", order); + Ok(()) + } + + async fn set_order_finalized(&self, order: OrderFinalizedData) -> StorageResult<()> { + println!("\n*** order finalized \n{:?}", order); + Ok(()) + } +} diff --git a/examples/nft_indexer.rs b/examples/nft_indexer.rs index 45a8151f2..d58b06e59 100644 --- a/examples/nft_indexer.rs +++ b/examples/nft_indexer.rs @@ -3,7 +3,7 @@ //! Can be run with `cargo run --example nft_indexer`. //! use anyhow::Result; -use ark_rs::{nft_indexer, nft_storage::DefaultStorage}; +use arkproject::{nft_indexer, nft_storage::DefaultStorage}; #[tokio::main] async fn main() -> Result<()> { diff --git a/src/lib.rs b/src/lib.rs index cdd051c45..51eda200c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,3 +11,8 @@ pub mod nft_indexer { pub mod nft_storage { pub use ark_storage::*; } + +// TODO: need to rework the organization of those crates. +pub mod arkchain { + pub use arkchain_indexer::*; +}