Skip to content

Commit

Permalink
Merge remote-tracking branch 'dojo/main' into torii-cleanups
Browse files Browse the repository at this point in the history
  • Loading branch information
glihm committed Nov 19, 2024
2 parents ba3b35e + 0342464 commit 231b273
Show file tree
Hide file tree
Showing 15 changed files with 362 additions and 17 deletions.
1 change: 1 addition & 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 bin/torii/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ base64.workspace = true
camino.workspace = true
chrono.workspace = true
clap.workspace = true
clap_complete.workspace = true
ctrlc = { version = "3.4", features = [ "termination" ] }
dojo-metrics.workspace = true
dojo-types.workspace = true
Expand Down
14 changes: 14 additions & 0 deletions bin/torii/src/cli.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//! CLI for Torii.
//!
//! Use a `Cli` struct to parse the CLI arguments
//! and to have flexibility in the future to add more commands
//! that may not start Torii directly.
use clap::Parser;
use torii_cli::ToriiArgs;

#[derive(Parser)]
#[command(name = "torii", author, version, about, long_about = None)]
pub struct Cli {
#[command(flatten)]
pub args: ToriiArgs,
}
7 changes: 4 additions & 3 deletions bin/torii/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use std::time::Duration;

use camino::Utf8PathBuf;
use clap::Parser;
use cli::Cli;
use dojo_metrics::exporters::prometheus::PrometheusRecorder;
use dojo_world::contracts::world::WorldContractReader;
use sqlx::sqlite::{
Expand All @@ -30,7 +31,6 @@ use tempfile::{NamedTempFile, TempDir};
use tokio::sync::broadcast;
use tokio::sync::broadcast::Sender;
use tokio_stream::StreamExt;
use torii_cli::ToriiArgs;
use torii_core::engine::{Engine, EngineConfig, IndexingFlags, Processors};
use torii_core::executor::Executor;
use torii_core::processors::store_transaction::StoreTransactionProcessor;
Expand All @@ -46,17 +46,18 @@ use url::{form_urlencoded, Url};

pub(crate) const LOG_TARGET: &str = "torii::cli";

mod cli;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
let mut args = ToriiArgs::parse().with_config_file()?;
let mut args = Cli::parse().args.with_config_file()?;

let world_address = if let Some(world_address) = args.world_address {
world_address
} else {
return Err(anyhow::anyhow!("Please specify a world address."));
};

// let mut contracts = parse_erc_contracts(&args.contracts)?;
args.indexing.contracts.push(Contract { address: world_address, r#type: ContractType::WORLD });

let filter_layer = EnvFilter::try_from_default_env()
Expand Down
2 changes: 2 additions & 0 deletions crates/katana/cli/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ pub struct MetricsOptions {
pub metrics_port: u16,
}

#[cfg(feature = "server")]
impl Default for MetricsOptions {
fn default() -> Self {
MetricsOptions {
Expand Down Expand Up @@ -366,6 +367,7 @@ fn default_max_connections() -> u32 {
DEFAULT_RPC_MAX_CONNECTIONS
}

#[cfg(feature = "server")]
fn default_page_size() -> u64 {
DEFAULT_RPC_MAX_EVENT_PAGE_SIZE
}
Expand Down
4 changes: 2 additions & 2 deletions crates/katana/monitoring/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ services:
command: >
katana
--db-dir .katana/data-dir
--metrics 0.0.0.0:9001
--host 0.0.0.0 --port 5050
--http.addr 0.0.0.0 --http.port 5050
--metrics --metrics.addr 0.0.0.0 --metrics.port 9001
prometheus:
restart: unless-stopped
Expand Down
2 changes: 1 addition & 1 deletion crates/torii/cli/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub const DEFAULT_RPC_URL: &str = "http://0.0.0.0:5050";

/// Dojo World Indexer
#[derive(Parser, Debug, Clone, serde::Serialize, serde::Deserialize)]
#[command(name = "torii", author, version, about, long_about = None)]
#[command(name = "torii", author, about, long_about = None)]
#[command(next_help_heading = "Torii general options")]
pub struct ToriiArgs {
/// The world to index
Expand Down
15 changes: 15 additions & 0 deletions crates/torii/cli/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::str::FromStr;

use anyhow::Context;
use clap::ArgAction;
use serde::ser::SerializeSeq;
use serde::{Deserialize, Serialize};
use starknet::core::types::Felt;
use torii_core::types::{Contract, ContractType};
Expand Down Expand Up @@ -141,6 +142,7 @@ pub struct IndexingOptions {
help = "ERC contract addresses to index. You may only specify ERC20 or ERC721 contracts."
)]
#[serde(deserialize_with = "deserialize_contracts")]
#[serde(serialize_with = "serialize_contracts")]
#[serde(default)]
pub contracts: Vec<Contract>,

Expand Down Expand Up @@ -327,6 +329,19 @@ where
contracts.iter().map(|s| parse_erc_contract(s).map_err(serde::de::Error::custom)).collect()
}

fn serialize_contracts<S>(contracts: &Vec<Contract>, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let mut seq = serializer.serialize_seq(Some(contracts.len()))?;

for contract in contracts {
seq.serialize_element(&contract.to_string())?;
}

seq.end()
}

// ** Default functions to setup serde of the configuration file **
fn default_http_addr() -> IpAddr {
DEFAULT_HTTP_ADDR
Expand Down
27 changes: 25 additions & 2 deletions crates/torii/client/src/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@ use starknet::providers::jsonrpc::HttpTransport;
use starknet::providers::JsonRpcClient;
use tokio::sync::RwLock as AsyncRwLock;
use torii_grpc::client::{EntityUpdateStreaming, EventUpdateStreaming, IndexerUpdateStreaming};
use torii_grpc::proto::world::{RetrieveEntitiesResponse, RetrieveEventsResponse};
use torii_grpc::proto::world::{
RetrieveEntitiesResponse, RetrieveEventsResponse, RetrieveTokenBalancesResponse,
RetrieveTokensResponse,
};
use torii_grpc::types::schema::Entity;
use torii_grpc::types::{EntityKeysClause, Event, EventQuery, Query};
use torii_grpc::types::{EntityKeysClause, Event, EventQuery, Query, Token, TokenBalance};
use torii_relay::client::EventLoop;
use torii_relay::types::Message;

Expand Down Expand Up @@ -85,6 +88,26 @@ impl Client {
self.metadata.read()
}

/// Retrieves tokens matching contract addresses.
pub async fn tokens(&self, contract_addresses: Vec<Felt>) -> Result<Vec<Token>, Error> {
let mut grpc_client = self.inner.write().await;
let RetrieveTokensResponse { tokens } =
grpc_client.retrieve_tokens(contract_addresses).await?;
Ok(tokens.into_iter().map(TryInto::try_into).collect::<Result<Vec<Token>, _>>()?)
}

/// Retrieves token balances for account addresses and contract addresses.
pub async fn token_balances(
&self,
account_addresses: Vec<Felt>,
contract_addresses: Vec<Felt>,
) -> Result<Vec<TokenBalance>, Error> {
let mut grpc_client = self.inner.write().await;
let RetrieveTokenBalancesResponse { balances } =
grpc_client.retrieve_token_balances(account_addresses, contract_addresses).await?;
Ok(balances.into_iter().map(TryInto::try_into).collect::<Result<Vec<TokenBalance>, _>>()?)
}

/// Retrieves entities matching query parameter.
///
/// The query param includes an optional clause for filtering. Without clause, it fetches ALL
Expand Down
28 changes: 28 additions & 0 deletions crates/torii/core/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,28 @@ pub struct Event {
pub executed_at: DateTime<Utc>,
pub created_at: DateTime<Utc>,
}

#[derive(FromRow, Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct Token {
pub id: String,
pub contract_address: String,
pub name: String,
pub symbol: String,
pub decimals: u8,
pub metadata: String,
}

#[derive(FromRow, Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct TokenBalance {
pub id: String,
pub balance: String,
pub account_address: String,
pub contract_address: String,
pub token_id: String,
}

#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq)]
pub struct Contract {
pub address: Felt,
Expand All @@ -134,6 +156,12 @@ pub enum ContractType {
ERC721,
}

impl std::fmt::Display for Contract {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}:{:#x}", self.r#type, self.address)
}
}

impl FromStr for ContractType {
type Err = anyhow::Error;

Expand Down
15 changes: 15 additions & 0 deletions crates/torii/grpc/proto/types.proto
Original file line number Diff line number Diff line change
Expand Up @@ -149,4 +149,19 @@ enum ComparisonOperator {
GTE = 3;
LT = 4;
LTE = 5;
}

message Token {
string contract_address = 2;
string name = 3;
string symbol = 4;
uint32 decimals = 5;
string metadata = 6;
}

message TokenBalance {
string balance = 1;
string account_address = 2;
string contract_address = 3;
string token_id = 4;
}
30 changes: 30 additions & 0 deletions crates/torii/grpc/proto/world.proto
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,36 @@ service World {

// Subscribe to events
rpc SubscribeEvents (SubscribeEventsRequest) returns (stream SubscribeEventsResponse);

// Retrieve tokens
rpc RetrieveTokens (RetrieveTokensRequest) returns (RetrieveTokensResponse);

// Retrieve token balances
rpc RetrieveTokenBalances (RetrieveTokenBalancesRequest) returns (RetrieveTokenBalancesResponse);
}

// A request to retrieve tokens
message RetrieveTokensRequest {
// The list of contract addresses to retrieve tokens for
repeated bytes contract_addresses = 1;
}

// A response containing tokens
message RetrieveTokensResponse {
repeated types.Token tokens = 1;
}

// A request to retrieve token balances
message RetrieveTokenBalancesRequest {
// The account addresses to retrieve balances for
repeated bytes account_addresses = 1;
// The list of token contract addresses to retrieve balances for
repeated bytes contract_addresses = 2;
}

// A response containing token balances
message RetrieveTokenBalancesResponse {
repeated types.TokenBalance balances = 1;
}

// A request to subscribe to indexer updates.
Expand Down
49 changes: 44 additions & 5 deletions crates/torii/grpc/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@ use tonic::transport::Endpoint;

use crate::proto::world::{
world_client, RetrieveEntitiesRequest, RetrieveEntitiesResponse, RetrieveEventMessagesRequest,
RetrieveEventsRequest, RetrieveEventsResponse, SubscribeEntitiesRequest,
SubscribeEntityResponse, SubscribeEventMessagesRequest, SubscribeEventsRequest,
SubscribeEventsResponse, SubscribeIndexerRequest, SubscribeIndexerResponse,
SubscribeModelsRequest, SubscribeModelsResponse, UpdateEntitiesSubscriptionRequest,
UpdateEventMessagesSubscriptionRequest, WorldMetadataRequest,
RetrieveEventsRequest, RetrieveEventsResponse, RetrieveTokenBalancesRequest,
RetrieveTokenBalancesResponse, RetrieveTokensRequest, RetrieveTokensResponse,
SubscribeEntitiesRequest, SubscribeEntityResponse, SubscribeEventMessagesRequest,
SubscribeEventsRequest, SubscribeEventsResponse, SubscribeIndexerRequest,
SubscribeIndexerResponse, SubscribeModelsRequest, SubscribeModelsResponse,
UpdateEntitiesSubscriptionRequest, UpdateEventMessagesSubscriptionRequest,
WorldMetadataRequest,
};
use crate::types::schema::{Entity, SchemaError};
use crate::types::{EntityKeysClause, Event, EventQuery, IndexerUpdate, ModelKeysClause, Query};
Expand Down Expand Up @@ -90,6 +92,43 @@ impl WorldClient {
.and_then(|metadata| metadata.try_into().map_err(Error::ParseStr))
}

pub async fn retrieve_tokens(
&mut self,
contract_addresses: Vec<Felt>,
) -> Result<RetrieveTokensResponse, Error> {
self.inner
.retrieve_tokens(RetrieveTokensRequest {
contract_addresses: contract_addresses
.into_iter()
.map(|c| c.to_bytes_be().to_vec())
.collect(),
})
.await
.map_err(Error::Grpc)
.map(|res| res.into_inner())
}

pub async fn retrieve_token_balances(
&mut self,
account_addresses: Vec<Felt>,
contract_addresses: Vec<Felt>,
) -> Result<RetrieveTokenBalancesResponse, Error> {
self.inner
.retrieve_token_balances(RetrieveTokenBalancesRequest {
account_addresses: account_addresses
.into_iter()
.map(|a| a.to_bytes_be().to_vec())
.collect(),
contract_addresses: contract_addresses
.into_iter()
.map(|c| c.to_bytes_be().to_vec())
.collect(),
})
.await
.map_err(Error::Grpc)
.map(|res| res.into_inner())
}

pub async fn retrieve_entities(
&mut self,
query: Query,
Expand Down
Loading

0 comments on commit 231b273

Please sign in to comment.