February 18, 2025
Nexus
Заходим на сервер, вводим следующую команду и ждём, пока установятся зависимости:
sudo apt update && sudo apt upgrade -y && \ sudo apt install -y tmux nano build-essential pkg-config libssl-dev git-all unzip && \ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y && \ source $HOME/.cargo/env && \ cargo --version && \ rustup target add riscv32i-unknown-none-elf && \ sudo apt remove -y protobuf-compiler && \ curl -LO https://github.com/protocolbuffers/protobuf/releases/download/v25.2/protoc-25.2-linux-x86_64.zip && \ unzip protoc-25.2-linux-x86_64.zip -d $HOME/.local && \ export PATH="$HOME/.local/bin:$PATH" && \ protoc --version
Вводим следующую команду и ждём 10 минут, пока нода установится:
curl https://cli.nexus.xyz/ | sh
nano $HOME/.nexus/network-api/clients/cli/src/setup.rs
Зажимаем Ctrl+K что бы удалить все строки.
Копируем и вставляем новый код:
use colored::Colorize;
use directories::ProjectDirs;
use serde::{Deserialize, Serialize};
use std::fs;
// Update the import path to use the proto module
// use crate::config;
// use crate::orchestrator_client::OrchestratorClient;
pub enum SetupResult {
Anonymous,
Connected(String), // String could be the public key or other connection info
Invalid,
}
#[derive(Serialize, Deserialize)]
pub struct UserConfig {
pub node_id: String,
pub user_id: Option<String>,
}
// fn save_user_config(user_id: &str, node_id: &str) -> std::io::Result<()> {
// let proj_dirs =
// ProjectDirs::from("xyz", "nexus", "cli").expect("Failed to determine config directory");
// let config_dir = proj_dirs.config_dir();
// fs::create_dir_all(config_dir)?;
// let config_path = config_dir.join("user.json");
// let config = UserConfig {
// user_id: Some(user_id.to_string()),
// node_id: node_id.to_string(),
// };
// fs::write(&config_path, serde_json::to_string_pretty(&config)?)?;
// //print the user config was saved properly
// println!("User ID: {}", user_id);
// println!("Node ID: {}", node_id);
// println!("User config saved to: {}", config_path.to_string_lossy());
// Ok(())
// }
//function that takes a node_id and saves it to the user config
fn save_node_id(node_id: &str) -> std::io::Result<()> {
let proj_dirs =
ProjectDirs::from("xyz", "nexus", "cli").expect("Failed to determine config directory");
//
let config_dir = proj_dirs.config_dir();
fs::create_dir_all(config_dir)?;
//
let config_path = proj_dirs.config_dir().join("user.json");
let config = UserConfig {
node_id: node_id.to_string(),
user_id: None,
};
fs::write(&config_path, serde_json::to_string_pretty(&config)?)?;
Ok(())
}
pub async fn run_initial_setup() -> SetupResult {
//check if there is a user config file
let proj_dirs =
ProjectDirs::from("xyz", "nexus", "cli").expect("Failed to determine config directory");
let config_path = proj_dirs.config_dir().join("user.json");
if config_path.exists() {
println!("\nThis node is already connected to an account");
//ask the user if they want to use the existing config
println!("Do you want to use the existing user account? (y/n)");
let mut use_existing_config = String::new();
std::io::stdin()
.read_line(&mut use_existing_config)
.unwrap();
let use_existing_config = use_existing_config.trim();
if use_existing_config == "y" {
match fs::read_to_string(&config_path) {
Ok(content) => match serde_json::from_str::<UserConfig>(&content) {
Ok(user_config) => {
println!("\nUsing existing node ID: {}", user_config.node_id);
return SetupResult::Connected(user_config.node_id);
}
Err(e) => {
println!("{}", format!("Failed to parse config file: {}", e).red());
return SetupResult::Invalid;
}
},
Err(e) => {
println!("{}", format!("Failed to read config file: {}", e).red());
return SetupResult::Invalid;
}
}
} else {
println!("Ignoring existing user account...");
}
}
println!("\nThis node is not connected to any account.\n");
println!("[1] Enter '1' to start proving without earning NEX");
println!("[2] Enter '2' to start earning NEX by connecting adding your node ID");
let mut option = String::new();
std::io::stdin().read_line(&mut option).unwrap();
let option = option.trim();
//if no config file exists, ask the user to enter their email
match option {
"1" => {
println!("You chose option 1\n");
SetupResult::Anonymous
}
"2" => {
println!(
"\n===== {} =====\n",
"Adding your node ID to the CLI"
.bold()
.underline()
.bright_cyan()
);
println!("You chose to start earning NEX by connecting your node ID\n");
println!("If you don't have a node ID, you can get it by following these steps:\n");
println!("1. Go to https://app.nexus.xyz/nodes");
println!("2. Sign in");
println!("3. Click on the '+ Add Node' button");
println!("4. Select 'Add CLI node'");
println!("5. You will be given a node ID to add to this CLI");
println!("6. Enter the node ID into the terminal below:\n");
let node_id = get_node_id_from_user();
match save_node_id(&node_id) {
Ok(_) => SetupResult::Connected(node_id),
Err(e) => {
println!("{}", format!("Failed to save node ID: {}", e).red());
SetupResult::Invalid
}
}
}
_ => {
println!("Invalid option");
SetupResult::Invalid
}
}
}
pub fn clear_user_config() -> std::io::Result<()> {
let proj_dirs =
ProjectDirs::from("xyz", "nexus", "cli").expect("Failed to determine config directory");
let config_path = proj_dirs.config_dir().join("user.json");
if config_path.exists() {
fs::remove_file(config_path)?;
}
Ok(())
}
fn get_node_id_from_user() -> String {
println!("{}", "Please enter your node ID:".green());
let mut node_id = String::new();
std::io::stdin()
.read_line(&mut node_id)
.expect("Failed to read node ID");
node_id.trim().to_string()
}
Сохраняем изменения в редакторе
Нажмите комбинацию клавиш CTRL+X, затем Y и Enter.
Запускаем ноду
Перейдите в директорию и запустите ноду:
cd /root/.nexus/network-api/clients/cli/
cargo run --release -- --start --beta
Привязка ID
Если ошибок нет, выберите опцию 2, введите свой ID и нажмите Enter.
Важно: ID для каждой ноды должен быть уникальным.
Если после этого снова возникает ошибка:
rustup target add riscv32i-unknown-none-elf
tmux new-session -s nexus
cargo run --release -- --start --beta
Если видим такие логи, значит нода работает.
Всем спасибо, подпишитесь на мой телеграм канал, там больше новых гайдов! https://t.me/SotochkaZela