Skip to content
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

feat: add dapp-portal support to zk_inception #2659

Merged
merged 10 commits into from
Aug 20, 2024
1 change: 1 addition & 0 deletions zk_toolbox/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 zk_toolbox/crates/common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ serde_yaml.workspace = true
sqlx.workspace = true
tokio.workspace = true
toml.workspace = true
types.workspace = true
url.workspace = true
xshell.workspace = true
thiserror.workspace = true
Expand Down
15 changes: 15 additions & 0 deletions zk_toolbox/crates/common/src/docker.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::collections::HashMap;

use xshell::{cmd, Shell};

use crate::cmd::Cmd;
Expand All @@ -9,3 +11,16 @@ pub fn up(shell: &Shell, docker_compose_file: &str) -> anyhow::Result<()> {
pub fn down(shell: &Shell, docker_compose_file: &str) -> anyhow::Result<()> {
Ok(Cmd::new(cmd!(shell, "docker compose -f {docker_compose_file} down")).run()?)
}

pub fn run(
shell: &Shell,
docker_image: &str,
docker_args: HashMap<String, String>,
) -> anyhow::Result<()> {
let mut args = vec![];
for (key, value) in docker_args.iter() {
args.push(key);
args.push(value);
}
Ok(Cmd::new(cmd!(shell, "docker run {args...} {docker_image}")).run()?)
}
19 changes: 19 additions & 0 deletions zk_toolbox/crates/common/src/ethereum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use ethers::{
providers::Middleware,
types::{Address, TransactionRequest, H256},
};
use types::TokenInfo;

use crate::{logger, wallets::Wallet};

Expand Down Expand Up @@ -58,10 +59,28 @@ pub async fn distribute_eth(
abigen!(
TokenContract,
r"[
function name() external view returns (string)
function symbol() external view returns (string)
function decimals() external view returns (uint8)
function mint(address to, uint256 amount)
]"
);

pub async fn get_token_info(token_address: Address, rpc_url: String) -> anyhow::Result<TokenInfo> {
let provider = Provider::<Http>::try_from(rpc_url)?;
let contract = TokenContract::new(token_address, Arc::new(provider));

let name = contract.name().call().await?;
let symbol = contract.symbol().call().await?;
let decimals = contract.decimals().call().await?;

Ok(TokenInfo {
name,
symbol,
decimals,
})
}

pub async fn mint_token(
main_wallet: Wallet,
token_address: Address,
Expand Down
3 changes: 3 additions & 0 deletions zk_toolbox/crates/config/src/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ pub const ERA_OBSERBAVILITY_GIT_REPO: &str = "https://github.com/matter-labs/era
pub(crate) const LOCAL_CONFIGS_PATH: &str = "configs/";
pub(crate) const LOCAL_DB_PATH: &str = "db/";

/// Name of portal config file
pub const PORTAL_CONFIG_FILE: &str = "portal.config.js";

/// Path to ecosystem contacts
pub(crate) const ECOSYSTEM_PATH: &str = "etc/env/ecosystems";

Expand Down
1 change: 1 addition & 0 deletions zk_toolbox/crates/config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,5 @@ mod wallets;

pub mod external_node;
pub mod forge_interface;
pub mod portal;
pub mod traits;
124 changes: 124 additions & 0 deletions zk_toolbox/crates/config/src/portal.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
use std::path::{Path, PathBuf};

use serde::{Deserialize, Serialize};
use types::TokenInfo;
use xshell::Shell;

use crate::{
consts::{LOCAL_CONFIGS_PATH, PORTAL_CONFIG_FILE},
traits::{FileConfigWithDefaultName, ReadConfig, SaveConfig},
};

#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct PortalRuntimeConfig {
pub node_type: String,
pub hyperchains_config: HyperchainsConfig,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct HyperchainsConfig(pub Vec<HyperchainConfig>);

impl HyperchainsConfig {
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct HyperchainConfig {
pub network: NetworkConfig,
pub tokens: Vec<TokenConfig>,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct NetworkConfig {
pub id: u64, // L2 Network ID
pub key: String, // L2 Network key
pub name: String, // L2 Network name
pub rpc_url: String, // L2 RPC URL
#[serde(skip_serializing_if = "Option::is_none")]
pub block_explorer_url: Option<String>, // L2 Block Explorer URL
#[serde(skip_serializing_if = "Option::is_none")]
pub block_explorer_api: Option<String>, // L2 Block Explorer API
#[serde(skip_serializing_if = "Option::is_none")]
pub public_l1_network_id: Option<u64>, // Ethereum Mainnet or Ethereum Sepolia Testnet ID
#[serde(skip_serializing_if = "Option::is_none")]
pub l1_network: Option<L1NetworkConfig>,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct L1NetworkConfig {
pub id: u64,
pub name: String,
pub network: String,
pub native_currency: TokenInfo,
pub rpc_urls: RpcUrls,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct RpcUrls {
pub default: RpcUrlConfig,
pub public: RpcUrlConfig,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct RpcUrlConfig {
pub http: Vec<String>,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct TokenConfig {
pub address: String,
pub symbol: String,
pub decimals: u8,
#[serde(skip_serializing_if = "Option::is_none")]
pub l1_address: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
}

impl PortalRuntimeConfig {
pub fn get_config_path(ecosystem_base_path: &Path) -> PathBuf {
ecosystem_base_path
.join(LOCAL_CONFIGS_PATH)
.join(PORTAL_CONFIG_FILE)
}
}

impl FileConfigWithDefaultName for PortalRuntimeConfig {
const FILE_NAME: &'static str = PORTAL_CONFIG_FILE;
}

impl SaveConfig for PortalRuntimeConfig {
fn save(&self, shell: &Shell, path: impl AsRef<Path>) -> anyhow::Result<()> {
// The dapp-portal is served as a pre-built static app in a Docker image.
// It uses a JavaScript file (config.js) that injects the configuration at runtime
// by overwriting the '##runtimeConfig' property of the window object.
// Therefore, we generate a JavaScript file instead of a JSON file.
// This file will be mounted to the Docker image when it runs.
let json = serde_json::to_string_pretty(&self)?;
let config_js_content = format!("window['##runtimeConfig'] = {};", json);
sanekmelnikov marked this conversation as resolved.
Show resolved Hide resolved
Ok(shell.write_file(path, config_js_content.as_bytes())?)
}
}

impl ReadConfig for PortalRuntimeConfig {
fn read(shell: &Shell, path: impl AsRef<Path>) -> anyhow::Result<Self> {
let config_js_content = shell.read_file(path)?;
// Extract the JSON part from the JavaScript file
let json_start = config_js_content
.find('{')
.ok_or_else(|| anyhow::anyhow!("Invalid config file format"))?;
let json_end = config_js_content
.rfind('}')
.ok_or_else(|| anyhow::anyhow!("Invalid config file format"))?;
let json_str = &config_js_content[json_start..=json_end];
// Parse the JSON into PortalRuntimeConfig
let config: PortalRuntimeConfig = serde_json::from_str(json_str)?;
Ok(config)
}
}
2 changes: 2 additions & 0 deletions zk_toolbox/crates/types/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
mod base_token;
mod l1_network;
mod prover_mode;
mod token_info;
mod wallet_creation;

pub use base_token::*;
pub use l1_network::*;
pub use prover_mode::*;
pub use token_info::*;
pub use wallet_creation::*;
pub use zksync_basic_types::{
commitment::L1BatchCommitmentMode, protocol_version::ProtocolSemanticVersion,
Expand Down
18 changes: 18 additions & 0 deletions zk_toolbox/crates/types/src/token_info.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
pub struct TokenInfo {
pub name: String,
pub symbol: String,
pub decimals: u8,
}

impl TokenInfo {
pub fn eth() -> Self {
Self {
name: "Ether".to_string(),
symbol: "ETH".to_string(),
decimals: 18,
}
}
}
2 changes: 2 additions & 0 deletions zk_toolbox/crates/zk_inception/src/commands/args/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
pub use containers::*;
pub use portal::*;
pub use run_server::*;
pub use update::*;

mod containers;
mod portal;
mod run_server;
mod update;
12 changes: 12 additions & 0 deletions zk_toolbox/crates/zk_inception/src/commands/args/portal.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
use clap::Parser;
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize, Parser)]
pub struct PortalArgs {
#[clap(
long,
default_value = "3030",
help = "The port number for the portal app"
)]
pub port: u16,
}
20 changes: 14 additions & 6 deletions zk_toolbox/crates/zk_inception/src/commands/chain/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,21 @@ use xshell::Shell;

use crate::{
accept_ownership::accept_admin,
commands::chain::{
args::init::{InitArgs, InitArgsFinal},
deploy_l2_contracts, deploy_paymaster,
genesis::genesis,
set_token_multiplier_setter::set_token_multiplier_setter,
commands::{
chain::{
args::init::{InitArgs, InitArgsFinal},
deploy_l2_contracts, deploy_paymaster,
genesis::genesis,
set_token_multiplier_setter::set_token_multiplier_setter,
},
portal::create_and_save_portal_config,
},
consts::AMOUNT_FOR_DISTRIBUTION_TO_WALLETS,
messages::{
msg_initializing_chain, MSG_ACCEPTING_ADMIN_SPINNER, MSG_CHAIN_INITIALIZED,
MSG_CHAIN_NOT_FOUND_ERR, MSG_DISTRIBUTING_ETH_SPINNER, MSG_GENESIS_DATABASE_ERR,
MSG_MINT_BASE_TOKEN_SPINNER, MSG_REGISTERING_CHAIN_SPINNER, MSG_SELECTED_CONFIG,
MSG_MINT_BASE_TOKEN_SPINNER, MSG_PORTAL_FAILED_TO_CREATE_CONFIG_ERR,
MSG_REGISTERING_CHAIN_SPINNER, MSG_SELECTED_CONFIG,
MSG_UPDATING_TOKEN_MULTIPLIER_SETTER_SPINNER,
},
utils::forge::{check_the_balance, fill_forge_private_key},
Expand Down Expand Up @@ -145,6 +149,10 @@ pub async fn init(
.await
.context(MSG_GENESIS_DATABASE_ERR)?;

create_and_save_portal_config(ecosystem_config, shell)
.await
.context(MSG_PORTAL_FAILED_TO_CREATE_CONFIG_ERR)?;

Ok(())
}

Expand Down
1 change: 1 addition & 0 deletions zk_toolbox/crates/zk_inception/src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pub mod containers;
pub mod contract_verifier;
pub mod ecosystem;
pub mod external_node;
pub mod portal;
pub mod prover;
pub mod server;
pub mod update;
Loading
Loading