From 5454d8454f3996c246bfe9d5624b54b51e6b75de Mon Sep 17 00:00:00 2001 From: Leigh McCulloch <351529+leighmcculloch@users.noreply.github.com> Date: Wed, 4 Dec 2024 08:34:17 +1000 Subject: [PATCH 1/2] Add a stale CI workflow (#1775) --- .github/workflows/stale.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .github/workflows/stale.yml diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml new file mode 100644 index 000000000..54c57da0e --- /dev/null +++ b/.github/workflows/stale.yml @@ -0,0 +1,23 @@ +name: 'Stale Issues / PRs' + +on: + workflow_dispatch: + schedule: + - cron: '0 18 * * *' # approx 9:30am daily + +jobs: + stale: + runs-on: ubuntu-latest + steps: + - uses: actions/stale@v9 + with: + debug-only: false + days-before-stale: 30 + days-before-close: 30 + stale-issue-message: 'This issue is stale because it has been assigned for 30 days with no activity. It will be closed in 30 days unless the stale label is removed, and the assignee is removed or updated.' + stale-pr-message: 'This pull request is stale because it has been open for 30 days with no activity. It will be closed in 30 days unless the stale label is removed.' + stale-issue-label: stale + stale-pr-label: stale + remove-stale-when-updated: true + delete-branch: true + include-only-assigned: true From a03b1d7557251e6300b811c51f8b234f942d980a Mon Sep 17 00:00:00 2001 From: Willem Wyndham Date: Wed, 4 Dec 2024 10:31:57 -0500 Subject: [PATCH 2/2] feat: add `tx op add` (#1663) Co-authored-by: Leigh McCulloch <351529+leighmcculloch@users.noreply.github.com> Co-authored-by: Jane Wang --- FULL_HELP_DOCS.md | 375 ++++++++++++++---- .../tests/it/integration/hello_world.rs | 5 +- .../soroban-test/tests/it/integration/keys.rs | 9 +- .../tests/it/integration/tx/operations.rs | 98 +++++ cmd/crates/soroban-test/tests/it/main.rs | 2 +- cmd/soroban-cli/src/commands/tx/help.rs | 24 ++ cmd/soroban-cli/src/commands/tx/mod.rs | 28 +- .../src/commands/tx/new/account_merge.rs | 10 +- .../src/commands/tx/new/bump_sequence.rs | 10 +- .../src/commands/tx/new/change_trust.rs | 10 +- .../src/commands/tx/new/create_account.rs | 12 +- .../src/commands/tx/new/manage_data.rs | 10 +- cmd/soroban-cli/src/commands/tx/new/mod.rs | 62 ++- .../src/commands/tx/new/payment.rs | 12 +- .../src/commands/tx/new/set_options.rs | 12 +- .../commands/tx/new/set_trustline_flags.rs | 12 +- .../src/commands/tx/op/add/account_merge.rs | 14 + .../src/commands/tx/op/add/args.rs | 46 +++ .../src/commands/tx/op/add/bump_sequence.rs | 14 + .../src/commands/tx/op/add/change_trust.rs | 14 + .../src/commands/tx/op/add/create_account.rs | 14 + .../src/commands/tx/op/add/manage_data.rs | 14 + cmd/soroban-cli/src/commands/tx/op/add/mod.rs | 65 +++ .../src/commands/tx/op/add/payment.rs | 14 + .../src/commands/tx/op/add/set_options.rs | 14 + .../commands/tx/op/add/set_trustline_flags.rs | 14 + cmd/soroban-cli/src/commands/tx/op/mod.rs | 25 ++ cmd/soroban-cli/src/commands/tx/xdr.rs | 14 +- 28 files changed, 808 insertions(+), 145 deletions(-) create mode 100644 cmd/soroban-cli/src/commands/tx/help.rs create mode 100644 cmd/soroban-cli/src/commands/tx/op/add/account_merge.rs create mode 100644 cmd/soroban-cli/src/commands/tx/op/add/args.rs create mode 100644 cmd/soroban-cli/src/commands/tx/op/add/bump_sequence.rs create mode 100644 cmd/soroban-cli/src/commands/tx/op/add/change_trust.rs create mode 100644 cmd/soroban-cli/src/commands/tx/op/add/create_account.rs create mode 100644 cmd/soroban-cli/src/commands/tx/op/add/manage_data.rs create mode 100644 cmd/soroban-cli/src/commands/tx/op/add/mod.rs create mode 100644 cmd/soroban-cli/src/commands/tx/op/add/payment.rs create mode 100644 cmd/soroban-cli/src/commands/tx/op/add/set_options.rs create mode 100644 cmd/soroban-cli/src/commands/tx/op/add/set_trustline_flags.rs create mode 100644 cmd/soroban-cli/src/commands/tx/op/mod.rs diff --git a/FULL_HELP_DOCS.md b/FULL_HELP_DOCS.md index a755ef18a..61686ab22 100644 --- a/FULL_HELP_DOCS.md +++ b/FULL_HELP_DOCS.md @@ -1455,30 +1455,12 @@ Sign, Simulate, and Send transactions ###### **Subcommands:** -* `simulate` — Simulate a transaction envelope from stdin * `hash` — Calculate the hash of a transaction envelope from stdin -* `sign` — Sign a transaction envelope appending the signature to the envelope -* `send` — Send a transaction envelope to the network * `new` — Create a new transaction - - - -## `stellar tx simulate` - -Simulate a transaction envelope from stdin - -**Usage:** `stellar tx simulate [OPTIONS] --source-account ` - -###### **Options:** - -* `--rpc-url ` — RPC server endpoint -* `--rpc-header ` — RPC Header(s) to include in requests to the RPC provider -* `--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 where transaction originates from. Alias `source`. Can be an identity (--source alice), a public key (--source GDKW...), a muxed account (--source MDA…), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). If `--build-only` or `--sim-only` flags were NOT provided, this key will also be used to sign the final transaction. In that case, trying to sign with public key will fail -* `--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 ` — Location of config directory, default is "." +* `operation` — Manipulate the operations in a transaction, including adding new operations +* `send` — Send a transaction envelope to the network +* `sign` — Sign a transaction envelope appending the signature to the envelope +* `simulate` — Simulate a transaction envelope from stdin @@ -1497,43 +1479,6 @@ Calculate the hash of a transaction envelope from stdin -## `stellar tx sign` - -Sign a transaction envelope appending the signature to the envelope - -**Usage:** `stellar tx sign [OPTIONS]` - -###### **Options:** - -* `--sign-with-key ` — Sign with a local key. Can be an identity (--sign-with-key alice), a secret key (--sign-with-key SC36…), or a seed phrase (--sign-with-key "kite urban…"). If using seed phrase, `--hd-path` defaults to the `0` path -* `--hd-path ` — If using a seed phrase to sign, sets which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` -* `--sign-with-lab` — Sign with https://lab.stellar.org -* `--rpc-url ` — RPC server endpoint -* `--rpc-header ` — RPC Header(s) to include in requests to the RPC provider -* `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server -* `--network ` — Name of network to use from config -* `--global` — Use global config -* `--config-dir ` — Location of config directory, default is "." - - - -## `stellar tx send` - -Send a transaction envelope to the network - -**Usage:** `stellar tx send [OPTIONS]` - -###### **Options:** - -* `--rpc-url ` — RPC server endpoint -* `--rpc-header ` — RPC Header(s) to include in requests to the RPC provider -* `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server -* `--network ` — Name of network to use from config -* `--global` — Use global config -* `--config-dir ` — Location of config directory, default is "." - - - ## `stellar tx new` Create a new transaction @@ -1544,12 +1489,26 @@ Create a new transaction * `account-merge` — Transfers the XLM balance of an account to another account and removes the source account from the ledger * `bump-sequence` — Bumps forward the sequence number of the source account to the given sequence number, invalidating any transaction with a smaller sequence number -* `change-trust` — Creates, updates, or deletes a trustline Learn more about trustlines https://developers.stellar.org/docs/learn/fundamentals/stellar-data-structures/accounts#trustlines +* `change-trust` — Creates, updates, or deletes a trustline +Learn more about trustlines +https://developers.stellar.org/docs/learn/fundamentals/stellar-data-structures/accounts#trustlines * `create-account` — Creates and funds a new account with the specified starting balance -* `manage-data` — Sets, modifies, or deletes a data entry (name/value pair) that is attached to an account Learn more about entries and subentries: https://developers.stellar.org/docs/learn/fundamentals/stellar-data-structures/accounts#subentries +* `manage-data` — Sets, modifies, or deletes a data entry (name/value pair) that is attached to an account +Learn more about entries and subentries: +https://developers.stellar.org/docs/learn/fundamentals/stellar-data-structures/accounts#subentries * `payment` — Sends an amount in a specific asset to a destination account -* `set-options` — Set option for an account such as flags, inflation destination, signers, home domain, and master key weight Learn more about flags: https://developers.stellar.org/docs/learn/glossary#flags Learn more about the home domain: https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0001.md Learn more about signers operations and key weight: https://developers.stellar.org/docs/learn/encyclopedia/security/signatures-multisig#multisig -* `set-trustline-flags` — Allows issuing account to configure authorization and trustline flags to an asset The Asset parameter is of the `TrustLineAsset` type. If you are modifying a trustline to a regular asset (i.e. one in a Code:Issuer format), this is equivalent to the Asset type. If you are modifying a trustline to a pool share, however, this is composed of the liquidity pool's unique ID. Learn more about flags: https://developers.stellar.org/docs/learn/glossary#flags +* `set-options` — Set option for an account such as flags, inflation destination, signers, home domain, and master key weight +Learn more about flags: +https://developers.stellar.org/docs/learn/glossary#flags +Learn more about the home domain: +https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0001.md +Learn more about signers operations and key weight: +https://developers.stellar.org/docs/learn/encyclopedia/security/signatures-multisig#multisig +* `set-trustline-flags` — Allows issuing account to configure authorization and trustline flags to an asset +The Asset parameter is of the `TrustLineAsset` type. If you are modifying a trustline to a regular asset (i.e. one in a Code:Issuer format), this is equivalent to the Asset type. +If you are modifying a trustline to a pool share, however, this is composed of the liquidity pool's unique ID. +Learn more about flags: +https://developers.stellar.org/docs/learn/glossary#flags @@ -1609,7 +1568,9 @@ Bumps forward the sequence number of the source account to the given sequence nu ## `stellar tx new change-trust` -Creates, updates, or deletes a trustline Learn more about trustlines https://developers.stellar.org/docs/learn/fundamentals/stellar-data-structures/accounts#trustlines +Creates, updates, or deletes a trustline +Learn more about trustlines +https://developers.stellar.org/docs/learn/fundamentals/stellar-data-structures/accounts#trustlines **Usage:** `stellar tx new change-trust [OPTIONS] --source-account --line ` @@ -1669,7 +1630,9 @@ Creates and funds a new account with the specified starting balance ## `stellar tx new manage-data` -Sets, modifies, or deletes a data entry (name/value pair) that is attached to an account Learn more about entries and subentries: https://developers.stellar.org/docs/learn/fundamentals/stellar-data-structures/accounts#subentries +Sets, modifies, or deletes a data entry (name/value pair) that is attached to an account +Learn more about entries and subentries: +https://developers.stellar.org/docs/learn/fundamentals/stellar-data-structures/accounts#subentries **Usage:** `stellar tx new manage-data [OPTIONS] --source-account --data-name ` @@ -1728,7 +1691,13 @@ Sends an amount in a specific asset to a destination account ## `stellar tx new set-options` -Set option for an account such as flags, inflation destination, signers, home domain, and master key weight Learn more about flags: https://developers.stellar.org/docs/learn/glossary#flags Learn more about the home domain: https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0001.md Learn more about signers operations and key weight: https://developers.stellar.org/docs/learn/encyclopedia/security/signatures-multisig#multisig +Set option for an account such as flags, inflation destination, signers, home domain, and master key weight +Learn more about flags: +https://developers.stellar.org/docs/learn/glossary#flags +Learn more about the home domain: +https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0001.md +Learn more about signers operations and key weight: +https://developers.stellar.org/docs/learn/encyclopedia/security/signatures-multisig#multisig **Usage:** `stellar tx new set-options [OPTIONS] --source-account ` @@ -1770,7 +1739,11 @@ Set option for an account such as flags, inflation destination, signers, home do ## `stellar tx new set-trustline-flags` -Allows issuing account to configure authorization and trustline flags to an asset The Asset parameter is of the `TrustLineAsset` type. If you are modifying a trustline to a regular asset (i.e. one in a Code:Issuer format), this is equivalent to the Asset type. If you are modifying a trustline to a pool share, however, this is composed of the liquidity pool's unique ID. Learn more about flags: https://developers.stellar.org/docs/learn/glossary#flags +Allows issuing account to configure authorization and trustline flags to an asset +The Asset parameter is of the `TrustLineAsset` type. If you are modifying a trustline to a regular asset (i.e. one in a Code:Issuer format), this is equivalent to the Asset type. +If you are modifying a trustline to a pool share, however, this is composed of the liquidity pool's unique ID. +Learn more about flags: +https://developers.stellar.org/docs/learn/glossary#flags **Usage:** `stellar tx new set-trustline-flags [OPTIONS] --source-account --trustor --asset ` @@ -1802,6 +1775,274 @@ Allows issuing account to configure authorization and trustline flags to an asse +## `stellar tx operation` + +Manipulate the operations in a transaction, including adding new operations + +**Usage:** `stellar tx operation ` + +###### **Subcommands:** + +* `add` — Add Operation to a transaction + + + +## `stellar tx operation add` + +Add Operation to a transaction + +**Usage:** `stellar tx operation add ` + +###### **Subcommands:** + +* `account-merge` — Transfers the XLM balance of an account to another account and removes the source account from the ledger +* `bump-sequence` — Bumps forward the sequence number of the source account to the given sequence number, invalidating any transaction with a smaller sequence number +* `change-trust` — Creates, updates, or deletes a trustline +Learn more about trustlines +https://developers.stellar.org/docs/learn/fundamentals/stellar-data-structures/accounts#trustlines +* `create-account` — Creates and funds a new account with the specified starting balance +* `manage-data` — Sets, modifies, or deletes a data entry (name/value pair) that is attached to an account +Learn more about entries and subentries: +https://developers.stellar.org/docs/learn/fundamentals/stellar-data-structures/accounts#subentries +* `payment` — Sends an amount in a specific asset to a destination account +* `set-options` — Set option for an account such as flags, inflation destination, signers, home domain, and master key weight +Learn more about flags: +https://developers.stellar.org/docs/learn/glossary#flags +Learn more about the home domain: +https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0001.md +Learn more about signers operations and key weight: +https://developers.stellar.org/docs/learn/encyclopedia/security/signatures-multisig#multisig +* `set-trustline-flags` — Allows issuing account to configure authorization and trustline flags to an asset +The Asset parameter is of the `TrustLineAsset` type. If you are modifying a trustline to a regular asset (i.e. one in a Code:Issuer format), this is equivalent to the Asset type. +If you are modifying a trustline to a pool share, however, this is composed of the liquidity pool's unique ID. +Learn more about flags: +https://developers.stellar.org/docs/learn/glossary#flags + + + +## `stellar tx operation add account-merge` + +Transfers the XLM balance of an account to another account and removes the source account from the ledger + +**Usage:** `stellar tx operation add account-merge [OPTIONS] --account ` + +###### **Options:** + +* `--global` — Use global config +* `--config-dir ` — Location of config directory, default is "." +* `--operation-source-account ` — Source account used for the operation +* `--account ` — Muxed Account to merge with, e.g. `GBX...`, 'MBX...' + + + +## `stellar tx operation add bump-sequence` + +Bumps forward the sequence number of the source account to the given sequence number, invalidating any transaction with a smaller sequence number + +**Usage:** `stellar tx operation add bump-sequence [OPTIONS] --bump-to ` + +###### **Options:** + +* `--global` — Use global config +* `--config-dir ` — Location of config directory, default is "." +* `--operation-source-account ` — Source account used for the operation +* `--bump-to ` — Sequence number to bump to + + + +## `stellar tx operation add change-trust` + +Creates, updates, or deletes a trustline +Learn more about trustlines +https://developers.stellar.org/docs/learn/fundamentals/stellar-data-structures/accounts#trustlines + +**Usage:** `stellar tx operation add change-trust [OPTIONS] --line ` + +###### **Options:** + +* `--global` — Use global config +* `--config-dir ` — Location of config directory, default is "." +* `--operation-source-account ` — Source account used for the operation +* `--line ` +* `--limit ` — Limit for the trust line, 0 to remove the trust line + + Default value: `9223372036854775807` + + + +## `stellar tx operation add create-account` + +Creates and funds a new account with the specified starting balance + +**Usage:** `stellar tx operation add create-account [OPTIONS] --destination ` + +###### **Options:** + +* `--global` — Use global config +* `--config-dir ` — Location of config directory, default is "." +* `--operation-source-account ` — Source account used for the operation +* `--destination ` — Account Id to create, e.g. `GBX...` +* `--starting-balance ` — Initial balance in stroops of the account, default 1 XLM + + Default value: `10_000_000` + + + +## `stellar tx operation add manage-data` + +Sets, modifies, or deletes a data entry (name/value pair) that is attached to an account +Learn more about entries and subentries: +https://developers.stellar.org/docs/learn/fundamentals/stellar-data-structures/accounts#subentries + +**Usage:** `stellar tx operation add manage-data [OPTIONS] --data-name ` + +###### **Options:** + +* `--global` — Use global config +* `--config-dir ` — Location of config directory, default is "." +* `--operation-source-account ` — Source account used for the operation +* `--data-name ` — String up to 64 bytes long. If this is a new Name it will add the given name/value pair to the account. If this Name is already present then the associated value will be modified +* `--data-value ` — Up to 64 bytes long hex string If not present then the existing Name will be deleted. If present then this value will be set in the `DataEntry` + + + +## `stellar tx operation add payment` + +Sends an amount in a specific asset to a destination account + +**Usage:** `stellar tx operation add payment [OPTIONS] --destination --amount ` + +###### **Options:** + +* `--global` — Use global config +* `--config-dir ` — Location of config directory, default is "." +* `--operation-source-account ` — Source account used for the operation +* `--destination ` — Account to send to, e.g. `GBX...` +* `--asset ` — Asset to send, default native, e.i. XLM + + Default value: `native` +* `--amount ` — Amount of the aforementioned asset to send. e.g. `10_000_000` (1 XLM) + + + +## `stellar tx operation add set-options` + +Set option for an account such as flags, inflation destination, signers, home domain, and master key weight +Learn more about flags: +https://developers.stellar.org/docs/learn/glossary#flags +Learn more about the home domain: +https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0001.md +Learn more about signers operations and key weight: +https://developers.stellar.org/docs/learn/encyclopedia/security/signatures-multisig#multisig + +**Usage:** `stellar tx operation add set-options [OPTIONS]` + +###### **Options:** + +* `--global` — Use global config +* `--config-dir ` — Location of config directory, default is "." +* `--operation-source-account ` — Source account used for the operation +* `--inflation-dest ` — Account of the inflation destination +* `--master-weight ` — A number from 0-255 (inclusive) representing the weight of the master key. If the weight of the master key is updated to 0, it is effectively disabled +* `--low-threshold ` — A number from 0-255 (inclusive) representing the threshold this account sets on all operations it performs that have a low threshold. https://developers.stellar.org/docs/learn/encyclopedia/security/signatures-multisig#multisig +* `--med-threshold ` — A number from 0-255 (inclusive) representing the threshold this account sets on all operations it performs that have a medium threshold. https://developers.stellar.org/docs/learn/encyclopedia/security/signatures-multisig#multisig +* `--high-threshold ` — A number from 0-255 (inclusive) representing the threshold this account sets on all operations it performs that have a high threshold. https://developers.stellar.org/docs/learn/encyclopedia/security/signatures-multisig#multisig +* `--home-domain ` — Sets the home domain of an account. See https://developers.stellar.org/docs/learn/encyclopedia/network-configuration/federation +* `--signer ` — Add, update, or remove a signer from an account +* `--signer-weight ` — Signer weight is a number from 0-255 (inclusive). The signer is deleted if the weight is 0 +* `--set-required` — When enabled, an issuer must approve an account before that account can hold its asset. https://developers.stellar.org/docs/tokens/control-asset-access#authorization-required-0x1 +* `--set-revocable` — When enabled, an issuer can revoke an existing trustline's authorization, thereby freezing the asset held by an account. https://developers.stellar.org/docs/tokens/control-asset-access#authorization-revocable-0x2 +* `--set-clawback-enabled` — Enables the issuing account to take back (burning) all of the asset. https://developers.stellar.org/docs/tokens/control-asset-access#clawback-enabled-0x8 +* `--set-immutable` — With this setting, none of the other authorization flags (`AUTH_REQUIRED_FLAG`, `AUTH_REVOCABLE_FLAG`) can be set, and the issuing account can't be merged. https://developers.stellar.org/docs/tokens/control-asset-access#authorization-immutable-0x4 +* `--clear-required` +* `--clear-revocable` +* `--clear-immutable` +* `--clear-clawback-enabled` + + + +## `stellar tx operation add set-trustline-flags` + +Allows issuing account to configure authorization and trustline flags to an asset +The Asset parameter is of the `TrustLineAsset` type. If you are modifying a trustline to a regular asset (i.e. one in a Code:Issuer format), this is equivalent to the Asset type. +If you are modifying a trustline to a pool share, however, this is composed of the liquidity pool's unique ID. +Learn more about flags: +https://developers.stellar.org/docs/learn/glossary#flags + +**Usage:** `stellar tx operation add set-trustline-flags [OPTIONS] --trustor --asset ` + +###### **Options:** + +* `--global` — Use global config +* `--config-dir ` — Location of config directory, default is "." +* `--operation-source-account ` — Source account used for the operation +* `--trustor ` — Account to set trustline flags for +* `--asset ` — Asset to set trustline flags for +* `--set-authorize` — Signifies complete authorization allowing an account to transact freely with the asset to make and receive payments and place orders +* `--set-authorize-to-maintain-liabilities` — Denotes limited authorization that allows an account to maintain current orders but not to otherwise transact with the asset +* `--set-trustline-clawback-enabled` — Enables the issuing account to take back (burning) all of the asset. See our section on Clawbacks: https://developers.stellar.org/docs/learn/encyclopedia/transactions-specialized/clawbacks +* `--clear-authorize` +* `--clear-authorize-to-maintain-liabilities` +* `--clear-trustline-clawback-enabled` + + + +## `stellar tx send` + +Send a transaction envelope to the network + +**Usage:** `stellar tx send [OPTIONS]` + +###### **Options:** + +* `--rpc-url ` — RPC server endpoint +* `--rpc-header ` — RPC Header(s) to include in requests to the RPC provider +* `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server +* `--network ` — Name of network to use from config +* `--global` — Use global config +* `--config-dir ` — Location of config directory, default is "." + + + +## `stellar tx sign` + +Sign a transaction envelope appending the signature to the envelope + +**Usage:** `stellar tx sign [OPTIONS]` + +###### **Options:** + +* `--sign-with-key ` — Sign with a local key. Can be an identity (--sign-with-key alice), a secret key (--sign-with-key SC36…), or a seed phrase (--sign-with-key "kite urban…"). If using seed phrase, `--hd-path` defaults to the `0` path +* `--hd-path ` — If using a seed phrase to sign, sets which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` +* `--sign-with-lab` — Sign with https://lab.stellar.org +* `--rpc-url ` — RPC server endpoint +* `--rpc-header ` — RPC Header(s) to include in requests to the RPC provider +* `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server +* `--network ` — Name of network to use from config +* `--global` — Use global config +* `--config-dir ` — Location of config directory, default is "." + + + +## `stellar tx simulate` + +Simulate a transaction envelope from stdin + +**Usage:** `stellar tx simulate [OPTIONS] --source-account ` + +###### **Options:** + +* `--rpc-url ` — RPC server endpoint +* `--rpc-header ` — RPC Header(s) to include in requests to the RPC provider +* `--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 where transaction originates from. Alias `source`. Can be an identity (--source alice), a public key (--source GDKW...), a muxed account (--source MDA…), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). If `--build-only` or `--sim-only` flags were NOT provided, this key will also be used to sign the final transaction. In that case, trying to sign with public key will fail +* `--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 ` — Location of config directory, default is "." + + + ## `stellar xdr` Decode and encode XDR diff --git a/cmd/crates/soroban-test/tests/it/integration/hello_world.rs b/cmd/crates/soroban-test/tests/it/integration/hello_world.rs index fd38c2012..b9ed0196f 100644 --- a/cmd/crates/soroban-test/tests/it/integration/hello_world.rs +++ b/cmd/crates/soroban-test/tests/it/integration/hello_world.rs @@ -1,10 +1,9 @@ -use predicates::boolean::PredicateBooleanExt; use soroban_cli::{ commands::{ contract::{self, fetch}, txn_result::TxnResult, }, - config::{address::Address, locator, secret}, + config::{locator, secret}, }; use soroban_rpc::GetLatestLedgerResponse; use soroban_test::{AssertExt, TestEnv, LOCAL_NETWORK_PASSPHRASE}; @@ -19,7 +18,7 @@ async fn invoke_view_with_non_existent_source_account() { let sandbox = &TestEnv::new(); let id = deploy_hello(sandbox).await; let world = "world"; - let mut cmd = hello_world_cmd(&id, world); + let cmd = hello_world_cmd(&id, world); let res = sandbox.run_cmd_with(cmd, "").await.unwrap(); assert_eq!(res, TxnResult::Res(format!(r#"["Hello",{world:?}]"#))); } diff --git a/cmd/crates/soroban-test/tests/it/integration/keys.rs b/cmd/crates/soroban-test/tests/it/integration/keys.rs index 267a0b095..28723b3a1 100644 --- a/cmd/crates/soroban-test/tests/it/integration/keys.rs +++ b/cmd/crates/soroban-test/tests/it/integration/keys.rs @@ -3,13 +3,12 @@ use soroban_test::AssertExt; use soroban_test::TestEnv; fn pubkey_for_identity(sandbox: &TestEnv, name: &str) -> String { - let output = sandbox + sandbox .new_assert_cmd("keys") .arg("address") .arg(name) .assert() - .stdout_as_str(); - return output; + .stdout_as_str() } #[tokio::test] @@ -61,7 +60,7 @@ async fn overwrite_identity() { "error: An identity with the name 'test2' already exists", )); - assert_eq!(initial_pubkey, pubkey_for_identity(&sandbox, "test2")); + assert_eq!(initial_pubkey, pubkey_for_identity(sandbox, "test2")); sandbox .new_assert_cmd("keys") @@ -72,5 +71,5 @@ async fn overwrite_identity() { .stderr(predicate::str::contains("Overwriting identity 'test2'")) .success(); - assert_ne!(initial_pubkey, pubkey_for_identity(&sandbox, "test2")); + assert_ne!(initial_pubkey, pubkey_for_identity(sandbox, "test2")); } diff --git a/cmd/crates/soroban-test/tests/it/integration/tx/operations.rs b/cmd/crates/soroban-test/tests/it/integration/tx/operations.rs index 9988b2cdd..1ce1f06c9 100644 --- a/cmd/crates/soroban-test/tests/it/integration/tx/operations.rs +++ b/cmd/crates/soroban-test/tests/it/integration/tx/operations.rs @@ -3,6 +3,7 @@ use soroban_cli::{ utils::contract_id_hash_from_asset, xdr::{self, ReadXdr, SequenceNumber}, }; +use soroban_rpc::LedgerEntryResult; use soroban_test::{AssertExt, TestEnv}; use crate::integration::{ @@ -30,6 +31,20 @@ fn new_account(sandbox: &TestEnv, name: &str) -> String { .stdout_as_str() } +fn gen_account_no_fund(sandbox: &TestEnv, name: &str) -> String { + sandbox + .new_assert_cmd("keys") + .args(["generate", "--no-fund", name]) + .assert() + .success(); + sandbox + .new_assert_cmd("keys") + .args(["address", name]) + .assert() + .success() + .stdout_as_str() +} + // returns test and test1 addresses fn setup_accounts(sandbox: &TestEnv) -> (String, String) { (test_address(sandbox), new_account(sandbox, "test1")) @@ -614,3 +629,86 @@ async fn issue_asset(sandbox: &TestEnv, test: &str, asset: &str, limit: u64, ini .assert() .success(); } + +#[tokio::test] +async fn multi_create_accounts() { + let sandbox = &TestEnv::new(); + let client = soroban_rpc::Client::new(&sandbox.rpc_url).unwrap(); + let nums: Vec = (1..=3).collect(); + let mut accounts: Vec<(String, String)> = nums + .iter() + .map(|x| { + let name = format!("test_{x}"); + let address = gen_account_no_fund(sandbox, &name); + (name, address) + }) + .collect(); + let (_, test_99_address) = accounts.pop().unwrap(); + + let input = sandbox + .new_assert_cmd("tx") + .args([ + "new", + "create-account", + "--fee=1000000", + "--build-only", + "--destination", + &test_99_address, + ]) + .assert() + .success() + .stdout_as_str(); + + let final_tx = accounts.iter().fold(input, |tx_env, (_, address)| { + sandbox + .new_assert_cmd("tx") + .args(["op", "add", "create-account", "--destination", address]) + .write_stdin(tx_env.as_bytes()) + .assert() + .success() + .stdout_as_str() + }); + let out = sandbox + .new_assert_cmd("tx") + .arg("send") + .write_stdin( + sandbox + .new_assert_cmd("tx") + .arg("sign") + .arg("--sign-with-key=test") + .write_stdin(final_tx.as_bytes()) + .assert() + .success() + .stdout_as_str() + .as_bytes(), + ) + .assert() + .success() + .stdout_as_str(); + println!("{out}"); + let keys = accounts + .iter() + .map(|(_, address)| { + xdr::LedgerKey::Account(xdr::LedgerKeyAccount { + account_id: address.parse().unwrap(), + }) + }) + .collect::>(); + + let account = client.get_account(&test_99_address).await.unwrap(); + println!("{account:#?}"); + let entries = client.get_ledger_entries(&keys).await.unwrap(); + println!("{entries:#?}"); + entries + .entries + .unwrap() + .iter() + .for_each(|LedgerEntryResult { xdr, .. }| { + let xdr::LedgerEntryData::Account(value) = + xdr::LedgerEntryData::from_xdr_base64(xdr, xdr::Limits::none()).unwrap() + else { + panic!("Expected Account"); + }; + assert_eq!(value.balance, 10_000_000); + }); +} diff --git a/cmd/crates/soroban-test/tests/it/main.rs b/cmd/crates/soroban-test/tests/it/main.rs index 5a0b2a07f..e06c1a47d 100644 --- a/cmd/crates/soroban-test/tests/it/main.rs +++ b/cmd/crates/soroban-test/tests/it/main.rs @@ -3,7 +3,7 @@ mod build; mod config; mod help; mod init; -#[cfg(feature = "it")] +// #[cfg(feature = "it")] mod integration; mod plugin; mod util; diff --git a/cmd/soroban-cli/src/commands/tx/help.rs b/cmd/soroban-cli/src/commands/tx/help.rs new file mode 100644 index 000000000..c3d15d41d --- /dev/null +++ b/cmd/soroban-cli/src/commands/tx/help.rs @@ -0,0 +1,24 @@ +pub const ACCOUNT_MERGE:&str = "Transfers the XLM balance of an account to another account and removes the source account from the ledger"; +pub const BUMP_SEQUENCE: &str = "Bumps forward the sequence number of the source account to the given sequence number, invalidating any transaction with a smaller sequence number"; +pub const CHANGE_TRUST: &str = r"Creates, updates, or deletes a trustline +Learn more about trustlines +https://developers.stellar.org/docs/learn/fundamentals/stellar-data-structures/accounts#trustlines"; + +pub const CREATE_ACCOUNT: &str = + "Creates and funds a new account with the specified starting balance"; +pub const MANAGE_DATA: &str = r"Sets, modifies, or deletes a data entry (name/value pair) that is attached to an account +Learn more about entries and subentries: +https://developers.stellar.org/docs/learn/fundamentals/stellar-data-structures/accounts#subentries"; +pub const PAYMENT: &str = "Sends an amount in a specific asset to a destination account"; +pub const SET_OPTIONS: &str = r"Set option for an account such as flags, inflation destination, signers, home domain, and master key weight +Learn more about flags: +https://developers.stellar.org/docs/learn/glossary#flags +Learn more about the home domain: +https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0001.md +Learn more about signers operations and key weight: +https://developers.stellar.org/docs/learn/encyclopedia/security/signatures-multisig#multisig"; +pub const SET_TRUSTLINE_FLAGS: &str = r"Allows issuing account to configure authorization and trustline flags to an asset +The Asset parameter is of the `TrustLineAsset` type. If you are modifying a trustline to a regular asset (i.e. one in a Code:Issuer format), this is equivalent to the Asset type. +If you are modifying a trustline to a pool share, however, this is composed of the liquidity pool's unique ID. +Learn more about flags: +https://developers.stellar.org/docs/learn/glossary#flags"; diff --git a/cmd/soroban-cli/src/commands/tx/mod.rs b/cmd/soroban-cli/src/commands/tx/mod.rs index c0390f92e..d9fd79faf 100644 --- a/cmd/soroban-cli/src/commands/tx/mod.rs +++ b/cmd/soroban-cli/src/commands/tx/mod.rs @@ -2,7 +2,9 @@ use super::global; pub mod args; pub mod hash; +pub mod help; pub mod new; +pub mod op; pub mod send; pub mod sign; pub mod simulate; @@ -12,17 +14,20 @@ pub use args::Args; #[derive(Debug, clap::Subcommand)] pub enum Cmd { - /// Simulate a transaction envelope from stdin - Simulate(simulate::Cmd), /// Calculate the hash of a transaction envelope from stdin Hash(hash::Cmd), - /// Sign a transaction envelope appending the signature to the envelope - Sign(sign::Cmd), - /// Send a transaction envelope to the network - Send(send::Cmd), /// Create a new transaction #[command(subcommand)] New(new::Cmd), + /// Manipulate the operations in a transaction, including adding new operations + #[command(subcommand, visible_alias = "op")] + Operation(op::Cmd), + /// Send a transaction envelope to the network + Send(send::Cmd), + /// Sign a transaction envelope appending the signature to the envelope + Sign(sign::Cmd), + /// Simulate a transaction envelope from stdin + Simulate(simulate::Cmd), } #[derive(thiserror::Error, Debug)] @@ -32,21 +37,24 @@ pub enum Error { #[error(transparent)] New(#[from] new::Error), #[error(transparent)] - Simulate(#[from] simulate::Error), + Op(#[from] op::Error), + #[error(transparent)] + Send(#[from] send::Error), #[error(transparent)] Sign(#[from] sign::Error), #[error(transparent)] - Send(#[from] send::Error), + Simulate(#[from] simulate::Error), } impl Cmd { pub async fn run(&self, global_args: &global::Args) -> Result<(), Error> { match self { - Cmd::Simulate(cmd) => cmd.run(global_args).await?, Cmd::Hash(cmd) => cmd.run(global_args)?, Cmd::New(cmd) => cmd.run(global_args).await?, - Cmd::Sign(cmd) => cmd.run(global_args).await?, + Cmd::Operation(cmd) => cmd.run(global_args)?, Cmd::Send(cmd) => cmd.run(global_args).await?, + Cmd::Sign(cmd) => cmd.run(global_args).await?, + Cmd::Simulate(cmd) => cmd.run(global_args).await?, }; Ok(()) } diff --git a/cmd/soroban-cli/src/commands/tx/new/account_merge.rs b/cmd/soroban-cli/src/commands/tx/new/account_merge.rs index ce01f5e1f..0d07fce91 100644 --- a/cmd/soroban-cli/src/commands/tx/new/account_merge.rs +++ b/cmd/soroban-cli/src/commands/tx/new/account_merge.rs @@ -7,13 +7,19 @@ use crate::{commands::tx, xdr}; pub struct Cmd { #[command(flatten)] pub tx: tx::Args, + #[clap(flatten)] + pub op: Args, +} + +#[derive(Debug, clap::Args, Clone)] +pub struct Args { /// Muxed Account to merge with, e.g. `GBX...`, 'MBX...' #[arg(long)] pub account: xdr::MuxedAccount, } -impl From<&Cmd> for xdr::OperationBody { - fn from(cmd: &Cmd) -> Self { +impl From<&Args> for xdr::OperationBody { + fn from(cmd: &Args) -> Self { xdr::OperationBody::AccountMerge(cmd.account.clone()) } } diff --git a/cmd/soroban-cli/src/commands/tx/new/bump_sequence.rs b/cmd/soroban-cli/src/commands/tx/new/bump_sequence.rs index dfb521f23..ff04e96a0 100644 --- a/cmd/soroban-cli/src/commands/tx/new/bump_sequence.rs +++ b/cmd/soroban-cli/src/commands/tx/new/bump_sequence.rs @@ -7,13 +7,19 @@ use crate::{commands::tx, xdr}; pub struct Cmd { #[command(flatten)] pub tx: tx::Args, + #[clap(flatten)] + pub op: Args, +} + +#[derive(Debug, clap::Args, Clone)] +pub struct Args { /// Sequence number to bump to #[arg(long)] pub bump_to: i64, } -impl From<&Cmd> for xdr::OperationBody { - fn from(cmd: &Cmd) -> Self { +impl From<&Args> for xdr::OperationBody { + fn from(cmd: &Args) -> Self { xdr::OperationBody::BumpSequence(xdr::BumpSequenceOp { bump_to: cmd.bump_to.into(), }) diff --git a/cmd/soroban-cli/src/commands/tx/new/change_trust.rs b/cmd/soroban-cli/src/commands/tx/new/change_trust.rs index da9acc8cf..2013db75b 100644 --- a/cmd/soroban-cli/src/commands/tx/new/change_trust.rs +++ b/cmd/soroban-cli/src/commands/tx/new/change_trust.rs @@ -7,6 +7,12 @@ use crate::{commands::tx, tx::builder, xdr}; pub struct Cmd { #[command(flatten)] pub tx: tx::Args, + #[clap(flatten)] + pub op: Args, +} + +#[derive(Debug, clap::Args, Clone)] +pub struct Args { #[arg(long)] pub line: builder::Asset, /// Limit for the trust line, 0 to remove the trust line @@ -14,8 +20,8 @@ pub struct Cmd { pub limit: i64, } -impl From<&Cmd> for xdr::OperationBody { - fn from(cmd: &Cmd) -> Self { +impl From<&Args> for xdr::OperationBody { + fn from(cmd: &Args) -> Self { let line = match cmd.line.0.clone() { xdr::Asset::CreditAlphanum4(asset) => xdr::ChangeTrustAsset::CreditAlphanum4(asset), xdr::Asset::CreditAlphanum12(asset) => xdr::ChangeTrustAsset::CreditAlphanum12(asset), diff --git a/cmd/soroban-cli/src/commands/tx/new/create_account.rs b/cmd/soroban-cli/src/commands/tx/new/create_account.rs index 2826439e9..acdfd6e2d 100644 --- a/cmd/soroban-cli/src/commands/tx/new/create_account.rs +++ b/cmd/soroban-cli/src/commands/tx/new/create_account.rs @@ -7,16 +7,22 @@ use crate::{commands::tx, tx::builder, xdr}; pub struct Cmd { #[command(flatten)] pub tx: tx::Args, + #[clap(flatten)] + pub op: Args, +} + +#[derive(Debug, clap::Args, Clone)] +pub struct Args { /// Account Id to create, e.g. `GBX...` - #[arg(long)] + #[arg(long, alias = "dest")] pub destination: xdr::AccountId, /// Initial balance in stroops of the account, default 1 XLM #[arg(long, default_value = "10_000_000")] pub starting_balance: builder::Amount, } -impl From<&Cmd> for xdr::OperationBody { - fn from(cmd: &Cmd) -> Self { +impl From<&Args> for xdr::OperationBody { + fn from(cmd: &Args) -> Self { xdr::OperationBody::CreateAccount(xdr::CreateAccountOp { destination: cmd.destination.clone(), starting_balance: cmd.starting_balance.into(), diff --git a/cmd/soroban-cli/src/commands/tx/new/manage_data.rs b/cmd/soroban-cli/src/commands/tx/new/manage_data.rs index 4f4ab480d..30e9a36fd 100644 --- a/cmd/soroban-cli/src/commands/tx/new/manage_data.rs +++ b/cmd/soroban-cli/src/commands/tx/new/manage_data.rs @@ -7,6 +7,12 @@ use crate::{commands::tx, xdr}; pub struct Cmd { #[command(flatten)] pub tx: tx::Args, + #[clap(flatten)] + pub op: Args, +} + +#[derive(Debug, clap::Args, Clone)] +pub struct Args { /// String up to 64 bytes long. /// If this is a new Name it will add the given name/value pair to the account. /// If this Name is already present then the associated value will be modified. @@ -19,8 +25,8 @@ pub struct Cmd { pub data_value: Option>, } -impl From<&Cmd> for xdr::OperationBody { - fn from(cmd: &Cmd) -> Self { +impl From<&Args> for xdr::OperationBody { + fn from(cmd: &Args) -> Self { let data_value = cmd.data_value.clone().map(Into::into); let data_name = cmd.data_name.clone().into(); xdr::OperationBody::ManageData(xdr::ManageDataOp { diff --git a/cmd/soroban-cli/src/commands/tx/new/mod.rs b/cmd/soroban-cli/src/commands/tx/new/mod.rs index e5923f4ec..24c25995f 100644 --- a/cmd/soroban-cli/src/commands/tx/new/mod.rs +++ b/cmd/soroban-cli/src/commands/tx/new/mod.rs @@ -2,47 +2,33 @@ use clap::Parser; use super::global; -mod account_merge; -mod bump_sequence; -mod change_trust; -mod create_account; -mod manage_data; -mod payment; -mod set_options; -mod set_trustline_flags; +pub mod account_merge; +pub mod bump_sequence; +pub mod change_trust; +pub mod create_account; +pub mod manage_data; +pub mod payment; +pub mod set_options; +pub mod set_trustline_flags; #[derive(Debug, Parser)] #[allow(clippy::doc_markdown)] pub enum Cmd { - /// Transfers the XLM balance of an account to another account and removes the source account from the ledger + #[command(about = super::help::ACCOUNT_MERGE)] AccountMerge(account_merge::Cmd), - /// Bumps forward the sequence number of the source account to the given sequence number, invalidating any transaction with a smaller sequence number + #[command(about = super::help::BUMP_SEQUENCE)] BumpSequence(bump_sequence::Cmd), - /// Creates, updates, or deletes a trustline - /// Learn more about trustlines - /// https://developers.stellar.org/docs/learn/fundamentals/stellar-data-structures/accounts#trustlines + #[command(about = super::help::CHANGE_TRUST)] ChangeTrust(change_trust::Cmd), - /// Creates and funds a new account with the specified starting balance + #[command(about = super::help::CREATE_ACCOUNT)] CreateAccount(create_account::Cmd), - /// Sets, modifies, or deletes a data entry (name/value pair) that is attached to an account - /// Learn more about entries and subentries: - /// https://developers.stellar.org/docs/learn/fundamentals/stellar-data-structures/accounts#subentries + #[command(about = super::help::MANAGE_DATA)] ManageData(manage_data::Cmd), - /// Sends an amount in a specific asset to a destination account + #[command(about = super::help::PAYMENT)] Payment(payment::Cmd), - /// Set option for an account such as flags, inflation destination, signers, home domain, and master key weight - /// Learn more about flags: - /// https://developers.stellar.org/docs/learn/glossary#flags - /// Learn more about the home domain: - /// https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0001.md - /// Learn more about signers operations and key weight: - /// https://developers.stellar.org/docs/learn/encyclopedia/security/signatures-multisig#multisig + #[command(about = super::help::SET_OPTIONS)] SetOptions(set_options::Cmd), - /// Allows issuing account to configure authorization and trustline flags to an asset - /// The Asset parameter is of the `TrustLineAsset` type. If you are modifying a trustline to a regular asset (i.e. one in a Code:Issuer format), this is equivalent to the Asset type. - /// If you are modifying a trustline to a pool share, however, this is composed of the liquidity pool's unique ID. - /// Learn more about flags: - /// https://developers.stellar.org/docs/learn/glossary#flags + #[command(about = super::help::SET_TRUSTLINE_FLAGS)] SetTrustlineFlags(set_trustline_flags::Cmd), } @@ -55,14 +41,14 @@ pub enum Error { impl Cmd { pub async fn run(&self, global_args: &global::Args) -> Result<(), Error> { match self { - Cmd::AccountMerge(cmd) => cmd.tx.handle_and_print(cmd, global_args).await, - Cmd::BumpSequence(cmd) => cmd.tx.handle_and_print(cmd, global_args).await, - Cmd::ChangeTrust(cmd) => cmd.tx.handle_and_print(cmd, global_args).await, - Cmd::CreateAccount(cmd) => cmd.tx.handle_and_print(cmd, global_args).await, - Cmd::ManageData(cmd) => cmd.tx.handle_and_print(cmd, global_args).await, - Cmd::Payment(cmd) => cmd.tx.handle_and_print(cmd, global_args).await, - Cmd::SetOptions(cmd) => cmd.tx.handle_and_print(cmd, global_args).await, - Cmd::SetTrustlineFlags(cmd) => cmd.tx.handle_and_print(cmd, global_args).await, + Cmd::AccountMerge(cmd) => cmd.tx.handle_and_print(&cmd.op, global_args).await, + Cmd::BumpSequence(cmd) => cmd.tx.handle_and_print(&cmd.op, global_args).await, + Cmd::ChangeTrust(cmd) => cmd.tx.handle_and_print(&cmd.op, global_args).await, + Cmd::CreateAccount(cmd) => cmd.tx.handle_and_print(&cmd.op, global_args).await, + Cmd::ManageData(cmd) => cmd.tx.handle_and_print(&cmd.op, global_args).await, + Cmd::Payment(cmd) => cmd.tx.handle_and_print(&cmd.op, global_args).await, + Cmd::SetOptions(cmd) => cmd.tx.handle_and_print(&cmd.op, global_args).await, + Cmd::SetTrustlineFlags(cmd) => cmd.tx.handle_and_print(&cmd.op, global_args).await, }?; Ok(()) } diff --git a/cmd/soroban-cli/src/commands/tx/new/payment.rs b/cmd/soroban-cli/src/commands/tx/new/payment.rs index 3cebfa532..683b2731c 100644 --- a/cmd/soroban-cli/src/commands/tx/new/payment.rs +++ b/cmd/soroban-cli/src/commands/tx/new/payment.rs @@ -7,8 +7,14 @@ use crate::{commands::tx, tx::builder, xdr}; pub struct Cmd { #[command(flatten)] pub tx: tx::Args, + #[clap(flatten)] + pub op: Args, +} + +#[derive(Debug, clap::Args, Clone)] +pub struct Args { /// Account to send to, e.g. `GBX...` - #[arg(long)] + #[arg(long, visible_alias = "dest")] pub destination: xdr::MuxedAccount, /// Asset to send, default native, e.i. XLM #[arg(long, default_value = "native")] @@ -18,8 +24,8 @@ pub struct Cmd { pub amount: builder::Amount, } -impl From<&Cmd> for xdr::OperationBody { - fn from(cmd: &Cmd) -> Self { +impl From<&Args> for xdr::OperationBody { + fn from(cmd: &Args) -> Self { xdr::OperationBody::Payment(xdr::PaymentOp { destination: cmd.destination.clone(), asset: cmd.asset.clone().into(), diff --git a/cmd/soroban-cli/src/commands/tx/new/set_options.rs b/cmd/soroban-cli/src/commands/tx/new/set_options.rs index 69cd10745..77c7c0895 100644 --- a/cmd/soroban-cli/src/commands/tx/new/set_options.rs +++ b/cmd/soroban-cli/src/commands/tx/new/set_options.rs @@ -3,11 +3,17 @@ use clap::{command, Parser}; use crate::{commands::tx, xdr}; #[derive(Parser, Debug, Clone)] -#[allow(clippy::struct_excessive_bools, clippy::doc_markdown)] #[group(skip)] pub struct Cmd { #[command(flatten)] pub tx: tx::Args, + #[clap(flatten)] + pub op: Args, +} + +#[derive(Debug, clap::Args, Clone)] +#[allow(clippy::struct_excessive_bools, clippy::doc_markdown)] +pub struct Args { #[arg(long)] /// Account of the inflation destination. pub inflation_dest: Option, @@ -61,8 +67,8 @@ pub struct Cmd { pub clear_clawback_enabled: bool, } -impl From<&Cmd> for xdr::OperationBody { - fn from(cmd: &Cmd) -> Self { +impl From<&Args> for xdr::OperationBody { + fn from(cmd: &Args) -> Self { let mut set_flags = None; let mut set_flag = |flag: xdr::AccountFlags| { *set_flags.get_or_insert(0) |= flag as u32; diff --git a/cmd/soroban-cli/src/commands/tx/new/set_trustline_flags.rs b/cmd/soroban-cli/src/commands/tx/new/set_trustline_flags.rs index d9b70ecbd..482dd3a90 100644 --- a/cmd/soroban-cli/src/commands/tx/new/set_trustline_flags.rs +++ b/cmd/soroban-cli/src/commands/tx/new/set_trustline_flags.rs @@ -2,12 +2,18 @@ use clap::{command, Parser}; use crate::{commands::tx, tx::builder, xdr}; -#[allow(clippy::struct_excessive_bools, clippy::doc_markdown)] #[derive(Parser, Debug, Clone)] #[group(skip)] pub struct Cmd { #[command(flatten)] pub tx: tx::Args, + #[clap(flatten)] + pub op: Args, +} + +#[derive(Debug, clap::Args, Clone)] +#[allow(clippy::struct_excessive_bools, clippy::doc_markdown)] +pub struct Args { /// Account to set trustline flags for #[arg(long)] pub trustor: xdr::AccountId, @@ -32,8 +38,8 @@ pub struct Cmd { pub clear_trustline_clawback_enabled: bool, } -impl From<&Cmd> for xdr::OperationBody { - fn from(cmd: &Cmd) -> Self { +impl From<&Args> for xdr::OperationBody { + fn from(cmd: &Args) -> Self { let mut set_flags = 0; let mut set_flag = |flag: xdr::TrustLineFlags| set_flags |= flag as u32; diff --git a/cmd/soroban-cli/src/commands/tx/op/add/account_merge.rs b/cmd/soroban-cli/src/commands/tx/op/add/account_merge.rs new file mode 100644 index 000000000..bd643c199 --- /dev/null +++ b/cmd/soroban-cli/src/commands/tx/op/add/account_merge.rs @@ -0,0 +1,14 @@ +use clap::{command, Parser}; + +use std::fmt::Debug; + +use super::new; + +#[derive(Parser, Debug, Clone)] +#[group(skip)] +pub struct Cmd { + #[command(flatten)] + pub args: super::args::Args, + #[command(flatten)] + pub op: new::account_merge::Args, +} diff --git a/cmd/soroban-cli/src/commands/tx/op/add/args.rs b/cmd/soroban-cli/src/commands/tx/op/add/args.rs new file mode 100644 index 000000000..f1858e0b0 --- /dev/null +++ b/cmd/soroban-cli/src/commands/tx/op/add/args.rs @@ -0,0 +1,46 @@ +use super::xdr::add_op; +use crate::{ + config::{address, locator}, + xdr, +}; + +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error(transparent)] + Address(#[from] address::Error), + #[error(transparent)] + TxXdr(#[from] super::xdr::Error), +} + +#[derive(Debug, clap::Args, Clone)] +#[group(skip)] +pub struct Args { + #[clap(flatten)] + pub locator: locator::Args, + /// Source account used for the operation + #[arg( + long, + visible_alias = "op-source", + env = "STELLAR_OPERATION_SOURCE_ACCOUNT" + )] + pub operation_source_account: Option, +} + +impl Args { + pub fn add_op( + &self, + op_body: impl Into, + tx_env: xdr::TransactionEnvelope, + ) -> Result { + let source_account = self + .operation_source_account + .as_ref() + .map(|a| a.resolve_muxed_account(&self.locator, None)) + .transpose()?; + let op = xdr::Operation { + source_account, + body: op_body.into(), + }; + Ok(add_op(tx_env, op)?) + } +} diff --git a/cmd/soroban-cli/src/commands/tx/op/add/bump_sequence.rs b/cmd/soroban-cli/src/commands/tx/op/add/bump_sequence.rs new file mode 100644 index 000000000..907d8d2d6 --- /dev/null +++ b/cmd/soroban-cli/src/commands/tx/op/add/bump_sequence.rs @@ -0,0 +1,14 @@ +use clap::{command, Parser}; + +use std::fmt::Debug; + +use super::new; + +#[derive(Parser, Debug, Clone)] +#[group(skip)] +pub struct Cmd { + #[command(flatten)] + pub args: super::args::Args, + #[command(flatten)] + pub op: new::bump_sequence::Args, +} diff --git a/cmd/soroban-cli/src/commands/tx/op/add/change_trust.rs b/cmd/soroban-cli/src/commands/tx/op/add/change_trust.rs new file mode 100644 index 000000000..af9afae1b --- /dev/null +++ b/cmd/soroban-cli/src/commands/tx/op/add/change_trust.rs @@ -0,0 +1,14 @@ +use clap::{command, Parser}; + +use std::fmt::Debug; + +use super::new; + +#[derive(Parser, Debug, Clone)] +#[group(skip)] +pub struct Cmd { + #[command(flatten)] + pub args: super::args::Args, + #[command(flatten)] + pub op: new::change_trust::Args, +} diff --git a/cmd/soroban-cli/src/commands/tx/op/add/create_account.rs b/cmd/soroban-cli/src/commands/tx/op/add/create_account.rs new file mode 100644 index 000000000..e30ff20a1 --- /dev/null +++ b/cmd/soroban-cli/src/commands/tx/op/add/create_account.rs @@ -0,0 +1,14 @@ +use clap::{command, Parser}; + +use std::fmt::Debug; + +use super::new; + +#[derive(Parser, Debug, Clone)] +#[group(skip)] +pub struct Cmd { + #[command(flatten)] + pub args: super::args::Args, + #[command(flatten)] + pub op: new::create_account::Args, +} diff --git a/cmd/soroban-cli/src/commands/tx/op/add/manage_data.rs b/cmd/soroban-cli/src/commands/tx/op/add/manage_data.rs new file mode 100644 index 000000000..962233a84 --- /dev/null +++ b/cmd/soroban-cli/src/commands/tx/op/add/manage_data.rs @@ -0,0 +1,14 @@ +use clap::{command, Parser}; + +use std::fmt::Debug; + +use super::new; + +#[derive(Parser, Debug, Clone)] +#[group(skip)] +pub struct Cmd { + #[command(flatten)] + pub args: super::args::Args, + #[command(flatten)] + pub op: new::manage_data::Args, +} diff --git a/cmd/soroban-cli/src/commands/tx/op/add/mod.rs b/cmd/soroban-cli/src/commands/tx/op/add/mod.rs new file mode 100644 index 000000000..b94fc74ce --- /dev/null +++ b/cmd/soroban-cli/src/commands/tx/op/add/mod.rs @@ -0,0 +1,65 @@ +use clap::Parser; + +use super::super::{global, help, xdr::tx_envelope_from_stdin}; +use crate::xdr::WriteXdr; + +pub(crate) use super::super::{new, xdr}; + +mod account_merge; +mod args; +mod bump_sequence; +mod change_trust; +mod create_account; +mod manage_data; +mod payment; +mod set_options; +mod set_trustline_flags; + +#[derive(Debug, Parser)] +#[allow(clippy::doc_markdown)] +pub enum Cmd { + #[command(about = help::ACCOUNT_MERGE)] + AccountMerge(account_merge::Cmd), + #[command(about = help::BUMP_SEQUENCE)] + BumpSequence(bump_sequence::Cmd), + #[command(about = help::CHANGE_TRUST)] + ChangeTrust(change_trust::Cmd), + #[command(about = help::CREATE_ACCOUNT)] + CreateAccount(create_account::Cmd), + #[command(about = help::MANAGE_DATA)] + ManageData(manage_data::Cmd), + #[command(about = help::PAYMENT)] + Payment(payment::Cmd), + #[command(about = help::SET_OPTIONS)] + SetOptions(set_options::Cmd), + #[command(about = help::SET_TRUSTLINE_FLAGS)] + SetTrustlineFlags(set_trustline_flags::Cmd), +} + +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error(transparent)] + Args(#[from] args::Error), + #[error(transparent)] + TxXdr(#[from] super::super::xdr::Error), + #[error(transparent)] + Xdr(#[from] crate::xdr::Error), +} + +impl Cmd { + pub fn run(&self, _: &global::Args) -> Result<(), Error> { + let tx_env = tx_envelope_from_stdin()?; + let res = match self { + Cmd::AccountMerge(cmd) => cmd.args.add_op(&cmd.op, tx_env), + Cmd::BumpSequence(cmd) => cmd.args.add_op(&cmd.op, tx_env), + Cmd::ChangeTrust(cmd) => cmd.args.add_op(&cmd.op, tx_env), + Cmd::CreateAccount(cmd) => cmd.args.add_op(&cmd.op, tx_env), + Cmd::ManageData(cmd) => cmd.args.add_op(&cmd.op, tx_env), + Cmd::Payment(cmd) => cmd.args.add_op(&cmd.op, tx_env), + Cmd::SetOptions(cmd) => cmd.args.add_op(&cmd.op, tx_env), + Cmd::SetTrustlineFlags(cmd) => cmd.args.add_op(&cmd.op, tx_env), + }?; + println!("{}", res.to_xdr_base64(crate::xdr::Limits::none())?); + Ok(()) + } +} diff --git a/cmd/soroban-cli/src/commands/tx/op/add/payment.rs b/cmd/soroban-cli/src/commands/tx/op/add/payment.rs new file mode 100644 index 000000000..d8146c91a --- /dev/null +++ b/cmd/soroban-cli/src/commands/tx/op/add/payment.rs @@ -0,0 +1,14 @@ +use clap::{command, Parser}; + +use std::fmt::Debug; + +use super::new; + +#[derive(Parser, Debug, Clone)] +#[group(skip)] +pub struct Cmd { + #[command(flatten)] + pub args: super::args::Args, + #[command(flatten)] + pub op: new::payment::Args, +} diff --git a/cmd/soroban-cli/src/commands/tx/op/add/set_options.rs b/cmd/soroban-cli/src/commands/tx/op/add/set_options.rs new file mode 100644 index 000000000..75b43124a --- /dev/null +++ b/cmd/soroban-cli/src/commands/tx/op/add/set_options.rs @@ -0,0 +1,14 @@ +use clap::{command, Parser}; + +use std::fmt::Debug; + +use super::new; + +#[derive(Parser, Debug, Clone)] +#[group(skip)] +pub struct Cmd { + #[command(flatten)] + pub args: super::args::Args, + #[command(flatten)] + pub op: new::set_options::Args, +} diff --git a/cmd/soroban-cli/src/commands/tx/op/add/set_trustline_flags.rs b/cmd/soroban-cli/src/commands/tx/op/add/set_trustline_flags.rs new file mode 100644 index 000000000..8ffee7a7b --- /dev/null +++ b/cmd/soroban-cli/src/commands/tx/op/add/set_trustline_flags.rs @@ -0,0 +1,14 @@ +use clap::{command, Parser}; + +use std::fmt::Debug; + +use super::new; + +#[derive(Parser, Debug, Clone)] +#[group(skip)] +pub struct Cmd { + #[command(flatten)] + pub args: super::args::Args, + #[command(flatten)] + pub op: new::set_trustline_flags::Args, +} diff --git a/cmd/soroban-cli/src/commands/tx/op/mod.rs b/cmd/soroban-cli/src/commands/tx/op/mod.rs new file mode 100644 index 000000000..9c38ecfd3 --- /dev/null +++ b/cmd/soroban-cli/src/commands/tx/op/mod.rs @@ -0,0 +1,25 @@ +use super::global; + +pub mod add; + +#[derive(Debug, clap::Subcommand)] +pub enum Cmd { + /// Add Operation to a transaction + #[command(subcommand)] + Add(add::Cmd), +} + +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error(transparent)] + Add(#[from] add::Error), +} + +impl Cmd { + pub fn run(&self, global_args: &global::Args) -> Result<(), Error> { + match self { + Cmd::Add(cmd) => cmd.run(global_args)?, + }; + Ok(()) + } +} diff --git a/cmd/soroban-cli/src/commands/tx/xdr.rs b/cmd/soroban-cli/src/commands/tx/xdr.rs index fcacce9ac..0e6e253e6 100644 --- a/cmd/soroban-cli/src/commands/tx/xdr.rs +++ b/cmd/soroban-cli/src/commands/tx/xdr.rs @@ -3,7 +3,9 @@ use std::{ path::PathBuf, }; -use crate::xdr::{Limits, ReadXdr, Transaction, TransactionEnvelope, TransactionV1Envelope}; +use crate::xdr::{ + Limits, Operation, ReadXdr, Transaction, TransactionEnvelope, TransactionV1Envelope, +}; #[derive(Debug, thiserror::Error)] pub enum Error { @@ -17,6 +19,8 @@ pub enum Error { Io(#[from] std::io::Error), #[error("only transaction v1 is supported")] OnlyTransactionV1Supported, + #[error("too many operations, limited to 100 operations in a transaction")] + TooManyOperations, } pub fn tx_envelope_from_stdin() -> Result { @@ -36,3 +40,11 @@ pub fn unwrap_envelope_v1(tx_env: TransactionEnvelope) -> Result Result { + let mut tx = unwrap_envelope_v1(tx_env)?; + let mut ops = tx.operations.to_vec(); + ops.push(op); + tx.operations = ops.try_into().map_err(|_| Error::TooManyOperations)?; + Ok(tx.into()) +}