-
Notifications
You must be signed in to change notification settings - Fork 179
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
fix: fix sozo issues with migration on sepolia #2398
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,3 +20,4 @@ bindings | |
justfile | ||
spawn-and-move-db | ||
types-test-db | ||
examples/spawn-and-move/manifests/saya/** |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
scarb 2.7.0 | ||
starknet-foundry 0.30.0 |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,13 +2,15 @@ use std::str::FromStr; | |
|
||
use anyhow::{anyhow, Result}; | ||
use clap::Args; | ||
use dojo_utils::env::{ | ||
DOJO_KEYSTORE_PASSWORD_ENV_VAR, DOJO_KEYSTORE_PATH_ENV_VAR, DOJO_PRIVATE_KEY_ENV_VAR, | ||
}; | ||
use dojo_utils::keystore::prompt_password_if_needed; | ||
use dojo_world::config::Environment; | ||
use starknet::core::types::Felt; | ||
use starknet::signers::{LocalWallet, SigningKey}; | ||
use tracing::trace; | ||
|
||
use super::{DOJO_KEYSTORE_PASSWORD_ENV_VAR, DOJO_KEYSTORE_PATH_ENV_VAR, DOJO_PRIVATE_KEY_ENV_VAR}; | ||
|
||
#[derive(Debug, Args, Clone)] | ||
#[command(next_help_heading = "Signer options")] | ||
// INVARIANT: | ||
|
@@ -42,35 +44,73 @@ pub struct SignerOptions { | |
} | ||
|
||
impl SignerOptions { | ||
/// Retrieves the signer from the CLI or environment metadata. | ||
/// First, attempt to locate the signer from CLI arguments or environment variables via CLAP. | ||
/// If unsuccessful, then search for the signer within the Dojo environment metadata. | ||
/// If the signer is not found in any of the above locations, return an error. | ||
pub fn signer(&self, env_metadata: Option<&Environment>, no_wait: bool) -> Result<LocalWallet> { | ||
if let Some(private_key) = self.private_key(env_metadata) { | ||
trace!(private_key, "Signing using private key."); | ||
return Ok(LocalWallet::from_signing_key(SigningKey::from_secret_scalar( | ||
Felt::from_str(&private_key)?, | ||
))); | ||
let pk_cli = self.private_key.clone(); | ||
let pk_env = env_metadata.and_then(|env| env.private_key().map(|s| s.to_string())); | ||
|
||
let pk_keystore_cli = self.private_key_from_keystore_cli(no_wait)?; | ||
let pk_keystore_env = self.private_key_from_keystore_env(env_metadata, no_wait)?; | ||
|
||
let private_key = if let Some(private_key) = pk_cli { | ||
trace!("Signing using private key from CLI."); | ||
SigningKey::from_secret_scalar(Felt::from_str(&private_key)?) | ||
} else if let Some(private_key) = pk_keystore_cli { | ||
trace!("Signing using private key from CLI keystore."); | ||
private_key | ||
} else if let Some(private_key) = pk_env { | ||
trace!("Signing using private key from env metadata."); | ||
SigningKey::from_secret_scalar(Felt::from_str(&private_key)?) | ||
} else if let Some(private_key) = pk_keystore_env { | ||
trace!("Signing using private key from env metadata keystore."); | ||
private_key | ||
} else { | ||
return Err(anyhow!( | ||
"Could not find private key. Please specify the private key or path to the \ | ||
keystore file." | ||
)); | ||
}; | ||
|
||
Ok(LocalWallet::from_signing_key(private_key)) | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Refactor suggestion: Improve clarity and modularity in The |
||
|
||
/// Retrieves the private key from the CLI keystore. | ||
/// If the keystore path is not set, it returns `None`. | ||
pub fn private_key_from_keystore_cli(&self, no_wait: bool) -> Result<Option<SigningKey>> { | ||
if let Some(path) = &self.keystore_path { | ||
let password = prompt_password_if_needed(self.keystore_password.as_deref(), no_wait)?; | ||
|
||
let private_key = SigningKey::from_keystore(path, &password)?; | ||
return Ok(Some(private_key)); | ||
} | ||
|
||
if let Some(path) = self.keystore_path(env_metadata) { | ||
let password = { | ||
if let Some(password) = self.keystore_password(env_metadata) { | ||
password.to_owned() | ||
} else if no_wait { | ||
return Err(anyhow!("Could not find password. Please specify the password.")); | ||
} else { | ||
trace!("Prompting user for keystore password."); | ||
rpassword::prompt_password("Enter password: ")? | ||
} | ||
}; | ||
Ok(None) | ||
} | ||
|
||
/// Retrieves the private key from the keystore in the environment metadata. | ||
/// If the keystore path is not set, it returns `None`. | ||
pub fn private_key_from_keystore_env( | ||
&self, | ||
env_metadata: Option<&Environment>, | ||
no_wait: bool, | ||
) -> Result<Option<SigningKey>> { | ||
if let Some(path) = env_metadata.and_then(|env| env.keystore_path()) { | ||
let password = prompt_password_if_needed( | ||
env_metadata.and_then(|env| env.keystore_password()), | ||
no_wait, | ||
)?; | ||
|
||
let private_key = SigningKey::from_keystore(path, &password)?; | ||
return Ok(LocalWallet::from_signing_key(private_key)); | ||
return Ok(Some(private_key)); | ||
} | ||
|
||
Err(anyhow!( | ||
"Could not find private key. Please specify the private key or path to the keystore \ | ||
file." | ||
)) | ||
Ok(None) | ||
} | ||
|
||
/// Retrieves the private key from the CLI or environment metadata. | ||
pub fn private_key(&self, env_metadata: Option<&Environment>) -> Option<String> { | ||
if let Some(s) = &self.private_key { | ||
Some(s.to_owned()) | ||
|
@@ -79,21 +119,14 @@ impl SignerOptions { | |
} | ||
} | ||
|
||
/// Retrieves the keystore path from the CLI or environment metadata. | ||
pub fn keystore_path(&self, env_metadata: Option<&Environment>) -> Option<String> { | ||
if let Some(s) = &self.keystore_path { | ||
Some(s.to_owned()) | ||
} else { | ||
env_metadata.and_then(|env| env.keystore_path().map(|s| s.to_string())) | ||
} | ||
} | ||
|
||
pub fn keystore_password(&self, env_metadata: Option<&Environment>) -> Option<String> { | ||
if let Some(s) = &self.keystore_password { | ||
Some(s.to_owned()) | ||
} else { | ||
env_metadata.and_then(|env| env.keystore_password().map(|s| s.to_string())) | ||
} | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
pub const STARKNET_RPC_URL_ENV_VAR: &str = "STARKNET_RPC_URL"; | ||
pub const DOJO_PRIVATE_KEY_ENV_VAR: &str = "DOJO_PRIVATE_KEY"; | ||
pub const DOJO_KEYSTORE_PATH_ENV_VAR: &str = "DOJO_KEYSTORE_PATH"; | ||
pub const DOJO_KEYSTORE_PASSWORD_ENV_VAR: &str = "DOJO_KEYSTORE_PASSWORD"; | ||
pub const DOJO_ACCOUNT_ADDRESS_ENV_VAR: &str = "DOJO_ACCOUNT_ADDRESS"; | ||
pub const DOJO_WORLD_ADDRESS_ENV_VAR: &str = "DOJO_WORLD_ADDRESS"; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
use anyhow::{anyhow, Result}; | ||
|
||
/// Prompts the user for a password if no password is provided and `no_wait` is not set. | ||
/// The `no_wait` is used for non-interactive commands. | ||
pub fn prompt_password_if_needed(maybe_password: Option<&str>, no_wait: bool) -> Result<String> { | ||
if let Some(password) = maybe_password { | ||
Ok(password.to_owned()) | ||
} else if no_wait { | ||
Err(anyhow!("Could not find password. Please specify the password.")) | ||
} else { | ||
Ok(rpassword::prompt_password("Enter password: ")?.to_owned()) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Refactor suggestion: Consider modularizing keystore handling.
The import of
prompt_password_if_needed
directly in the global scope suggests that password prompting and keystore handling are significant aspects of this module. Consider encapsulating these functionalities into a separate module or class to improve modularity and maintainability.