Skip to content

Commit

Permalink
refactor: make DojoMetadata to handle metadata specific to dojo eas…
Browse files Browse the repository at this point in the history
  • Loading branch information
lambda-0x authored Aug 5, 2023
1 parent 7893eed commit a2ccbde
Show file tree
Hide file tree
Showing 18 changed files with 169 additions and 104 deletions.
8 changes: 2 additions & 6 deletions crates/sozo/src/commands/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,9 @@ impl AuthArgs {
pub fn run(self, config: &Config) -> Result<()> {
let env_metadata = if config.manifest_path().exists() {
let ws = scarb::ops::read_workspace(config.manifest_path(), config)?;
let env_metadata = dojo_metadata_from_workspace(&ws)
.and_then(|dojo_metadata| dojo_metadata.get("env").cloned());

env_metadata
.as_ref()
.and_then(|env_metadata| env_metadata.get(ws.config().profile().as_str()).cloned())
.or(env_metadata)
// TODO: Check the updated scarb way to read profile specific values
dojo_metadata_from_workspace(&ws).and_then(|inner| inner.env().cloned())
} else {
None
};
Expand Down
8 changes: 2 additions & 6 deletions crates/sozo/src/commands/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,9 @@ impl ComponentArgs {
pub fn run(self, config: &Config) -> Result<()> {
let env_metadata = if config.manifest_path().exists() {
let ws = scarb::ops::read_workspace(config.manifest_path(), config)?;
let env_metadata = dojo_metadata_from_workspace(&ws)
.and_then(|dojo_metadata| dojo_metadata.get("env").cloned());

env_metadata
.as_ref()
.and_then(|env_metadata| env_metadata.get(ws.config().profile().as_str()).cloned())
.or(env_metadata)
// TODO: Check the updated scarb way to read profile specific values
dojo_metadata_from_workspace(&ws).and_then(|inner| inner.env().cloned())
} else {
None
};
Expand Down
8 changes: 2 additions & 6 deletions crates/sozo/src/commands/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,9 @@ impl EventsArgs {
pub fn run(self, config: &Config) -> Result<()> {
let env_metadata = if config.manifest_path().exists() {
let ws = scarb::ops::read_workspace(config.manifest_path(), config)?;
let env_metadata = dojo_metadata_from_workspace(&ws)
.and_then(|dojo_metadata| dojo_metadata.get("env").cloned());

env_metadata
.as_ref()
.and_then(|env_metadata| env_metadata.get(ws.config().profile().as_str()).cloned())
.or(env_metadata)
// TODO: Check the updated scarb way to read profile specific values
dojo_metadata_from_workspace(&ws).and_then(|inner| inner.env().cloned())
} else {
None
};
Expand Down
8 changes: 2 additions & 6 deletions crates/sozo/src/commands/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,9 @@ impl ExecuteArgs {
pub fn run(self, config: &Config) -> Result<()> {
let env_metadata = if config.manifest_path().exists() {
let ws = scarb::ops::read_workspace(config.manifest_path(), config)?;
let env_metadata = dojo_metadata_from_workspace(&ws)
.and_then(|dojo_metadata| dojo_metadata.get("env").cloned());

env_metadata
.as_ref()
.and_then(|env_metadata| env_metadata.get(ws.config().profile().as_str()).cloned())
.or(env_metadata)
// TODO: Check the updated scarb way to read profile specific values
dojo_metadata_from_workspace(&ws).and_then(|inner| inner.env().cloned())
} else {
None
};
Expand Down
11 changes: 2 additions & 9 deletions crates/sozo/src/commands/migrate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,8 @@ impl MigrateArgs {
scarb::ops::compile(packages, &ws)?;
}

let mut env_metadata = dojo_metadata_from_workspace(&ws)
.and_then(|dojo_metadata| dojo_metadata.get("env").cloned());

// If there is an environment-specific metadata, use that, otherwise use the
// workspace's default environment metadata.
env_metadata = env_metadata
.as_ref()
.and_then(|env_metadata| env_metadata.get(ws.config().profile().as_str()).cloned())
.or(env_metadata);
let env_metadata = dojo_metadata_from_workspace(&ws).and_then(|inner| inner.env().cloned());
// TODO: Check the updated scarb way to read profile specific values

ws.config().tokio_handle().block_on(migration::execute(
self,
Expand Down
29 changes: 12 additions & 17 deletions crates/sozo/src/commands/options/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ use starknet::accounts::SingleOwnerAccount;
use starknet::core::types::FieldElement;
use starknet::providers::Provider;
use starknet::signers::{LocalWallet, SigningKey};
use toml::Value;

use super::Environment;

#[derive(Debug, Args)]
#[command(next_help_heading = "Account options")]
Expand Down Expand Up @@ -39,7 +40,7 @@ impl AccountOptions {
pub async fn account<P>(
&self,
provider: P,
env_metadata: Option<&Value>,
env_metadata: Option<&Environment>,
) -> Result<SingleOwnerAccount<P, LocalWallet>>
where
P: Provider + Send + Sync + 'static,
Expand All @@ -53,13 +54,11 @@ impl AccountOptions {
Ok(SingleOwnerAccount::new(provider, signer, account_address, chain_id))
}

fn signer(&self, env_metadata: Option<&Value>) -> Result<LocalWallet> {
fn signer(&self, env_metadata: Option<&Environment>) -> Result<LocalWallet> {
if let Some(private_key) = self
.private_key
.as_deref()
.or_else(|| {
env_metadata.and_then(|env| env.get("private_key").and_then(|v| v.as_str()))
})
.or_else(|| env_metadata.and_then(|env| env.private_key()))
.or(std::env::var("DOJO_PRIVATE_KEY").ok().as_deref())
{
return Ok(LocalWallet::from_signing_key(SigningKey::from_secret_scalar(
Expand All @@ -71,10 +70,7 @@ impl AccountOptions {
if let Some(password) = self
.keystore_password
.as_deref()
.or_else(|| {
env_metadata
.and_then(|env| env.get("keystore_password").and_then(|v| v.as_str()))
})
.or_else(|| env_metadata.and_then(|env| env.keystore_password()))
.or(std::env::var("DOJO_KEYSTORE_PASSWORD").ok().as_deref())
{
return Ok(LocalWallet::from_signing_key(SigningKey::from_keystore(
Expand All @@ -91,15 +87,14 @@ impl AccountOptions {
))
}

fn account_address(&self, env_metadata: Option<&Value>) -> Result<FieldElement> {
fn account_address(&self, env_metadata: Option<&Environment>) -> Result<FieldElement> {
if let Some(address) = self.account_address {
Ok(address)
} else if let Some(address) = env_metadata.and_then(|env| {
env.get("account_address")
.and_then(|v| v.as_str().map(|s| s.to_string()))
.or(std::env::var("DOJO_ACCOUNT_ADDRESS").ok())
}) {
Ok(FieldElement::from_str(&address)?)
} else if let Some(address) = env_metadata
.and_then(|env| env.account_address())
.or(std::env::var("DOJO_ACCOUNT_ADDRESS").ok().as_deref())
{
Ok(FieldElement::from_str(address)?)
} else {
Err(anyhow!(
"Could not find account address. Please specify it with --account-address or in \
Expand Down
109 changes: 105 additions & 4 deletions crates/sozo/src/commands/options/mod.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,111 @@
use scarb::core::Workspace;
use toml::Value;
use scarb::core::{ManifestMetadata, Workspace};
use serde::Deserialize;

pub mod account;
pub mod starknet;
pub mod world;

pub(super) fn dojo_metadata_from_workspace(ws: &Workspace<'_>) -> Option<Value> {
ws.current_package().ok()?.manifest.metadata.tool_metadata.as_ref()?.get("dojo").cloned()
pub(crate) fn dojo_metadata_from_workspace(ws: &Workspace<'_>) -> Option<DojoMetadata> {
Some(ws.current_package().ok()?.manifest.metadata.dojo())
}

#[derive(Default, Deserialize, Debug, Clone)]
pub(crate) struct DojoMetadata {
env: Option<Environment>,
}

#[derive(Default, Deserialize, Clone, Debug)]
pub struct Environment {
rpc_url: Option<String>,
account_address: Option<String>,
private_key: Option<String>,
keystore_path: Option<String>,
keystore_password: Option<String>,
world_address: Option<String>,
}

impl Environment {
pub fn world_address(&self) -> Option<&str> {
self.world_address.as_deref()
}

pub fn rpc_url(&self) -> Option<&str> {
self.rpc_url.as_deref()
}

pub fn account_address(&self) -> Option<&str> {
self.account_address.as_deref()
}

pub fn private_key(&self) -> Option<&str> {
self.private_key.as_deref()
}

#[allow(dead_code)]
pub fn keystore_path(&self) -> Option<&str> {
self.keystore_path.as_deref()
}

pub fn keystore_password(&self) -> Option<&str> {
self.keystore_password.as_deref()
}
}

impl DojoMetadata {
pub fn env(&self) -> Option<&Environment> {
self.env.as_ref()
}
}
trait MetadataExt {
fn dojo(&self) -> DojoMetadata;
}

impl MetadataExt for ManifestMetadata {
fn dojo(&self) -> DojoMetadata {
self.tool_metadata
.as_ref()
.and_then(|e| e.get("dojo"))
.cloned()
.map(|v| v.try_into::<DojoMetadata>().unwrap_or_default())
.unwrap_or_default()
}
}

#[cfg(test)]
mod test {
use super::*;
#[test]
fn check_deserialization() {
let metadata: DojoMetadata = toml::from_str(
r#"
[env]
rpc_url = "http://localhost:5050/"
account_address = "0x03ee9e18edc71a6df30ac3aca2e0b02a198fbce19b7480a63a0d71cbd76652e0"
private_key = "0x0300001800000000300000180000000000030000000000003006001800006600"
keystore_path = "test/"
keystore_password = "dojo"
world_address = "0x0248cacaeac64c45be0c19ee8727e0bb86623ca7fa3f0d431a6c55e200697e5a"
"#,
)
.unwrap();

assert!(metadata.env.is_some());
let env = metadata.env.unwrap();

assert_eq!(env.rpc_url(), Some("http://localhost:5050/"));
assert_eq!(
env.account_address(),
Some("0x03ee9e18edc71a6df30ac3aca2e0b02a198fbce19b7480a63a0d71cbd76652e0")
);
assert_eq!(
env.private_key(),
Some("0x0300001800000000300000180000000000030000000000003006001800006600")
);
assert_eq!(env.keystore_path(), Some("test/"));
assert_eq!(env.keystore_password(), Some("dojo"));
assert_eq!(
env.world_address(),
Some("0x0248cacaeac64c45be0c19ee8727e0bb86623ca7fa3f0d431a6c55e200697e5a")
);
}
}
17 changes: 11 additions & 6 deletions crates/sozo/src/commands/options/starknet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ use anyhow::{anyhow, Result};
use clap::Args;
use starknet::providers::jsonrpc::HttpTransport;
use starknet::providers::JsonRpcClient;
use toml::Value;
use url::Url;

use super::Environment;

#[derive(Debug, Args)]
#[command(next_help_heading = "Starknet options")]
pub struct StarknetOptions {
Expand All @@ -15,14 +16,18 @@ pub struct StarknetOptions {
}

impl StarknetOptions {
pub fn provider(&self, env_metadata: Option<&Value>) -> Result<JsonRpcClient<HttpTransport>> {
pub fn provider(
&self,
env_metadata: Option<&Environment>,
) -> Result<JsonRpcClient<HttpTransport>> {
let url = if let Some(url) = self.rpc_url.clone() {
Some(url)
} else if let Some(url) = env_metadata
.and_then(|env| env.get("rpc_url").and_then(|v| v.as_str().map(|s| s.to_string())))
.or(std::env::var("STARKNET_RPC_URL").ok())
} else if let Some(url) =
env_metadata
.and_then(|env| env.rpc_url())
.or(std::env::var("STARKNET_RPC_URL").ok().as_deref())
{
Some(Url::parse(&url)?)
Some(Url::parse(url)?)
} else {
None
};
Expand Down
16 changes: 8 additions & 8 deletions crates/sozo/src/commands/options/world.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ use std::str::FromStr;
use anyhow::{anyhow, Result};
use clap::Args;
use starknet::core::types::FieldElement;
use toml::Value;

use super::Environment;

#[derive(Debug, Args)]
#[command(next_help_heading = "World options")]
Expand All @@ -14,15 +15,14 @@ pub struct WorldOptions {
}

impl WorldOptions {
pub fn address(&self, env_metadata: Option<&Value>) -> Result<FieldElement> {
pub fn address(&self, env_metadata: Option<&Environment>) -> Result<FieldElement> {
if let Some(world_address) = self.world_address {
Ok(world_address)
} else if let Some(world_address) = env_metadata.and_then(|env| {
env.get("world_address")
.and_then(|v| v.as_str().map(|s| s.to_string()))
.or(std::env::var("DOJO_WORLD_ADDRESS").ok())
}) {
Ok(FieldElement::from_str(&world_address)?)
} else if let Some(world_address) = env_metadata
.and_then(|env| env.world_address())
.or(std::env::var("DOJO_WORLD_ADDRESS").ok().as_deref())
{
Ok(FieldElement::from_str(world_address)?)
} else {
Err(anyhow!(
"Could not find World address. Please specify it with --world or in the world \
Expand Down
8 changes: 2 additions & 6 deletions crates/sozo/src/commands/register.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,9 @@ impl RegisterArgs {
pub fn run(self, config: &Config) -> Result<()> {
let env_metadata = if config.manifest_path().exists() {
let ws = scarb::ops::read_workspace(config.manifest_path(), config)?;
let env_metadata = dojo_metadata_from_workspace(&ws)
.and_then(|dojo_metadata| dojo_metadata.get("env").cloned());

env_metadata
.as_ref()
.and_then(|env_metadata| env_metadata.get(ws.config().profile().as_str()).cloned())
.or(env_metadata)
// TODO: Check the updated scarb way to read profile specific values
dojo_metadata_from_workspace(&ws).and_then(|inner| inner.env().cloned())
} else {
None
};
Expand Down
8 changes: 2 additions & 6 deletions crates/sozo/src/commands/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,9 @@ impl SystemArgs {
pub fn run(self, config: &Config) -> Result<()> {
let env_metadata = if config.manifest_path().exists() {
let ws = scarb::ops::read_workspace(config.manifest_path(), config)?;
let env_metadata = dojo_metadata_from_workspace(&ws)
.and_then(|dojo_metadata| dojo_metadata.get("env").cloned());

env_metadata
.as_ref()
.and_then(|env_metadata| env_metadata.get(ws.config().profile().as_str()).cloned())
.or(env_metadata)
// TODO: Check the updated scarb way to read profile specific values
dojo_metadata_from_workspace(&ws).and_then(|inner| inner.env().cloned())
} else {
None
};
Expand Down
5 changes: 2 additions & 3 deletions crates/sozo/src/ops/auth.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
use anyhow::{Context, Result};
use dojo_client::contract::world::WorldContract;
use toml::Value;

use crate::commands::auth::AuthCommand;
use crate::commands::{auth::AuthCommand, options::Environment};

pub async fn execute(command: AuthCommand, env_metadata: Option<Value>) -> Result<()> {
pub async fn execute(command: AuthCommand, env_metadata: Option<Environment>) -> Result<()> {
match command {
AuthCommand::Writer { component, system, world, starknet, account } => {
let world_address = world.address(env_metadata.as_ref())?;
Expand Down
5 changes: 2 additions & 3 deletions crates/sozo/src/ops/component.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
use anyhow::Result;
use dojo_client::contract::world::WorldContractReader;
use starknet::core::types::{BlockId, BlockTag};
use toml::Value;

use crate::commands::component::ComponentCommands;
use crate::commands::{component::ComponentCommands, options::Environment};

pub async fn execute(command: ComponentCommands, env_metadata: Option<Value>) -> Result<()> {
pub async fn execute(command: ComponentCommands, env_metadata: Option<Environment>) -> Result<()> {
match command {
ComponentCommands::Get { name, world, starknet } => {
let world_address = world.address(env_metadata.as_ref())?;
Expand Down
Loading

0 comments on commit a2ccbde

Please sign in to comment.