Skip to content

Commit

Permalink
Merge branch 'main' into add-other-ledger-test-emulators
Browse files Browse the repository at this point in the history
  • Loading branch information
elizabethengelman authored Jun 12, 2024
2 parents 87119c3 + e189c71 commit 4db00c4
Show file tree
Hide file tree
Showing 11 changed files with 352 additions and 26 deletions.
99 changes: 96 additions & 3 deletions FULL_HELP_DOCS.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ This document contains the help content for the `stellar` command-line program.
* [`stellar network ls`](#stellar-network-ls)
* [`stellar network start`](#stellar-network-start)
* [`stellar network stop`](#stellar-network-stop)
* [`stellar network container`](#stellar-network-container)
* [`stellar network container logs`](#stellar-network-container-logs)
* [`stellar network container start`](#stellar-network-container-start)
* [`stellar network container stop`](#stellar-network-container-stop)
* [`stellar version`](#stellar-version)
* [`stellar cache`](#stellar-cache)
* [`stellar cache clean`](#stellar-cache-clean)
Expand Down Expand Up @@ -452,6 +456,7 @@ Deploy a wasm contract

Possible values: `true`, `false`

* `--alias <ALIAS>` — The alias that will be used to save the contract's id



Expand Down Expand Up @@ -1188,8 +1193,9 @@ Start and configure networks
* `add` — Add a new network
* `rm` — Remove a network
* `ls` — List networks
* `start` — Start network
* `stop` — Stop a network started with `network start`. For example, if you ran `soroban network start local`, you can use `soroban network stop local` to stop it
* `start` — ⚠️ Deprecated: use `soroban container start` instead
* `stop` — ⚠️ Deprecated: use `soroban container stop` instead
* `container` — Commands to start, stop and get logs for a quickstart container



Expand Down Expand Up @@ -1257,6 +1263,8 @@ List networks

## `stellar network start`

⚠️ Deprecated: use `soroban container start` instead

Start network

Start a container running a Stellar node, RPC, API, and friendbot (faucet).
Expand Down Expand Up @@ -1288,7 +1296,9 @@ By default, when starting a testnet container, without any optional arguments, i

## `stellar network stop`

Stop a network started with `network start`. For example, if you ran `soroban network start local`, you can use `soroban network stop local` to stop it
⚠️ Deprecated: use `soroban container stop` instead

Stop a network started with `network start`. For example, if you ran `soroban network start local`, you can use `soroban network stop local` to stop it.

**Usage:** `stellar network stop [OPTIONS] <NETWORK>`

Expand All @@ -1305,6 +1315,89 @@ Stop a network started with `network start`. For example, if you ran `soroban ne



## `stellar network container`

Commands to start, stop and get logs for a quickstart container

**Usage:** `stellar network container <COMMAND>`

###### **Subcommands:**

* `logs` — Tail logs of a running network container
* `start` — Start network
* `stop` — Stop a network started with `network container start`. For example, if you ran `network container start local`, you can use `network container stop local` to stop it



## `stellar network container logs`

Tail logs of a running network container

**Usage:** `stellar network container logs [OPTIONS] <NETWORK>`

###### **Arguments:**

* `<NETWORK>` — Network to tail

Possible values: `local`, `testnet`, `futurenet`, `pubnet`


###### **Options:**

* `-d`, `--docker-host <DOCKER_HOST>` — Optional argument to override the default docker host. This is useful when you are using a non-standard docker host path for your Docker-compatible container runtime, e.g. Docker Desktop defaults to $HOME/.docker/run/docker.sock instead of /var/run/docker.sock



## `stellar network container start`

Start network

Start a container running a Stellar node, RPC, API, and friendbot (faucet).

soroban network start <NETWORK> [OPTIONS]

By default, when starting a testnet container, without any optional arguments, it will run the equivalent of the following docker command: docker run --rm -p 8000:8000 --name stellar stellar/quickstart:testing --testnet --enable-soroban-rpc

**Usage:** `stellar network container start [OPTIONS] <NETWORK>`

###### **Arguments:**

* `<NETWORK>` — Network to start

Possible values: `local`, `testnet`, `futurenet`, `pubnet`


###### **Options:**

* `-d`, `--docker-host <DOCKER_HOST>` — Optional argument to override the default docker host. This is useful when you are using a non-standard docker host path for your Docker-compatible container runtime, e.g. Docker Desktop defaults to $HOME/.docker/run/docker.sock instead of /var/run/docker.sock
* `-l`, `--limits <LIMITS>` — Optional argument to specify the limits for the local network only
* `-p`, `--ports-mapping <PORTS_MAPPING>` — Argument to specify the HOST_PORT:CONTAINER_PORT mapping

Default value: `8000:8000`
* `-t`, `--image-tag-override <IMAGE_TAG_OVERRIDE>` — Optional argument to override the default docker image tag for the given network
* `-v`, `--protocol-version <PROTOCOL_VERSION>` — Optional argument to specify the protocol version for the local network only



## `stellar network container stop`

Stop a network started with `network container start`. For example, if you ran `network container start local`, you can use `network container stop local` to stop it

**Usage:** `stellar network container stop [OPTIONS] <NETWORK>`

###### **Arguments:**

* `<NETWORK>` — Network to stop

Possible values: `local`, `testnet`, `futurenet`, `pubnet`


###### **Options:**

* `-d`, `--docker-host <DOCKER_HOST>` — Optional argument to override the default docker host. This is useful when you are using a non-standard docker host path for your Docker-compatible container runtime, e.g. Docker Desktop defaults to $HOME/.docker/run/docker.sock instead of /var/run/docker.sock



## `stellar version`

Print version information
Expand Down
10 changes: 5 additions & 5 deletions cmd/soroban-cli/src/commands/contract/bindings/typescript.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,17 @@ pub struct Cmd {
pub wasm: Option<std::path::PathBuf>,
/// Where to place generated project
#[arg(long)]
output_dir: PathBuf,
pub output_dir: PathBuf,
/// Whether to overwrite output directory if it already exists
#[arg(long)]
overwrite: bool,
pub overwrite: bool,
/// The contract ID/address on the network
#[arg(long, visible_alias = "id")]
contract_id: String,
pub contract_id: String,
#[command(flatten)]
locator: locator::Args,
pub locator: locator::Args,
#[command(flatten)]
network: network::Args,
pub network: network::Args,
}

#[derive(thiserror::Error, Debug)]
Expand Down
82 changes: 77 additions & 5 deletions cmd/soroban-cli/src/commands/contract/deploy/wasm.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
use std::array::TryFromSliceError;
use std::fmt::Debug;
use std::fs::{self, create_dir_all};
use std::io::Write;
use std::num::ParseIntError;
use std::path::PathBuf;
use std::{array::TryFromSliceError, fs::OpenOptions};

use clap::{arg, command, Parser};
use rand::Rng;
use regex::Regex;
use soroban_env_host::{
xdr::{
AccountId, ContractExecutable, ContractIdPreimage, ContractIdPreimageFromAddress,
Expand All @@ -14,6 +18,7 @@ use soroban_env_host::{
HostError,
};

use crate::commands::contract::AliasData;
use crate::commands::{
config::data,
contract::{self, id::wasm::get_contract_id},
Expand All @@ -37,23 +42,26 @@ use crate::{
pub struct Cmd {
/// WASM file to deploy
#[arg(long, group = "wasm_src")]
wasm: Option<std::path::PathBuf>,
pub wasm: Option<std::path::PathBuf>,
/// Hash of the already installed/deployed WASM file
#[arg(long = "wasm-hash", conflicts_with = "wasm", group = "wasm_src")]
wasm_hash: Option<String>,
pub wasm_hash: Option<String>,
/// Custom salt 32-byte salt for the token id
#[arg(
long,
help_heading = HEADING_RPC,
)]
salt: Option<String>,
pub salt: Option<String>,
#[command(flatten)]
config: config::Args,
pub config: config::Args,
#[command(flatten)]
pub fee: crate::fee::Args,
#[arg(long, short = 'i', default_value = "false")]
/// Whether to ignore safety checks when deploying contracts
pub ignore_checks: bool,
/// The alias that will be used to save the contract's id.
#[arg(long)]
pub alias: Option<String>,
}

#[derive(thiserror::Error, Debug)]
Expand Down Expand Up @@ -100,19 +108,83 @@ pub enum Error {
Network(#[from] network::Error),
#[error(transparent)]
Wasm(#[from] wasm::Error),
#[error("cannot access config dir for alias file")]
CannotAccessConfigDir,
#[error(
"alias must be 1-30 chars long, and have only letters, numbers, underscores and dashes"
)]
InvalidAliasFormat { alias: String },
#[error(transparent)]
JsonSerialization(#[from] serde_json::Error),
#[error(transparent)]
Io(#[from] std::io::Error),
}

impl Cmd {
pub async fn run(&self) -> Result<(), Error> {
self.validate_alias()?;

let res = self.run_against_rpc_server(None, None).await?.to_envelope();
match res {
TxnEnvelopeResult::TxnEnvelope(tx) => println!("{}", tx.to_xdr_base64(Limits::none())?),
TxnEnvelopeResult::Res(contract) => {
self.save_contract_id(&contract)?;
println!("{contract}");
}
}
Ok(())
}

fn validate_alias(&self) -> Result<(), Error> {
match self.alias.clone() {
Some(alias) => {
let regex = Regex::new(r"^[a-zA-Z0-9_-]{1,30}$").unwrap();

if regex.is_match(&alias) {
Ok(())
} else {
Err(Error::InvalidAliasFormat { alias })
}
}
None => Ok(()),
}
}

fn alias_path_for(&self, alias: &str) -> Result<PathBuf, Error> {
let config_dir = self.config.config_dir()?;
let file_name = format!("{alias}.json");

Ok(config_dir.join("contract-ids").join(file_name))
}

fn save_contract_id(&self, contract: &String) -> Result<(), Error> {
let Some(alias) = &self.alias else {
return Ok(());
};

let file_path = self.alias_path_for(alias)?;
let dir = file_path.parent().ok_or(Error::CannotAccessConfigDir)?;

create_dir_all(dir).map_err(|_| Error::CannotAccessConfigDir)?;

let content = fs::read_to_string(&file_path).unwrap_or_default();
let mut data: AliasData = serde_json::from_str(&content).unwrap_or_default();

let mut to_file = OpenOptions::new()
.create(true)
.truncate(true)
.write(true)
.open(file_path)?;

data.ids.insert(
self.config.get_network()?.network_passphrase,
contract.into(),
);

let content = serde_json::to_string(&data)?;

Ok(to_file.write_all(content.as_bytes())?)
}
}

#[async_trait::async_trait]
Expand Down
40 changes: 38 additions & 2 deletions cmd/soroban-cli/src/commands/contract/invoke.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ use super::super::{
config::{self, locator},
events,
};
use super::AliasData;
use crate::commands::txn_result::{TxnEnvelopeResult, TxnResult};
use crate::commands::NetworkRunnable;
use crate::get_spec::{self, get_remote_contract_spec};
Expand Down Expand Up @@ -152,6 +153,12 @@ pub enum Error {
Network(#[from] network::Error),
#[error(transparent)]
GetSpecError(#[from] get_spec::Error),
#[error("unable to read alias file")]
UnableToReadAliasFile,
#[error("alias file not found")]
NoAliasFileFound,
#[error(transparent)]
JsonDeserialization(#[from] serde_json::Error),
}

impl From<Infallible> for Error {
Expand Down Expand Up @@ -305,8 +312,37 @@ impl Cmd {

impl Cmd {
fn contract_id(&self) -> Result<[u8; 32], Error> {
soroban_spec_tools::utils::contract_id_from_str(&self.contract_id)
.map_err(|e| Error::CannotParseContractId(self.contract_id.clone(), e))
let contract_id: String = match self.load_contract_id() {
Ok(Some(id)) => id.to_string(),
_ => self.contract_id.clone(),
};

soroban_spec_tools::utils::contract_id_from_str(&contract_id)
.map_err(|e| Error::CannotParseContractId(contract_id.clone(), e))
}

fn alias_path(&self) -> Result<PathBuf, Error> {
let config_dir = self.config.config_dir()?;
let file_name = format!("{}.json", self.contract_id);

Ok(config_dir.join("contract-ids").join(file_name))
}

fn load_contract_id(&self) -> Result<Option<String>, Error> {
let network = &self.config.get_network()?.network_passphrase;
let file_path = self.alias_path()?;

if !file_path.exists() {
return Ok(None);
}

let content = fs::read_to_string(file_path)?;
let data: AliasData = serde_json::from_str(&content)?;

match data.ids.get(network) {
Some(id) => Ok(Some(id.into())),
_ => Ok(None),
}
}
}

Expand Down
9 changes: 9 additions & 0 deletions cmd/soroban-cli/src/commands/contract/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ pub mod optimize;
pub mod read;
pub mod restore;

use std::collections::HashMap;

use serde::{Deserialize, Serialize};

use crate::commands::global;

#[derive(Debug, clap::Subcommand)]
Expand Down Expand Up @@ -165,3 +169,8 @@ pub enum SpecOutput {
/// Pretty print of contract spec entries
Docs,
}

#[derive(Serialize, Deserialize, Default)]
pub struct AliasData {
ids: HashMap<String, String>,
}
Loading

0 comments on commit 4db00c4

Please sign in to comment.