Skip to content

Commit

Permalink
add usage example
Browse files Browse the repository at this point in the history
  • Loading branch information
kariy committed Aug 7, 2023
1 parent b764ffb commit 8548b6f
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 4 deletions.
13 changes: 13 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ members = [
"crates/katana/rpc",
"crates/sozo",
"crates/torii",
"examples/client",
]

[workspace.package]
Expand Down
15 changes: 15 additions & 0 deletions examples/client/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[package]
edition = "2021"
name = "client"
version = "0.1.0"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
async-trait.workspace = true
dojo-client = { path = "../../crates/dojo-client" }
starknet.workspace = true
tokio.workspace = true
tracing-subscriber.workspace = true
tracing.workspace = true
url = "2.2.2"
63 changes: 63 additions & 0 deletions examples/client/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
//! This example demonstrates how to use the `WorldPartialSyncer` to sync a single entity from the
//! world contract. The entity is synced to an in-memory storage, and then the storage is queried
//! for the entity's component.
//!
//! This uses the example project under `examples/ecs`.
use std::sync::Arc;
use std::time::Duration;

use dojo_client::contract::world::WorldContractReader;
use dojo_client::storage::EntityStorage;
use dojo_client::sync::{EntityComponentRequest, WorldPartialSyncer};
use starknet::core::types::FieldElement;
use starknet::core::utils::cairo_short_string_to_felt;
use starknet::providers::jsonrpc::HttpTransport;
use starknet::providers::JsonRpcClient;
use storage::InMemoryStorage;
use tokio::sync::RwLock;
use url::Url;

mod storage;

#[tokio::main]
async fn main() {
let client =
JsonRpcClient::new(HttpTransport::new(Url::parse("http://localhost:5050").unwrap()));

let world_address = FieldElement::from_hex_be(
"0x1e94df0369223154c60ed27db2a15677edcdb05e90cc4a54f091671fc399c90",
)
.unwrap();
let key = FieldElement::from_hex_be(
"0x3ee9e18edc71a6df30ac3aca2e0b02a198fbce19b7480a63a0d71cbd76652e0",
)
.unwrap();

let storage = Arc::new(RwLock::new(InMemoryStorage::new()));
let storage_clone = Arc::clone(&storage);

tokio::task::spawn(async move {
loop {
// Read the entity's position directly from the storage.
let values = storage_clone
.read()
.await
.get(cairo_short_string_to_felt("Position").unwrap(), vec![key], 2)
.await;

println!("Position x {:#x} y {:#x}", values[0], values[1]);
tokio::time::sleep(Duration::from_secs(2)).await;
}
});

let world_reader = WorldContractReader::new(world_address, &client);

let mut partial_syncer = WorldPartialSyncer::new(
storage,
&world_reader,
vec![EntityComponentRequest { component: String::from("Position"), keys: vec![key] }],
);

partial_syncer.start().await;
}
49 changes: 49 additions & 0 deletions examples/client/src/storage.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
use std::collections::HashMap;

use async_trait::async_trait;
use dojo_client::storage::{get_component_storage_base_address, EntityStorage};
use starknet::core::types::FieldElement;

/// Simple in memory implementation of [EntityStorage]
pub struct InMemoryStorage {
/// storage key -> Component value
pub inner: HashMap<FieldElement, FieldElement>,
}

impl InMemoryStorage {
pub fn new() -> Self {
Self { inner: HashMap::new() }
}
}

// Example implementation of [EntityStorage]
#[async_trait]
impl EntityStorage for InMemoryStorage {
async fn set(
&mut self,
component: FieldElement,
keys: Vec<FieldElement>,
values: Vec<FieldElement>,
) {
let base_address = get_component_storage_base_address(component, &keys);
for (offset, value) in values.into_iter().enumerate() {
self.inner.insert(base_address + offset.into(), value);
}
}

async fn get(
&self,
component: FieldElement,
keys: Vec<FieldElement>,
length: usize,
) -> Vec<FieldElement> {
let base_address = get_component_storage_base_address(component, &keys);
let mut values = Vec::with_capacity(length);
for i in 0..length {
let address = base_address + i.into();
let value = self.inner.get(&address).cloned();
values.push(value.unwrap_or(FieldElement::ZERO));
}
values
}
}
8 changes: 4 additions & 4 deletions examples/ecs/src/systems.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ mod spawn {
use dojo_examples::components::Moves;

fn execute(ctx: Context) {
let position = get !(ctx.world, ctx.origin, (Position));

set !(
ctx.world,
(
Moves {
player: ctx.origin, remaining: 10
}, Position {
player: ctx.origin, x: 0, y: 0
Position {
player: ctx.origin, x: position.x + 10, y: position.y + 10
},
)
);
Expand Down

0 comments on commit 8548b6f

Please sign in to comment.