diff --git a/cmd/soroban-cli/src/commands/contract/asset.rs b/cmd/soroban-cli/src/commands/contract/asset.rs new file mode 100644 index 0000000000..ad7be0207c --- /dev/null +++ b/cmd/soroban-cli/src/commands/contract/asset.rs @@ -0,0 +1,27 @@ +use super::{deploy, id}; + +#[derive(Debug, clap::Subcommand)] +pub enum Cmd { + /// Get Id of builtin Soroban Asset Contract. Deprecated, use `soroban contract id asset` instead + Id(id::asset::Cmd), + /// Deploy builtin Soroban Asset Contract + Deploy(deploy::asset::Cmd), +} + +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error(transparent)] + Id(#[from] id::asset::Error), + #[error(transparent)] + Deploy(#[from] deploy::asset::Error), +} + +impl Cmd { + pub async fn run(&self) -> Result<(), Error> { + match &self { + Cmd::Id(id) => id.run()?, + Cmd::Deploy(asset) => asset.run().await?, + } + Ok(()) + } +} diff --git a/cmd/soroban-cli/src/commands/contract/mod.rs b/cmd/soroban-cli/src/commands/contract/mod.rs index db450f611c..35be97a70b 100644 --- a/cmd/soroban-cli/src/commands/contract/mod.rs +++ b/cmd/soroban-cli/src/commands/contract/mod.rs @@ -1,3 +1,4 @@ +pub mod asset; pub mod bindings; pub mod build; pub mod deploy; @@ -15,6 +16,9 @@ use crate::commands::global; #[derive(Debug, clap::Subcommand)] pub enum Cmd { + /// Utilities to deploy a Stellar Asset Contract or get its id + #[command(subcommand)] + Asset(asset::Cmd), /// Generate code client bindings for a contract #[command(subcommand)] Bindings(bindings::Cmd), @@ -26,9 +30,8 @@ pub enum Cmd { /// If no keys are specified the contract itself is extended. Extend(extend::Cmd), - /// Deploy a contract or Soroban Asset Contract - #[command(subcommand)] - Deploy(deploy::Cmd), + /// Deploy a wasm contract + Deploy(deploy::wasm::Cmd), /// Fetch a contract's Wasm binary Fetch(fetch::Cmd), @@ -67,6 +70,9 @@ pub enum Cmd { #[derive(thiserror::Error, Debug)] pub enum Error { + #[error(transparent)] + Asset(#[from] asset::Error), + #[error(transparent)] Bindings(#[from] bindings::Error), @@ -77,7 +83,7 @@ pub enum Error { Extend(#[from] extend::Error), #[error(transparent)] - Deploy(#[from] deploy::Error), + Deploy(#[from] deploy::wasm::Error), #[error(transparent)] Fetch(#[from] fetch::Error), @@ -106,6 +112,7 @@ pub enum Error { impl Cmd { pub async fn run(&self, global_args: &global::Args) -> Result<(), Error> { match &self { + Cmd::Asset(asset) => asset.run().await?, Cmd::Bindings(bindings) => bindings.run().await?, Cmd::Build(build) => build.run()?, Cmd::Extend(extend) => extend.run().await?, diff --git a/cmd/soroban-rpc/internal/test/cli_test.go b/cmd/soroban-rpc/internal/test/cli_test.go index fbffc660bf..997372ed89 100644 --- a/cmd/soroban-rpc/internal/test/cli_test.go +++ b/cmd/soroban-rpc/internal/test/cli_test.go @@ -51,7 +51,7 @@ func TestCLIWrapCustom(t *testing.T) { it := NewCLITest(t) assetCode := "deadbeef" issuerAccount := getCLIDefaultAccount(t) - strkeyContractID := runSuccessfulCLICmd(t, fmt.Sprintf("contract deploy asset --asset=%s:%s", assetCode, issuerAccount)) + strkeyContractID := runSuccessfulCLICmd(t, fmt.Sprintf("contract asset deploy --asset=%s:%s", assetCode, issuerAccount)) require.Equal(t, "true", runSuccessfulCLICmd(t, fmt.Sprintf("contract invoke --id=%s -- authorized --id=%s", strkeyContractID, issuerAccount))) asset := txnbuild.CreditAsset{ Code: assetCode, @@ -65,7 +65,7 @@ func TestCLIWrapCustom(t *testing.T) { func TestCLIWrapNative(t *testing.T) { NewCLITest(t) testAccount := getCLIDefaultAccount(t) - strkeyContractID := runSuccessfulCLICmd(t, fmt.Sprintf("contract deploy asset --asset=native:%s", testAccount)) + strkeyContractID := runSuccessfulCLICmd(t, fmt.Sprintf("contract asset deploy --asset=native:%s", testAccount)) require.Equal(t, "CAMTHSPKXZJIRTUXQP5QWJIFH3XIDMKLFAWVQOFOXPTKAW5GKV37ZC4N", strkeyContractID) require.Equal(t, "true", runSuccessfulCLICmd(t, fmt.Sprintf("contract invoke --id=%s -- authorized --id=%s", strkeyContractID, testAccount))) require.Equal(t, "\"9223372036854775807\"", runSuccessfulCLICmd(t, fmt.Sprintf("contract invoke --id=%s -- balance --id %s", strkeyContractID, testAccount))) @@ -84,13 +84,13 @@ func TestCLIContractInstallAndDeploy(t *testing.T) { runSuccessfulCLICmd(t, fmt.Sprintf("contract install --wasm %s --ignore-checks", helloWorldContractPath)) wasm := getHelloWorldContract(t) contractHash := xdr.Hash(sha256.Sum256(wasm)) - output := runSuccessfulCLICmd(t, fmt.Sprintf("contract deploy wasm --salt %s --wasm-hash %s --ignore-checks", hex.EncodeToString(testSalt[:]), contractHash.HexString())) + output := runSuccessfulCLICmd(t, fmt.Sprintf("contract deploy --salt %s --wasm-hash %s --ignore-checks", hex.EncodeToString(testSalt[:]), contractHash.HexString())) outputsContractIDInLastLine(t, output) } func TestCLIContractDeploy(t *testing.T) { NewCLITest(t) - output := runSuccessfulCLICmd(t, fmt.Sprintf("contract deploy wasm --salt %s --wasm %s --ignore-checks", hex.EncodeToString(testSalt[:]), helloWorldContractPath)) + output := runSuccessfulCLICmd(t, fmt.Sprintf("contract deploy --salt %s --wasm %s --ignore-checks", hex.EncodeToString(testSalt[:]), helloWorldContractPath)) outputsContractIDInLastLine(t, output) } @@ -110,14 +110,14 @@ func outputsContractIDInLastLine(t *testing.T, output string) { func TestCLIContractDeployAndInvoke(t *testing.T) { NewCLITest(t) - contractID := runSuccessfulCLICmd(t, fmt.Sprintf("contract deploy wasm --salt=%s --wasm %s --ignore-checks", hex.EncodeToString(testSalt[:]), helloWorldContractPath)) + contractID := runSuccessfulCLICmd(t, fmt.Sprintf("contract deploy --salt=%s --wasm %s --ignore-checks", hex.EncodeToString(testSalt[:]), helloWorldContractPath)) output := runSuccessfulCLICmd(t, fmt.Sprintf("contract invoke --id %s -- hello --world=world", contractID)) require.Contains(t, output, `["Hello","world"]`) } func TestCLIRestorePreamble(t *testing.T) { test := NewCLITest(t) - strkeyContractID := runSuccessfulCLICmd(t, fmt.Sprintf("contract deploy wasm --salt=%s --wasm %s --ignore-checks", hex.EncodeToString(testSalt[:]), helloWorldContractPath)) + strkeyContractID := runSuccessfulCLICmd(t, fmt.Sprintf("contract deploy --salt=%s --wasm %s --ignore-checks", hex.EncodeToString(testSalt[:]), helloWorldContractPath)) count := runSuccessfulCLICmd(t, fmt.Sprintf("contract invoke --id %s -- inc", strkeyContractID)) require.Equal(t, "1", count) count = runSuccessfulCLICmd(t, fmt.Sprintf("contract invoke --id %s -- inc", strkeyContractID)) @@ -135,7 +135,7 @@ func TestCLIRestorePreamble(t *testing.T) { func TestCLIExtend(t *testing.T) { test := NewCLITest(t) - strkeyContractID := runSuccessfulCLICmd(t, fmt.Sprintf("contract deploy wasm --salt=%s --wasm %s --ignore-checks", hex.EncodeToString(testSalt[:]), helloWorldContractPath)) + strkeyContractID := runSuccessfulCLICmd(t, fmt.Sprintf("contract deploy --salt=%s --wasm %s --ignore-checks", hex.EncodeToString(testSalt[:]), helloWorldContractPath)) count := runSuccessfulCLICmd(t, fmt.Sprintf("contract invoke --id %s -- inc", strkeyContractID)) require.Equal(t, "1", count) @@ -159,7 +159,7 @@ func TestCLIExtend(t *testing.T) { } func TestCLIExtendTooLow(t *testing.T) { test := NewCLITest(t) - strkeyContractID := runSuccessfulCLICmd(t, fmt.Sprintf("contract deploy wasm --salt=%s --wasm %s --ignore-checks", hex.EncodeToString(testSalt[:]), helloWorldContractPath)) + strkeyContractID := runSuccessfulCLICmd(t, fmt.Sprintf("contract deploy --salt=%s --wasm %s --ignore-checks", hex.EncodeToString(testSalt[:]), helloWorldContractPath)) count := runSuccessfulCLICmd(t, fmt.Sprintf("contract invoke --id %s -- inc", strkeyContractID)) require.Equal(t, "1", count) @@ -181,7 +181,7 @@ func TestCLIExtendTooLow(t *testing.T) { func TestCLIExtendTooHigh(t *testing.T) { test := NewCLITest(t) - strkeyContractID := runSuccessfulCLICmd(t, fmt.Sprintf("contract deploy wasm --salt=%s --wasm %s --ignore-checks", hex.EncodeToString(testSalt[:]), helloWorldContractPath)) + strkeyContractID := runSuccessfulCLICmd(t, fmt.Sprintf("contract deploy --salt=%s --wasm %s --ignore-checks", hex.EncodeToString(testSalt[:]), helloWorldContractPath)) count := runSuccessfulCLICmd(t, fmt.Sprintf("contract invoke --id %s -- inc", strkeyContractID)) require.Equal(t, "1", count) @@ -200,7 +200,7 @@ func TestCLIExtendTooHigh(t *testing.T) { func TestCLIRestore(t *testing.T) { test := NewCLITest(t) - strkeyContractID := runSuccessfulCLICmd(t, fmt.Sprintf("contract deploy wasm --salt=%s --wasm %s --ignore-checks", hex.EncodeToString(testSalt[:]), helloWorldContractPath)) + strkeyContractID := runSuccessfulCLICmd(t, fmt.Sprintf("contract deploy --salt=%s --wasm %s --ignore-checks", hex.EncodeToString(testSalt[:]), helloWorldContractPath)) count := runSuccessfulCLICmd(t, fmt.Sprintf("contract invoke --id %s -- inc", strkeyContractID)) require.Equal(t, "1", count) diff --git a/cmd/soroban-rpc/internal/test/simulate_transaction_test.go b/cmd/soroban-rpc/internal/test/simulate_transaction_test.go index 18b465cb29..cd7ed05b74 100644 --- a/cmd/soroban-rpc/internal/test/simulate_transaction_test.go +++ b/cmd/soroban-rpc/internal/test/simulate_transaction_test.go @@ -1125,7 +1125,7 @@ func TestSimulateSystemEvent(t *testing.T) { err = xdr.SafeUnmarshalBase64(response.TransactionData, &transactionData) require.NoError(t, err) - assert.InDelta(t, 7464, uint32(transactionData.Resources.ReadBytes), 200) + assert.InDelta(t, 7464, uint32(transactionData.Resources.ReadBytes), 700) // the resulting fee is derived from compute factors and a default padding is applied to instructions by preflight // for test purposes, the most deterministic way to assert the resulting fee is expected value in test scope, is to capture // the resulting fee from current preflight output and re-plug it in here, rather than try to re-implement the cost-model algo diff --git a/docs/soroban-cli-full-docs.md b/docs/soroban-cli-full-docs.md index 7018c2472d..0e65fd630f 100644 --- a/docs/soroban-cli-full-docs.md +++ b/docs/soroban-cli-full-docs.md @@ -20,6 +20,9 @@ This document contains the help content for the `soroban` command-line program. * [`soroban config identity rm`↴](#soroban-config-identity-rm) * [`soroban config identity show`↴](#soroban-config-identity-show) * [`soroban contract`↴](#soroban-contract) +* [`soroban contract asset`↴](#soroban-contract-asset) +* [`soroban contract asset id`↴](#soroban-contract-asset-id) +* [`soroban contract asset deploy`↴](#soroban-contract-asset-deploy) * [`soroban contract bindings`↴](#soroban-contract-bindings) * [`soroban contract bindings json`↴](#soroban-contract-bindings-json) * [`soroban contract bindings rust`↴](#soroban-contract-bindings-rust) @@ -27,8 +30,6 @@ This document contains the help content for the `soroban` command-line program. * [`soroban contract build`↴](#soroban-contract-build) * [`soroban contract extend`↴](#soroban-contract-extend) * [`soroban contract deploy`↴](#soroban-contract-deploy) -* [`soroban contract deploy asset`↴](#soroban-contract-deploy-asset) -* [`soroban contract deploy wasm`↴](#soroban-contract-deploy-wasm) * [`soroban contract fetch`↴](#soroban-contract-fetch) * [`soroban contract id`↴](#soroban-contract-id) * [`soroban contract id asset`↴](#soroban-contract-id-asset) @@ -376,10 +377,11 @@ Tools for smart contract developers ###### **Subcommands:** +* `asset` — Utilities to deploy a Stellar Asset Contract or get its id * `bindings` — Generate code client bindings for a contract * `build` — Build a contract from source * `extend` — Extend the time to live ledger of a contract-data ledger entry -* `deploy` — Deploy a contract or Soroban Asset Contract +* `deploy` — Deploy a wasm contract * `fetch` — Fetch a contract's Wasm binary * `id` — Generate the contract id for a given contract or asset * `inspect` — Inspect a WASM file listing contract functions, meta, etc @@ -391,6 +393,60 @@ Tools for smart contract developers +## `soroban contract asset` + +Utilities to deploy a Stellar Asset Contract or get its id + +**Usage:** `soroban contract asset ` + +###### **Subcommands:** + +* `id` — Get Id of builtin Soroban Asset Contract. Deprecated, use `soroban contract id asset` instead +* `deploy` — Deploy builtin Soroban Asset Contract + + + +## `soroban contract asset id` + +Get Id of builtin Soroban Asset Contract. Deprecated, use `soroban contract id asset` instead + +**Usage:** `soroban contract asset id [OPTIONS] --asset --source-account ` + +###### **Options:** + +* `--asset ` — ID of the Stellar classic asset to wrap, e.g. "USDC:G...5" +* `--rpc-url ` — RPC server endpoint +* `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server +* `--network ` — Name of network to use from config +* `--source-account ` — Account that signs the final transaction. Alias `source`. Can be an identity (--source alice), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). Default: `identity generate --default-seed` +* `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` +* `--global` — Use global config +* `--config-dir ` + + + +## `soroban contract asset deploy` + +Deploy builtin Soroban Asset Contract + +**Usage:** `soroban contract asset deploy [OPTIONS] --asset --source-account ` + +###### **Options:** + +* `--asset ` — ID of the Stellar classic asset to wrap, e.g. "USDC:G...5" +* `--rpc-url ` — RPC server endpoint +* `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server +* `--network ` — Name of network to use from config +* `--source-account ` — Account that signs the final transaction. Alias `source`. Can be an identity (--source alice), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). Default: `identity generate --default-seed` +* `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` +* `--global` — Use global config +* `--config-dir ` +* `--fee ` — fee amount for transaction, in stroops. 1 stroop = 0.0000001 xlm + + Default value: `100` + + + ## `soroban contract bindings` Generate code client bindings for a contract @@ -516,44 +572,9 @@ If no keys are specified the contract itself is extended. ## `soroban contract deploy` -Deploy a contract or Soroban Asset Contract - -**Usage:** `soroban contract deploy ` - -###### **Subcommands:** - -* `asset` — Deploy builtin Soroban Asset Contract -* `wasm` — Deploy normal Wasm Contract - - - -## `soroban contract deploy asset` - -Deploy builtin Soroban Asset Contract - -**Usage:** `soroban contract deploy asset [OPTIONS] --asset --source-account ` - -###### **Options:** - -* `--asset ` — ID of the Stellar classic asset to wrap, e.g. "USDC:G...5" -* `--rpc-url ` — RPC server endpoint -* `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server -* `--network ` — Name of network to use from config -* `--source-account ` — Account that signs the final transaction. Alias `source`. Can be an identity (--source alice), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). Default: `identity generate --default-seed` -* `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` -* `--global` — Use global config -* `--config-dir ` -* `--fee ` — fee amount for transaction, in stroops. 1 stroop = 0.0000001 xlm - - Default value: `100` - - - -## `soroban contract deploy wasm` - -Deploy normal Wasm Contract +Deploy a wasm contract -**Usage:** `soroban contract deploy wasm [OPTIONS] --source-account <--wasm |--wasm-hash >` +**Usage:** `soroban contract deploy [OPTIONS] --source-account <--wasm |--wasm-hash >` ###### **Options:**