diff --git a/.github/workflows/binaries.yml b/.github/workflows/binaries.yml index c008cc7b4..d913cf23d 100644 --- a/.github/workflows/binaries.yml +++ b/.github/workflows/binaries.yml @@ -132,12 +132,13 @@ jobs: $Env:Path += ";C:\Users\$Env:UserName\AppData\Local\Programs\Inno Setup 6" $Env:STELLAR_CLI_VERSION = "${{ env.VERSION }}" ISCC.exe installer.iss + mv Output/stellar-installer.exe ${{ env.STELLAR_CLI_INSTALLER }} - name: Upload Artifact uses: actions/upload-artifact@v4 with: name: ${{ env.STELLAR_CLI_INSTALLER }} - path: Output/stellar-installer.exe + path: ${{ env.STELLAR_CLI_INSTALLER }} - name: Build provenance for attestation (release only) if: github.event_name == 'release' diff --git a/.github/workflows/bindings-ts.yml b/.github/workflows/bindings-ts.yml index 957661c4c..9b5f767ac 100644 --- a/.github/workflows/bindings-ts.yml +++ b/.github/workflows/bindings-ts.yml @@ -24,6 +24,9 @@ jobs: --health-timeout 5s --health-retries 50 steps: + - uses: actions/setup-node@v4 + with: + node-version: '22.x' - uses: actions/checkout@v4 - uses: actions/cache@v4 with: diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 595e6e817..f3c9b1920 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -36,7 +36,7 @@ jobs: fail-fast: false matrix: check: [advisories, bans, licenses, sources] - continue-on-error: ${{ matrix.check == 'advisories' || matrix.check == 'bans' || matrix.check == 'licenses' }} + continue-on-error: ${{ matrix.check == 'advisories' }} steps: - uses: actions/checkout@v3 - uses: EmbarkStudios/cargo-deny-action@b01e7a8cfb1f496c52d77361e84c1840d8246393 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 diff --git a/Cargo.lock b/Cargo.lock index 45fc99742..bf7893a4b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1636,9 +1636,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -1646,9 +1646,9 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" @@ -1663,9 +1663,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-lite" @@ -1697,9 +1697,9 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", @@ -1708,21 +1708,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", @@ -4288,7 +4288,7 @@ dependencies = [ [[package]] name = "soroban-cli" -version = "22.0.0" +version = "22.0.1" dependencies = [ "assert_cmd", "assert_fs", @@ -4454,7 +4454,7 @@ dependencies = [ [[package]] name = "soroban-hello" -version = "0.0.0" +version = "22.0.1" [[package]] name = "soroban-ledger-snapshot" @@ -4525,7 +4525,7 @@ dependencies = [ [[package]] name = "soroban-spec-json" -version = "22.0.0" +version = "22.0.1" dependencies = [ "pretty_assertions", "serde", @@ -4555,7 +4555,7 @@ dependencies = [ [[package]] name = "soroban-spec-tools" -version = "22.0.0" +version = "22.0.1" dependencies = [ "base64 0.21.7", "ethnum", @@ -4573,7 +4573,7 @@ dependencies = [ [[package]] name = "soroban-spec-typescript" -version = "22.0.0" +version = "22.0.1" dependencies = [ "base64 0.21.7", "heck 0.4.1", @@ -4594,12 +4594,11 @@ dependencies = [ [[package]] name = "soroban-test" -version = "22.0.0" +version = "22.0.1" dependencies = [ "assert_cmd", "assert_fs", "ed25519-dalek", - "either", "fs_extra", "hex", "home", @@ -4667,18 +4666,18 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "stellar-bye" -version = "0.0.0" +version = "22.0.1" [[package]] name = "stellar-cli" -version = "22.0.0" +version = "22.0.1" dependencies = [ "soroban-cli", ] [[package]] name = "stellar-ledger" -version = "22.0.0" +version = "22.0.1" dependencies = [ "async-trait", "bollard", @@ -5025,42 +5024,42 @@ dependencies = [ [[package]] name = "test_constructor" -version = "0.0.0" +version = "22.0.1" dependencies = [ "soroban-sdk", ] [[package]] name = "test_custom_account" -version = "0.0.0" +version = "22.0.1" dependencies = [ "soroban-sdk", ] [[package]] name = "test_custom_types" -version = "0.0.0" +version = "22.0.1" dependencies = [ "soroban-sdk", ] [[package]] name = "test_hello_world" -version = "0.0.0" +version = "22.0.1" dependencies = [ "soroban-sdk", ] [[package]] name = "test_swap" -version = "0.0.0" +version = "22.0.1" dependencies = [ "soroban-sdk", ] [[package]] name = "test_token" -version = "0.0.0" +version = "22.0.1" dependencies = [ "soroban-sdk", "soroban-token-sdk", @@ -5068,7 +5067,7 @@ dependencies = [ [[package]] name = "test_udt" -version = "22.0.0" +version = "22.0.1" dependencies = [ "soroban-sdk", ] diff --git a/Cargo.toml b/Cargo.toml index d2572e9c0..cbfe6dd3c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,24 +19,24 @@ exclude = [ ] [workspace.package] -version = "22.0.0" +version = "22.0.1" rust-version = "1.81.0" # Dependencies located in this repo: [workspace.dependencies.soroban-cli] -version = "=22.0.0" +version = "=22.0.1" path = "cmd/soroban-cli" [workspace.dependencies.soroban-spec-json] -version = "=22.0.0" +version = "=22.0.1" path = "./cmd/crates/soroban-spec-json" [workspace.dependencies.soroban-spec-typescript] -version = "22.0.0" +version = "22.0.1" path = "./cmd/crates/soroban-spec-typescript" [workspace.dependencies.soroban-spec-tools] -version = "22.0.0" +version = "22.0.1" path = "./cmd/crates/soroban-spec-tools" # Dependencies from the rs-stellar-xdr repo: diff --git a/FULL_HELP_DOCS.md b/FULL_HELP_DOCS.md index 1ba366ac0..fc2a84335 100644 --- a/FULL_HELP_DOCS.md +++ b/FULL_HELP_DOCS.md @@ -258,6 +258,7 @@ Generate code client bindings for a contract * `json` — Generate Json Bindings * `rust` — Generate Rust bindings * `typescript` — Generate a TypeScript / JavaScript package +* `python` — Generate Python bindings @@ -289,20 +290,28 @@ Generate Rust bindings Generate a TypeScript / JavaScript package -**Usage:** `stellar contract bindings typescript [OPTIONS] --output-dir --contract-id ` +**Usage:** `stellar contract bindings typescript [OPTIONS] --output-dir ` ###### **Options:** -* `--wasm ` — Path to optional wasm binary +* `--wasm ` — Path to wasm file on local filesystem. You must either include this OR `--contract-id` +* `--contract-id ` — A contract ID/address on a network (if no network settings provided, Testnet will be assumed). You must either include this OR `--wasm` * `--output-dir ` — Where to place generated project * `--overwrite` — Whether to overwrite output directory if it already exists -* `--contract-id ` — The contract ID/address on the network -* `--global` — Use global config -* `--config-dir ` — Location of config directory, default is "." * `--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 contract bindings python` + +Generate Python bindings + +**Usage:** `stellar contract bindings python` @@ -1446,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 @@ -1488,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 @@ -1535,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 @@ -1600,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 ` @@ -1654,13 +1624,15 @@ Creates and funds a new account with the specified starting balance * `--destination ` — Account Id to create, e.g. `GBX...` * `--starting-balance ` — Initial balance in stroops of the account, default 1 XLM - Default value: `10000000` + Default value: `10_000_000` ## `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 ` @@ -1681,7 +1653,7 @@ Sets, modifies, or deletes a data entry (name/value pair) that is attached to an * `--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 "." -* `--data-name ` — Line to change, either 4 or 12 alphanumeric characters, or "native" if not specified +* `--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` @@ -1713,13 +1685,19 @@ Sends an amount in a specific asset to a destination account * `--asset ` — Asset to send, default native, e.i. XLM Default value: `native` -* `--amount ` — Amount of the aforementioned asset to send +* `--amount ` — Amount of the aforementioned asset to send. e.g. `10_000_000` (1 XLM) ## `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 ` @@ -1761,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 ` @@ -1793,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/Makefile b/Makefile index 92cdacd73..7aa1832ba 100644 --- a/Makefile +++ b/Makefile @@ -71,9 +71,11 @@ publish: typescript-bindings-fixtures: build-test-wasms cargo run -- contract bindings typescript \ --wasm ./target/wasm32-unknown-unknown/test-wasms/test_custom_types.wasm \ - --contract-id CBYMYMSDF6FBDNCFJCRC7KMO4REYFPOH2U4N7FXI3GJO6YXNCQ43CDSK \ - --network futurenet \ --output-dir ./cmd/crates/soroban-spec-typescript/fixtures/test_custom_types \ + --overwrite && \ + cargo run -- contract bindings typescript \ + --wasm ./target/wasm32-unknown-unknown/test-wasms/test_constructor.wasm \ + --output-dir ./cmd/crates/soroban-spec-typescript/fixtures/test_constructor \ --overwrite diff --git a/cmd/crates/soroban-spec-typescript/fixtures/test_constructor/.gitignore b/cmd/crates/soroban-spec-typescript/fixtures/test_constructor/.gitignore new file mode 100644 index 000000000..72aae85fa --- /dev/null +++ b/cmd/crates/soroban-spec-typescript/fixtures/test_constructor/.gitignore @@ -0,0 +1,2 @@ +node_modules/ +out/ diff --git a/cmd/crates/soroban-spec-typescript/fixtures/test_constructor/README.md b/cmd/crates/soroban-spec-typescript/fixtures/test_constructor/README.md new file mode 100644 index 000000000..28bfd61c9 --- /dev/null +++ b/cmd/crates/soroban-spec-typescript/fixtures/test_constructor/README.md @@ -0,0 +1,54 @@ +# test_constructor JS + +JS library for interacting with [Soroban](https://soroban.stellar.org/) smart contract `test_constructor` via Soroban RPC. + +This library was automatically generated by Soroban CLI using a command similar to: + +```bash +soroban contract bindings ts \ + --rpc-url INSERT_RPC_URL_HERE \ + --network-passphrase "INSERT_NETWORK_PASSPHRASE_HERE" \ + --contract-id INSERT_CONTRACT_ID_HERE \ + --output-dir ./path/to/test_constructor +``` + +The network passphrase and contract ID are exported from [index.ts](./src/index.ts) in the `networks` constant. If you are the one who generated this library and you know that this contract is also deployed to other networks, feel free to update `networks` with other valid options. This will help your contract consumers use this library more easily. + +# To publish or not to publish + +This library is suitable for publishing to NPM. You can publish it to NPM using the `npm publish` command. + +But you don't need to publish this library to NPM to use it. You can add it to your project's `package.json` using a file path: + +```json +"dependencies": { + "test_constructor": "./path/to/this/folder" +} +``` + +However, we've actually encountered [frustration](https://github.com/stellar/soroban-example-dapp/pull/117#discussion_r1232873560) using local libraries with NPM in this way. Though it seems a bit messy, we suggest generating the library directly to your `node_modules` folder automatically after each install by using a `postinstall` script. We've had the least trouble with this approach. NPM will automatically remove what it sees as erroneous directories during the `install` step, and then regenerate them when it gets to your `postinstall` step, which will keep the library up-to-date with your contract. + +```json +"scripts": { + "postinstall": "soroban contract bindings ts --rpc-url INSERT_RPC_URL_HERE --network-passphrase \"INSERT_NETWORK_PASSPHRASE_HERE\" --id INSERT_CONTRACT_ID_HERE --name test_constructor" +} +``` + +Obviously you need to adjust the above command based on the actual command you used to generate the library. + +# Use it + +Now that you have your library up-to-date and added to your project, you can import it in a file and see inline documentation for all of its exported methods: + +```js +import { Contract, networks } from "test_constructor" + +const contract = new Contract({ + ...networks.futurenet, // for example; check which networks this library exports + rpcUrl: '...', // use your own, or find one for testing at https://soroban.stellar.org/docs/reference/rpc#public-rpc-providers +}) + +contract.| +``` + +As long as your editor is configured to show JavaScript/TypeScript documentation, you can pause your typing at that `|` to get a list of all exports and inline-documentation for each. It exports a separate [async](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function) function for each method in the smart contract, with documentation for each generated from the comments the contract's author included in the original source code. diff --git a/cmd/crates/soroban-spec-typescript/fixtures/test_constructor/package.json b/cmd/crates/soroban-spec-typescript/fixtures/test_constructor/package.json new file mode 100644 index 000000000..8db466c05 --- /dev/null +++ b/cmd/crates/soroban-spec-typescript/fixtures/test_constructor/package.json @@ -0,0 +1,17 @@ +{ + "version": "0.0.0", + "name": "test_constructor", + "type": "module", + "exports": "./dist/index.js", + "typings": "dist/index.d.ts", + "scripts": { + "build": "tsc" + }, + "dependencies": { + "@stellar/stellar-sdk": "13.0.0", + "buffer": "6.0.3" + }, + "devDependencies": { + "typescript": "^5.6.2" + } +} diff --git a/cmd/crates/soroban-spec-typescript/fixtures/test_constructor/src/index.ts b/cmd/crates/soroban-spec-typescript/fixtures/test_constructor/src/index.ts new file mode 100644 index 000000000..f416e5a24 --- /dev/null +++ b/cmd/crates/soroban-spec-typescript/fixtures/test_constructor/src/index.ts @@ -0,0 +1,90 @@ +import { Buffer } from "buffer"; +import { Address } from '@stellar/stellar-sdk'; +import { + AssembledTransaction, + Client as ContractClient, + ClientOptions as ContractClientOptions, + MethodOptions, + Result, + Spec as ContractSpec, +} from '@stellar/stellar-sdk/contract'; +import type { + u32, + i32, + u64, + i64, + u128, + i128, + u256, + i256, + Option, + Typepoint, + Duration, +} from '@stellar/stellar-sdk/contract'; +export * from '@stellar/stellar-sdk' +export * as contract from '@stellar/stellar-sdk/contract' +export * as rpc from '@stellar/stellar-sdk/rpc' + +if (typeof window !== 'undefined') { + //@ts-ignore Buffer exists + window.Buffer = window.Buffer || Buffer; +} + + + + +export const Errors = { + +} + +export interface Client { + /** + * Construct and simulate a counter transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. + * Counter value + */ + counter: (options?: { + /** + * The fee to pay for the transaction. Default: BASE_FEE + */ + fee?: number; + + /** + * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT + */ + timeoutInSeconds?: number; + + /** + * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true + */ + simulate?: boolean; + }) => Promise> + +} +export class Client extends ContractClient { + static async deploy( + /** Constructor/Initialization Args for the contract's `__constructor` method */ + {counter}: {counter: u32}, + /** Options for initalizing a Client as well as for calling a method, with extras specific to deploying. */ + options: MethodOptions & + Omit & { + /** The hash of the Wasm blob, which must already be installed on-chain. */ + wasmHash: Buffer | string; + /** Salt used to generate the contract's ID. Passed through to {@link Operation.createCustomContract}. Default: random. */ + salt?: Buffer | Uint8Array; + /** The format used to decode `wasmHash`, if it's provided as a string. */ + format?: "hex" | "base64"; + } + ): Promise> { + return ContractClient.deploy({counter}, options) + } + constructor(public readonly options: ContractClientOptions) { + super( + new ContractSpec([ "AAAAAAAAABNFeGFtcGxlIGNvbnN0cnVjdG9yAAAAAA1fX2NvbnN0cnVjdG9yAAAAAAAAAQAAAAAAAAAHY291bnRlcgAAAAAEAAAAAA==", + "AAAAAAAAAA1Db3VudGVyIHZhbHVlAAAAAAAAB2NvdW50ZXIAAAAAAAAAAAEAAAAE" ]), + options + ) + } + public readonly fromJSON = { + counter: this.txFromJSON + } +} \ No newline at end of file diff --git a/cmd/crates/soroban-spec-typescript/fixtures/test_constructor/tsconfig.json b/cmd/crates/soroban-spec-typescript/fixtures/test_constructor/tsconfig.json new file mode 100644 index 000000000..acac14220 --- /dev/null +++ b/cmd/crates/soroban-spec-typescript/fixtures/test_constructor/tsconfig.json @@ -0,0 +1,98 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "ESNext", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ + // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + /* Modules */ + "module": "NodeNext", /* Specify what module code is generated. */ + // "rootDir": "./", /* Specify the root folder within your source files. */ + "moduleResolution": "nodenext", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + /* Emit */ + "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + "outDir": "./dist", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + // "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + // "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ + /* Type Checking */ + // "strict": true, /* Enable all strict type-checking options. */ + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + }, + "include": [ + "src/*" + ] +} \ No newline at end of file diff --git a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/README.md b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/README.md index 03f87f30b..5f90613a7 100644 --- a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/README.md +++ b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/README.md @@ -6,9 +6,9 @@ This library was automatically generated by Soroban CLI using a command similar ```bash soroban contract bindings ts \ - --rpc-url https://rpc-futurenet.stellar.org:443 \ - --network-passphrase "Test SDF Future Network ; October 2022" \ - --contract-id CBYMYMSDF6FBDNCFJCRC7KMO4REYFPOH2U4N7FXI3GJO6YXNCQ43CDSK \ + --rpc-url INSERT_RPC_URL_HERE \ + --network-passphrase "INSERT_NETWORK_PASSPHRASE_HERE" \ + --contract-id INSERT_CONTRACT_ID_HERE \ --output-dir ./path/to/test_custom_types ``` @@ -30,7 +30,7 @@ However, we've actually encountered [frustration](https://github.com/stellar/sor ```json "scripts": { - "postinstall": "soroban contract bindings ts --rpc-url https://rpc-futurenet.stellar.org:443 --network-passphrase \"Test SDF Future Network ; October 2022\" --id CBYMYMSDF6FBDNCFJCRC7KMO4REYFPOH2U4N7FXI3GJO6YXNCQ43CDSK --name test_custom_types" + "postinstall": "soroban contract bindings ts --rpc-url INSERT_RPC_URL_HERE --network-passphrase \"INSERT_NETWORK_PASSPHRASE_HERE\" --id INSERT_CONTRACT_ID_HERE --name test_custom_types" } ``` diff --git a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/index.d.ts b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/index.d.ts deleted file mode 100644 index cd888cc04..000000000 --- a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/index.d.ts +++ /dev/null @@ -1,628 +0,0 @@ -import { Buffer } from "buffer"; -import { AssembledTransaction, Client as ContractClient, ClientOptions as ContractClientOptions, Result } from '@stellar/stellar-sdk/contract'; -import type { u32, i32, i64, u128, i128, u256, i256, Option } from '@stellar/stellar-sdk/contract'; -export * from '@stellar/stellar-sdk'; -export * as contract from '@stellar/stellar-sdk/contract'; -export * as rpc from '@stellar/stellar-sdk/rpc'; -export declare const networks: { - readonly futurenet: { - readonly networkPassphrase: "Test SDF Future Network ; October 2022"; - readonly contractId: "CBYMYMSDF6FBDNCFJCRC7KMO4REYFPOH2U4N7FXI3GJO6YXNCQ43CDSK"; - }; -}; -/** - * This is from the rust doc above the struct Test - */ -export interface Test { - a: u32; - b: boolean; - c: string; -} -export type SimpleEnum = { - tag: "First"; - values: void; -} | { - tag: "Second"; - values: void; -} | { - tag: "Third"; - values: void; -}; -export declare enum RoyalCard { - Jack = 11, - Queen = 12, - King = 13 -} -export type TupleStruct = readonly [Test, SimpleEnum]; -export type ComplexEnum = { - tag: "Struct"; - values: readonly [Test]; -} | { - tag: "Tuple"; - values: readonly [TupleStruct]; -} | { - tag: "Enum"; - values: readonly [SimpleEnum]; -} | { - tag: "Asset"; - values: readonly [string, i128]; -} | { - tag: "Void"; - values: void; -}; -export declare const Errors: { - /** - * Please provide an odd number - */ - 1: { - message: string; - }; -}; -export interface Client { - /** - * Construct and simulate a hello transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - hello: ({ hello }: { - hello: string; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>; - /** - * Construct and simulate a woid transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - woid: (options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>; - /** - * Construct and simulate a val transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - val: (options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>; - /** - * Construct and simulate a u32_fail_on_even transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - u32_fail_on_even: ({ u32_ }: { - u32_: u32; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>>; - /** - * Construct and simulate a u32_ transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - u32_: ({ u32_ }: { - u32_: u32; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>; - /** - * Construct and simulate a i32_ transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - i32_: ({ i32_ }: { - i32_: i32; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>; - /** - * Construct and simulate a i64_ transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - i64_: ({ i64_ }: { - i64_: i64; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>; - /** - * Construct and simulate a strukt_hel transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - * Example contract method which takes a struct - */ - strukt_hel: ({ strukt }: { - strukt: Test; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>>; - /** - * Construct and simulate a strukt transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - strukt: ({ strukt }: { - strukt: Test; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>; - /** - * Construct and simulate a simple transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - simple: ({ simple }: { - simple: SimpleEnum; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>; - /** - * Construct and simulate a complex transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - complex: ({ complex }: { - complex: ComplexEnum; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>; - /** - * Construct and simulate a addresse transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - addresse: ({ addresse }: { - addresse: string; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>; - /** - * Construct and simulate a bytes transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - bytes: ({ bytes }: { - bytes: Buffer; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>; - /** - * Construct and simulate a bytes_n transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - bytes_n: ({ bytes_n }: { - bytes_n: Buffer; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>; - /** - * Construct and simulate a card transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - card: ({ card }: { - card: RoyalCard; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>; - /** - * Construct and simulate a boolean transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - boolean: ({ boolean }: { - boolean: boolean; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>; - /** - * Construct and simulate a not transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - * Negates a boolean value - */ - not: ({ boolean }: { - boolean: boolean; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>; - /** - * Construct and simulate a i128 transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - i128: ({ i128 }: { - i128: i128; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>; - /** - * Construct and simulate a u128 transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - u128: ({ u128 }: { - u128: u128; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>; - /** - * Construct and simulate a multi_args transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - multi_args: ({ a, b }: { - a: u32; - b: boolean; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>; - /** - * Construct and simulate a map transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - map: ({ map }: { - map: Map; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>>; - /** - * Construct and simulate a vec transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - vec: ({ vec }: { - vec: Array; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>>; - /** - * Construct and simulate a tuple transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - tuple: ({ tuple }: { - tuple: readonly [string, u32]; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>; - /** - * Construct and simulate a option transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - * Example of an optional argument - */ - option: ({ option }: { - option: Option; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>>; - /** - * Construct and simulate a u256 transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - u256: ({ u256 }: { - u256: u256; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>; - /** - * Construct and simulate a i256 transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - i256: ({ i256 }: { - i256: i256; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>; - /** - * Construct and simulate a string transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - string: ({ string }: { - string: string; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>; - /** - * Construct and simulate a tuple_strukt transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - tuple_strukt: ({ tuple_strukt }: { - tuple_strukt: TupleStruct; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>; -} -export declare class Client extends ContractClient { - readonly options: ContractClientOptions; - constructor(options: ContractClientOptions); - readonly fromJSON: { - hello: (json: string) => AssembledTransaction; - woid: (json: string) => AssembledTransaction; - val: (json: string) => AssembledTransaction; - u32_fail_on_even: (json: string) => AssembledTransaction>; - u32_: (json: string) => AssembledTransaction; - i32_: (json: string) => AssembledTransaction; - i64_: (json: string) => AssembledTransaction; - strukt_hel: (json: string) => AssembledTransaction; - strukt: (json: string) => AssembledTransaction; - simple: (json: string) => AssembledTransaction; - complex: (json: string) => AssembledTransaction; - addresse: (json: string) => AssembledTransaction; - bytes: (json: string) => AssembledTransaction; - bytes_n: (json: string) => AssembledTransaction; - card: (json: string) => AssembledTransaction; - boolean: (json: string) => AssembledTransaction; - not: (json: string) => AssembledTransaction; - i128: (json: string) => AssembledTransaction; - u128: (json: string) => AssembledTransaction; - multi_args: (json: string) => AssembledTransaction; - map: (json: string) => AssembledTransaction>; - vec: (json: string) => AssembledTransaction; - tuple: (json: string) => AssembledTransaction; - option: (json: string) => AssembledTransaction>; - u256: (json: string) => AssembledTransaction; - i256: (json: string) => AssembledTransaction; - string: (json: string) => AssembledTransaction; - tuple_strukt: (json: string) => AssembledTransaction; - }; -} diff --git a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/index.js b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/index.js deleted file mode 100644 index 4286b2a68..000000000 --- a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/index.js +++ /dev/null @@ -1,97 +0,0 @@ -import { Buffer } from "buffer"; -import { Client as ContractClient, Spec as ContractSpec, } from '@stellar/stellar-sdk/contract'; -export * from '@stellar/stellar-sdk'; -export * as contract from '@stellar/stellar-sdk/contract'; -export * as rpc from '@stellar/stellar-sdk/rpc'; -if (typeof window !== 'undefined') { - //@ts-ignore Buffer exists - window.Buffer = window.Buffer || Buffer; -} -export const networks = { - futurenet: { - networkPassphrase: "Test SDF Future Network ; October 2022", - contractId: "CBYMYMSDF6FBDNCFJCRC7KMO4REYFPOH2U4N7FXI3GJO6YXNCQ43CDSK", - } -}; -export var RoyalCard; -(function (RoyalCard) { - RoyalCard[RoyalCard["Jack"] = 11] = "Jack"; - RoyalCard[RoyalCard["Queen"] = 12] = "Queen"; - RoyalCard[RoyalCard["King"] = 13] = "King"; -})(RoyalCard || (RoyalCard = {})); -export const Errors = { - /** - * Please provide an odd number - */ - 1: { message: "NumberMustBeOdd" } -}; -export class Client extends ContractClient { - options; - constructor(options) { - super(new ContractSpec(["AAAAAQAAAC9UaGlzIGlzIGZyb20gdGhlIHJ1c3QgZG9jIGFib3ZlIHRoZSBzdHJ1Y3QgVGVzdAAAAAAAAAAABFRlc3QAAAADAAAAAAAAAAFhAAAAAAAABAAAAAAAAAABYgAAAAAAAAEAAAAAAAAAAWMAAAAAAAAR", - "AAAAAgAAAAAAAAAAAAAAClNpbXBsZUVudW0AAAAAAAMAAAAAAAAAAAAAAAVGaXJzdAAAAAAAAAAAAAAAAAAABlNlY29uZAAAAAAAAAAAAAAAAAAFVGhpcmQAAAA=", - "AAAAAwAAAAAAAAAAAAAACVJveWFsQ2FyZAAAAAAAAAMAAAAAAAAABEphY2sAAAALAAAAAAAAAAVRdWVlbgAAAAAAAAwAAAAAAAAABEtpbmcAAAAN", - "AAAAAQAAAAAAAAAAAAAAC1R1cGxlU3RydWN0AAAAAAIAAAAAAAAAATAAAAAAAAfQAAAABFRlc3QAAAAAAAAAATEAAAAAAAfQAAAAClNpbXBsZUVudW0AAA==", - "AAAAAgAAAAAAAAAAAAAAC0NvbXBsZXhFbnVtAAAAAAUAAAABAAAAAAAAAAZTdHJ1Y3QAAAAAAAEAAAfQAAAABFRlc3QAAAABAAAAAAAAAAVUdXBsZQAAAAAAAAEAAAfQAAAAC1R1cGxlU3RydWN0AAAAAAEAAAAAAAAABEVudW0AAAABAAAH0AAAAApTaW1wbGVFbnVtAAAAAAABAAAAAAAAAAVBc3NldAAAAAAAAAIAAAATAAAACwAAAAAAAAAAAAAABFZvaWQ=", - "AAAABAAAAAAAAAAAAAAABUVycm9yAAAAAAAAAQAAABxQbGVhc2UgcHJvdmlkZSBhbiBvZGQgbnVtYmVyAAAAD051bWJlck11c3RCZU9kZAAAAAAB", - "AAAAAAAAAAAAAAAFaGVsbG8AAAAAAAABAAAAAAAAAAVoZWxsbwAAAAAAABEAAAABAAAAEQ==", - "AAAAAAAAAAAAAAAEd29pZAAAAAAAAAAA", - "AAAAAAAAAAAAAAADdmFsAAAAAAAAAAABAAAAAA==", - "AAAAAAAAAAAAAAAQdTMyX2ZhaWxfb25fZXZlbgAAAAEAAAAAAAAABHUzMl8AAAAEAAAAAQAAA+kAAAAEAAAAAw==", - "AAAAAAAAAAAAAAAEdTMyXwAAAAEAAAAAAAAABHUzMl8AAAAEAAAAAQAAAAQ=", - "AAAAAAAAAAAAAAAEaTMyXwAAAAEAAAAAAAAABGkzMl8AAAAFAAAAAQAAAAU=", - "AAAAAAAAAAAAAAAEaTY0XwAAAAEAAAAAAAAABGk2NF8AAAAHAAAAAQAAAAc=", - "AAAAAAAAACxFeGFtcGxlIGNvbnRyYWN0IG1ldGhvZCB3aGljaCB0YWtlcyBhIHN0cnVjdAAAAApzdHJ1a3RfaGVsAAAAAAABAAAAAAAAAAZzdHJ1a3QAAAAAB9AAAAAEVGVzdAAAAAEAAAPqAAAAEQ==", - "AAAAAAAAAAAAAAAGc3RydWt0AAAAAAABAAAAAAAAAAZzdHJ1a3QAAAAAB9AAAAAEVGVzdAAAAAEAAAfQAAAABFRlc3Q=", - "AAAAAAAAAAAAAAAGc2ltcGxlAAAAAAABAAAAAAAAAAZzaW1wbGUAAAAAB9AAAAAKU2ltcGxlRW51bQAAAAAAAQAAB9AAAAAKU2ltcGxlRW51bQAA", - "AAAAAAAAAAAAAAAHY29tcGxleAAAAAABAAAAAAAAAAdjb21wbGV4AAAAB9AAAAALQ29tcGxleEVudW0AAAAAAQAAB9AAAAALQ29tcGxleEVudW0A", - "AAAAAAAAAAAAAAAIYWRkcmVzc2UAAAABAAAAAAAAAAhhZGRyZXNzZQAAABMAAAABAAAAEw==", - "AAAAAAAAAAAAAAAFYnl0ZXMAAAAAAAABAAAAAAAAAAVieXRlcwAAAAAAAA4AAAABAAAADg==", - "AAAAAAAAAAAAAAAHYnl0ZXNfbgAAAAABAAAAAAAAAAdieXRlc19uAAAAA+4AAAAJAAAAAQAAA+4AAAAJ", - "AAAAAAAAAAAAAAAEY2FyZAAAAAEAAAAAAAAABGNhcmQAAAfQAAAACVJveWFsQ2FyZAAAAAAAAAEAAAfQAAAACVJveWFsQ2FyZAAAAA==", - "AAAAAAAAAAAAAAAHYm9vbGVhbgAAAAABAAAAAAAAAAdib29sZWFuAAAAAAEAAAABAAAAAQ==", - "AAAAAAAAABdOZWdhdGVzIGEgYm9vbGVhbiB2YWx1ZQAAAAADbm90AAAAAAEAAAAAAAAAB2Jvb2xlYW4AAAAAAQAAAAEAAAAB", - "AAAAAAAAAAAAAAAEaTEyOAAAAAEAAAAAAAAABGkxMjgAAAALAAAAAQAAAAs=", - "AAAAAAAAAAAAAAAEdTEyOAAAAAEAAAAAAAAABHUxMjgAAAAKAAAAAQAAAAo=", - "AAAAAAAAAAAAAAAKbXVsdGlfYXJncwAAAAAAAgAAAAAAAAABYQAAAAAAAAQAAAAAAAAAAWIAAAAAAAABAAAAAQAAAAQ=", - "AAAAAAAAAAAAAAADbWFwAAAAAAEAAAAAAAAAA21hcAAAAAPsAAAABAAAAAEAAAABAAAD7AAAAAQAAAAB", - "AAAAAAAAAAAAAAADdmVjAAAAAAEAAAAAAAAAA3ZlYwAAAAPqAAAABAAAAAEAAAPqAAAABA==", - "AAAAAAAAAAAAAAAFdHVwbGUAAAAAAAABAAAAAAAAAAV0dXBsZQAAAAAAA+0AAAACAAAAEQAAAAQAAAABAAAD7QAAAAIAAAARAAAABA==", - "AAAAAAAAAB9FeGFtcGxlIG9mIGFuIG9wdGlvbmFsIGFyZ3VtZW50AAAAAAZvcHRpb24AAAAAAAEAAAAAAAAABm9wdGlvbgAAAAAD6AAAAAQAAAABAAAD6AAAAAQ=", - "AAAAAAAAAAAAAAAEdTI1NgAAAAEAAAAAAAAABHUyNTYAAAAMAAAAAQAAAAw=", - "AAAAAAAAAAAAAAAEaTI1NgAAAAEAAAAAAAAABGkyNTYAAAANAAAAAQAAAA0=", - "AAAAAAAAAAAAAAAGc3RyaW5nAAAAAAABAAAAAAAAAAZzdHJpbmcAAAAAABAAAAABAAAAEA==", - "AAAAAAAAAAAAAAAMdHVwbGVfc3RydWt0AAAAAQAAAAAAAAAMdHVwbGVfc3RydWt0AAAH0AAAAAtUdXBsZVN0cnVjdAAAAAABAAAH0AAAAAtUdXBsZVN0cnVjdAA="]), options); - this.options = options; - } - fromJSON = { - hello: (this.txFromJSON), - woid: (this.txFromJSON), - val: (this.txFromJSON), - u32_fail_on_even: (this.txFromJSON), - u32_: (this.txFromJSON), - i32_: (this.txFromJSON), - i64_: (this.txFromJSON), - strukt_hel: (this.txFromJSON), - strukt: (this.txFromJSON), - simple: (this.txFromJSON), - complex: (this.txFromJSON), - addresse: (this.txFromJSON), - bytes: (this.txFromJSON), - bytes_n: (this.txFromJSON), - card: (this.txFromJSON), - boolean: (this.txFromJSON), - not: (this.txFromJSON), - i128: (this.txFromJSON), - u128: (this.txFromJSON), - multi_args: (this.txFromJSON), - map: (this.txFromJSON), - vec: (this.txFromJSON), - tuple: (this.txFromJSON), - option: (this.txFromJSON), - u256: (this.txFromJSON), - i256: (this.txFromJSON), - string: (this.txFromJSON), - tuple_strukt: (this.txFromJSON) - }; -} diff --git a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/package-lock.json b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/package-lock.json deleted file mode 100644 index a4e3759e2..000000000 --- a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/package-lock.json +++ /dev/null @@ -1,355 +0,0 @@ -{ - "name": "test_custom_types", - "version": "0.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "test_custom_types", - "version": "0.0.0", - "dependencies": { - "@stellar/stellar-sdk": "13.0.0", - "buffer": "6.0.3" - }, - "devDependencies": { - "typescript": "^5.6.2" - } - }, - "node_modules/@stellar/js-xdr": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@stellar/js-xdr/-/js-xdr-3.1.2.tgz", - "integrity": "sha512-VVolPL5goVEIsvuGqDc5uiKxV03lzfWdvYg1KikvwheDmTBO68CKDji3bAZ/kppZrx5iTA8z3Ld5yuytcvhvOQ==", - "license": "Apache-2.0" - }, - "node_modules/@stellar/stellar-base": { - "version": "13.0.1", - "resolved": "https://registry.npmjs.org/@stellar/stellar-base/-/stellar-base-13.0.1.tgz", - "integrity": "sha512-Xbd12mc9Oj/130Tv0URmm3wXG77XMshZtZ2yNCjqX5ZbMD5IYpbBs3DVCteLU/4SLj/Fnmhh1dzhrQXnk4r+pQ==", - "license": "Apache-2.0", - "dependencies": { - "@stellar/js-xdr": "^3.1.2", - "base32.js": "^0.1.0", - "bignumber.js": "^9.1.2", - "buffer": "^6.0.3", - "sha.js": "^2.3.6", - "tweetnacl": "^1.0.3" - }, - "optionalDependencies": { - "sodium-native": "^4.3.0" - } - }, - "node_modules/@stellar/stellar-sdk": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/@stellar/stellar-sdk/-/stellar-sdk-13.0.0.tgz", - "integrity": "sha512-+wvmKi+XWwu27nLYTM17EgBdpbKohEkOfCIK4XKfsI4WpMXAqvnqSm98i9h5dAblNB+w8BJqzGs1JY0PtTGm4A==", - "license": "Apache-2.0", - "dependencies": { - "@stellar/stellar-base": "^13.0.1", - "axios": "^1.7.7", - "bignumber.js": "^9.1.2", - "eventsource": "^2.0.2", - "feaxios": "^0.0.20", - "randombytes": "^2.1.0", - "toml": "^3.0.0", - "urijs": "^1.19.1" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "license": "MIT" - }, - "node_modules/axios": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", - "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", - "license": "MIT", - "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "node_modules/base32.js": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/base32.js/-/base32.js-0.1.0.tgz", - "integrity": "sha512-n3TkB02ixgBOhTvANakDb4xaMXnYUVkNoRFJjQflcqMQhyEKxEHdj3E6N8t8sUQ0mjH/3/JxzlXuz3ul/J90pQ==", - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/base64-js": { - "version": "1.5.1", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/bignumber.js": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", - "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==", - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/buffer": { - "version": "6.0.3", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "license": "MIT", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/eventsource": { - "version": "2.0.2", - "license": "MIT", - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/feaxios": { - "version": "0.0.20", - "resolved": "https://registry.npmjs.org/feaxios/-/feaxios-0.0.20.tgz", - "integrity": "sha512-g3hm2YDNffNxA3Re3Hd8ahbpmDee9Fv1Pb1C/NoWsjY7mtD8nyNeJytUzn+DK0Hyl9o6HppeWOrtnqgmhOYfWA==", - "license": "MIT", - "dependencies": { - "is-retry-allowed": "^3.0.0" - } - }, - "node_modules/follow-redirects": { - "version": "1.15.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", - "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "license": "MIT", - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/form-data": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", - "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", - "license": "MIT", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "license": "ISC" - }, - "node_modules/is-retry-allowed": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-3.0.0.tgz", - "integrity": "sha512-9xH0xvoggby+u0uGF7cZXdrutWiBiaFG8ZT4YFPXL8NzkyAwX3AKGLeFQLvzDpM430+nDFBZ1LHkie/8ocL06A==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/node-gyp-build": { - "version": "4.8.3", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.3.tgz", - "integrity": "sha512-EMS95CMJzdoSKoIiXo8pxKoL8DYxwIZXYlLmgPb8KUv794abpnLK6ynsCAWNliOjREKruYKdzbh76HHYUHX7nw==", - "license": "MIT", - "optional": true, - "bin": { - "node-gyp-build": "bin.js", - "node-gyp-build-optional": "optional.js", - "node-gyp-build-test": "build-test.js" - } - }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "license": "MIT" - }, - "node_modules/randombytes": { - "version": "2.1.0", - "license": "MIT", - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "license": "(MIT AND BSD-3-Clause)", - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - }, - "bin": { - "sha.js": "bin.js" - } - }, - "node_modules/sodium-native": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/sodium-native/-/sodium-native-4.3.1.tgz", - "integrity": "sha512-YdP64gAdpIKHfL4ttuX4aIfjeunh9f+hNeQJpE9C8UMndB3zkgZ7YmmGT4J2+v6Ibyp6Wem8D1TcSrtdW0bqtg==", - "license": "MIT", - "optional": true, - "dependencies": { - "node-gyp-build": "^4.8.0" - } - }, - "node_modules/toml": { - "version": "3.0.0", - "license": "MIT" - }, - "node_modules/tweetnacl": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", - "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", - "license": "Unlicense" - }, - "node_modules/typescript": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", - "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/urijs": { - "version": "1.19.11", - "license": "MIT" - } - } -} diff --git a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/src/index.ts b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/src/index.ts index 7f2d5b000..92a28ee5a 100644 --- a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/src/index.ts +++ b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/src/index.ts @@ -4,6 +4,7 @@ import { AssembledTransaction, Client as ContractClient, ClientOptions as ContractClientOptions, + MethodOptions, Result, Spec as ContractSpec, } from '@stellar/stellar-sdk/contract'; @@ -30,12 +31,7 @@ if (typeof window !== 'undefined') { } -export const networks = { - futurenet: { - networkPassphrase: "Test SDF Future Network ; October 2022", - contractId: "CBYMYMSDF6FBDNCFJCRC7KMO4REYFPOH2U4N7FXI3GJO6YXNCQ43CDSK", - } -} as const + /** @@ -631,6 +627,20 @@ export interface Client { } export class Client extends ContractClient { + static async deploy( + /** Options for initalizing a Client as well as for calling a method, with extras specific to deploying. */ + options: MethodOptions & + Omit & { + /** The hash of the Wasm blob, which must already be installed on-chain. */ + wasmHash: Buffer | string; + /** Salt used to generate the contract's ID. Passed through to {@link Operation.createCustomContract}. Default: random. */ + salt?: Buffer | Uint8Array; + /** The format used to decode `wasmHash`, if it's provided as a string. */ + format?: "hex" | "base64"; + } + ): Promise> { + return ContractClient.deploy(null, options) + } constructor(public readonly options: ContractClientOptions) { super( new ContractSpec([ "AAAAAQAAAC9UaGlzIGlzIGZyb20gdGhlIHJ1c3QgZG9jIGFib3ZlIHRoZSBzdHJ1Y3QgVGVzdAAAAAAAAAAABFRlc3QAAAADAAAAAAAAAAFhAAAAAAAABAAAAAAAAAABYgAAAAAAAAEAAAAAAAAAAWMAAAAAAAAR", diff --git a/cmd/crates/soroban-spec-typescript/src/boilerplate.rs b/cmd/crates/soroban-spec-typescript/src/boilerplate.rs index 501d51434..bf5631eda 100644 --- a/cmd/crates/soroban-spec-typescript/src/boilerplate.rs +++ b/cmd/crates/soroban-spec-typescript/src/boilerplate.rs @@ -47,9 +47,9 @@ impl Project { pub fn init( &self, contract_name: &str, - contract_id: &str, - rpc_url: &str, - network_passphrase: &str, + contract_id: Option<&str>, + rpc_url: Option<&str>, + network_passphrase: Option<&str>, spec: &[ScSpecEntry], ) -> std::io::Result<()> { self.replace_placeholder_patterns(contract_name, contract_id, rpc_url, network_passphrase)?; @@ -59,9 +59,9 @@ impl Project { fn replace_placeholder_patterns( &self, contract_name: &str, - contract_id: &str, - rpc_url: &str, - network_passphrase: &str, + contract_id: Option<&str>, + rpc_url: Option<&str>, + network_passphrase: Option<&str>, ) -> std::io::Result<()> { let replacement_strings = &[ ("INSERT_CONTRACT_NAME_HERE", contract_name), @@ -73,9 +73,18 @@ impl Project { "INSERT_CAMEL_CASE_CONTRACT_NAME_HERE", &contract_name.to_lower_camel_case(), ), - ("INSERT_CONTRACT_ID_HERE", contract_id), - ("INSERT_NETWORK_PASSPHRASE_HERE", network_passphrase), - ("INSERT_RPC_URL_HERE", rpc_url), + ( + "INSERT_CONTRACT_ID_HERE", + contract_id.unwrap_or("INSERT_CONTRACT_ID_HERE"), + ), + ( + "INSERT_RPC_URL_HERE", + rpc_url.unwrap_or("INSERT_RPC_URL_HERE"), + ), + ( + "INSERT_NETWORK_PASSPHRASE_HERE", + network_passphrase.unwrap_or("INSERT_NETWORK_PASSPHRASE_HERE"), + ), ]; let root: &Path = self.as_ref(); ["package.json", "README.md", "src/index.ts"] @@ -93,8 +102,8 @@ impl Project { fn append_index_ts( &self, spec: &[ScSpecEntry], - contract_id: &str, - network_passphrase: &str, + contract_id: Option<&str>, + network_passphrase: Option<&str>, ) -> std::io::Result<()> { let networks = Project::format_networks_object(contract_id, network_passphrase); let types_and_fns = generate(spec); @@ -104,7 +113,15 @@ impl Project { .write_all(format!("\n\n{networks}\n\n{types_and_fns}").as_bytes()) } - fn format_networks_object(contract_id: &str, network_passphrase: &str) -> String { + fn format_networks_object( + contract_id: Option<&str>, + network_passphrase: Option<&str>, + ) -> String { + if contract_id.is_none() || network_passphrase.is_none() { + return String::new(); + } + let contract_id = contract_id.unwrap(); + let network_passphrase = network_passphrase.unwrap(); let network = match network_passphrase { NETWORK_PASSPHRASE_TESTNET => "testnet", NETWORK_PASSPHRASE_FUTURENET => "futurenet", @@ -138,9 +155,9 @@ mod test { let p: Project = root.as_ref().to_path_buf().try_into()?; p.init( "test_custom_types", - "CA3D5KRYM6CB7OWQ6TWYRR3Z4T7GNZLKERYNZGGA5SOAOPIFY6YQGAXE", - "https://rpc-futurenet.stellar.org:443", - "Test SDF Future Network ; October 2022", + Some("CA3D5KRYM6CB7OWQ6TWYRR3Z4T7GNZLKERYNZGGA5SOAOPIFY6YQGAXE"), + Some("https://rpc-futurenet.stellar.org:443"), + Some("Test SDF Future Network ; October 2022"), &spec, ) .unwrap(); diff --git a/cmd/crates/soroban-spec-typescript/src/lib.rs b/cmd/crates/soroban-spec-typescript/src/lib.rs index 94b5bb192..ee98a514d 100644 --- a/cmd/crates/soroban-spec-typescript/src/lib.rs +++ b/cmd/crates/soroban-spec-typescript/src/lib.rs @@ -59,7 +59,26 @@ pub fn generate_from_wasm(wasm: &[u8]) -> Result { Ok(json) } -fn generate_class(fns: &[Entry], spec: &[ScSpecEntry]) -> String { +fn generate_class( + fns: &[Entry], + constructor_args: Option>, + spec: &[ScSpecEntry], +) -> String { + let (constructor_args_in, constructor_args_out) = if let Some(inputs) = constructor_args { + let Some((args, arg_types)) = args_to_ts(&inputs) else { + panic!("inputs is present but couldn't be parsed by args_to_ts()"); + }; + ( + format!( + " + /** Constructor/Initialization Args for the contract's `__constructor` method */ + {args}: {arg_types},", + ), + args, + ) + } else { + (String::new(), "null".to_string()) + }; let method_types = fns.iter().map(entry_to_method_type).join(""); let from_jsons = fns .iter() @@ -74,6 +93,20 @@ fn generate_class(fns: &[Entry], spec: &[ScSpecEntry]) -> String { r#"export interface Client {{{method_types} }} export class Client extends ContractClient {{ + static async deploy({constructor_args_in} + /** Options for initalizing a Client as well as for calling a method, with extras specific to deploying. */ + options: MethodOptions & + Omit & {{ + /** The hash of the Wasm blob, which must already be installed on-chain. */ + wasmHash: Buffer | string; + /** Salt used to generate the contract's ID. Passed through to {{@link Operation.createCustomContract}}. Default: random. */ + salt?: Buffer | Uint8Array; + /** The format used to decode `wasmHash`, if it's provided as a string. */ + format?: "hex" | "base64"; + }} + ): Promise> {{ + return ContractClient.deploy({constructor_args_out}, options) + }} constructor(public readonly options: ContractClientOptions) {{ super( new ContractSpec([ {spec} ]), @@ -96,13 +129,20 @@ pub fn generate(spec: &[ScSpecEntry]) -> String { cases: vec![], }); } + let mut constructor_args: Option> = None; // Filter out function entries with names that start with "__" and partition the results + collected.iter().for_each(|entry| match entry { + Entry::Function { name, inputs, .. } if name == "__constructor" => { + constructor_args = Some(inputs.clone()); + } + _ => {} + }); let (fns, other): (Vec<_>, Vec<_>) = collected .into_iter() .filter(|entry| !matches!(entry, Entry::Function { name, .. } if name.starts_with("__"))) .partition(|entry| matches!(entry, Entry::Function { .. })); let top = other.iter().map(entry_to_method_type).join("\n"); - let bottom = generate_class(&fns, spec); + let bottom = generate_class(&fns, constructor_args, spec); format!("{top}\n\n{bottom}") } @@ -174,6 +214,18 @@ pub fn outputs_to_return_type(outputs: &[Type]) -> String { } } +/// Convert a function's inputs to TypeScript arguments. Returns a tuple with the arguments +/// as they'll actually be used in JS, as well as TS type definitions for the arguments. +pub fn args_to_ts(inputs: &[types::FunctionInput]) -> Option<(String, String)> { + if inputs.is_empty() { + None + } else { + let input_vals = inputs.iter().map(func_input_to_arg_name).join(", "); + let input_types = inputs.iter().map(func_input_to_ts).join(", "); + Some((format!("{{{input_vals}}}"), format!("{{{input_types}}}"))) + } +} + #[allow(clippy::too_many_lines)] pub fn entry_to_method_type(entry: &Entry) -> String { match entry { @@ -184,15 +236,11 @@ pub fn entry_to_method_type(entry: &Entry) -> String { outputs, .. } => { - let input_vals = inputs.iter().map(func_input_to_arg_name).join(", "); - let input = (!inputs.is_empty()) - .then(|| { - format!( - "{{{input_vals}}}: {{{}}}, ", - inputs.iter().map(func_input_to_ts).join(", ") - ) - }) - .unwrap_or_default(); + let input = if let Some((args, arg_types)) = args_to_ts(inputs) { + format!("{args}: {arg_types}, ") + } else { + String::new() + }; let doc = doc_to_ts_doc(doc, Some(name), 0); let return_type = outputs_to_return_type(outputs); format!( diff --git a/cmd/crates/soroban-spec-typescript/src/project_template/src/index.ts b/cmd/crates/soroban-spec-typescript/src/project_template/src/index.ts index 057d4ef72..b344a1c60 100644 --- a/cmd/crates/soroban-spec-typescript/src/project_template/src/index.ts +++ b/cmd/crates/soroban-spec-typescript/src/project_template/src/index.ts @@ -4,6 +4,7 @@ import { AssembledTransaction, Client as ContractClient, ClientOptions as ContractClientOptions, + MethodOptions, Result, Spec as ContractSpec, } from '@stellar/stellar-sdk/contract'; diff --git a/cmd/crates/soroban-spec-typescript/ts-tests/initialize.sh b/cmd/crates/soroban-spec-typescript/ts-tests/initialize.sh index 031061cca..e872923c6 100755 --- a/cmd/crates/soroban-spec-typescript/ts-tests/initialize.sh +++ b/cmd/crates/soroban-spec-typescript/ts-tests/initialize.sh @@ -29,18 +29,21 @@ function fund_all() { exe eval "./soroban keys generate root" exe eval "./soroban keys fund root" } -function deploy() { - exe eval "(./soroban contract deploy --quiet --source root --wasm $1 --ignore-checks) > $2" +function upload() { + exe eval "(./soroban contract $1 --quiet --source root --wasm $2 --ignore-checks) > $3" } function deploy_all() { - deploy ../../../../target/wasm32-unknown-unknown/test-wasms/test_custom_types.wasm contract-id-custom-types.txt + upload deploy ../../../../target/wasm32-unknown-unknown/test-wasms/test_custom_types.wasm contract-id-custom-types.txt + # TODO: support `--wasm-hash` with `contract bindings` + upload install ../../../../target/wasm32-unknown-unknown/test-wasms/test_constructor.wasm contract-wasm-hash-constructor.txt } function bind() { - exe eval "./soroban contract bindings typescript --contract-id $(cat $1) --output-dir ./node_modules/$2 --overwrite" - exe eval "sh -c \"cd ./node_modules/$2 && npm install && npm run build\"" + exe eval "./soroban contract bindings typescript $1 $2 --output-dir ./node_modules/$3 --overwrite" + exe eval "sh -c \"cd ./node_modules/$3 && npm install && npm run build\"" } function bind_all() { - bind contract-id-custom-types.txt test-custom-types + bind --contract-id $(cat contract-id-custom-types.txt) test-custom-types + bind --wasm ../../../../target/wasm32-unknown-unknown/test-wasms/test_constructor.wasm test-constructor } fund_all diff --git a/cmd/crates/soroban-spec-typescript/ts-tests/package-lock.json b/cmd/crates/soroban-spec-typescript/ts-tests/package-lock.json index 45cc97a67..786edd8ee 100644 --- a/cmd/crates/soroban-spec-typescript/ts-tests/package-lock.json +++ b/cmd/crates/soroban-spec-typescript/ts-tests/package-lock.json @@ -2340,9 +2340,9 @@ "dev": true }, "node_modules/node-gyp-build": { - "version": "4.8.3", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.3.tgz", - "integrity": "sha512-EMS95CMJzdoSKoIiXo8pxKoL8DYxwIZXYlLmgPb8KUv794abpnLK6ynsCAWNliOjREKruYKdzbh76HHYUHX7nw==", + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", + "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", "dev": true, "license": "MIT", "optional": true, diff --git a/cmd/crates/soroban-spec-typescript/ts-tests/src/test-constructor-args.ts b/cmd/crates/soroban-spec-typescript/ts-tests/src/test-constructor-args.ts new file mode 100644 index 000000000..a4f8bbfc4 --- /dev/null +++ b/cmd/crates/soroban-spec-typescript/ts-tests/src/test-constructor-args.ts @@ -0,0 +1,29 @@ +import { readFileSync } from "node:fs" +import { join } from "node:path" +import test from "ava" +import { networkPassphrase, rpcUrl, root, signer } from "./util.js" +import { Client } from "test-constructor" + +const wasmHash = readFileSync( + join(import.meta.dirname, "..", "contract-wasm-hash-constructor.txt"), + { encoding: "utf8" } +); + +const INIT_VALUE = 42; + +test("has correctly-typed result", async (t) => { + const deploy = await Client.deploy( + { counter: INIT_VALUE }, + { + networkPassphrase, + rpcUrl, + allowHttp: true, + wasmHash, + publicKey: root.keypair.publicKey(), + ...signer, + }, + ); + const { result: client } = await deploy.signAndSend(); + const { result } = await client.counter(); + t.is(result, INIT_VALUE); +}); diff --git a/cmd/crates/soroban-test/Cargo.toml b/cmd/crates/soroban-test/Cargo.toml index ebf903d82..61fcc0bd8 100644 --- a/cmd/crates/soroban-test/Cargo.toml +++ b/cmd/crates/soroban-test/Cargo.toml @@ -25,7 +25,6 @@ sep5 = { workspace = true } soroban-cli = { workspace = true } soroban-rpc = { workspace = true } -either = "1.13.0" thiserror = "1.0.31" sha2 = "0.10.6" assert_cmd = "2.0.4" diff --git a/cmd/crates/soroban-test/src/lib.rs b/cmd/crates/soroban-test/src/lib.rs index 3a16b63ca..96074e23d 100644 --- a/cmd/crates/soroban-test/src/lib.rs +++ b/cmd/crates/soroban-test/src/lib.rs @@ -27,7 +27,6 @@ use std::{ffi::OsString, fmt::Display, path::Path}; use assert_cmd::{assert::Assert, Command}; use assert_fs::{fixture::FixtureError, prelude::PathChild, TempDir}; -use either::Either; use fs_extra::dir::CopyOptions; use soroban_cli::{ @@ -203,10 +202,9 @@ impl TestEnv { source: &str, ) -> Result { let cmd = self.cmd_with_config::(command_str, None); - self.run_cmd_with(cmd, source).await.map(|r| match r { - Either::Left(help) => help, - Either::Right(tx) => tx.into_result().unwrap(), - }) + self.run_cmd_with(cmd, source) + .await + .map(|tx| tx.into_result().unwrap()) } /// A convenience method for using the invoke command. diff --git a/cmd/crates/soroban-test/tests/fixtures/bye/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/bye/Cargo.toml index deccb9c75..4756225d2 100644 --- a/cmd/crates/soroban-test/tests/fixtures/bye/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/bye/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "stellar-bye" -version = "0.0.0" +version = "22.0.1" edition = "2021" publish = false diff --git a/cmd/crates/soroban-test/tests/fixtures/hello/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/hello/Cargo.toml index fe7eb636a..a2fb7b15c 100644 --- a/cmd/crates/soroban-test/tests/fixtures/hello/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/hello/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "soroban-hello" -version = "0.0.0" +version = "22.0.1" edition = "2021" publish = false diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/constructor/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/constructor/Cargo.toml index 69d8a6430..9ccbb23d0 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/constructor/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/constructor/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "test_constructor" -version = "0.0.0" +version = "22.0.1" authors = ["Stellar Development Foundation "] license = "Apache-2.0" edition = "2021" diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_account/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_account/Cargo.toml index 765f671c6..e69dd96c9 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_account/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_account/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "test_custom_account" -version = "0.0.0" +version = "22.0.1" authors = ["Stellar Development Foundation "] license = "Apache-2.0" edition = "2021" diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_type/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_type/Cargo.toml index b5a17c6a5..50b6d8a72 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_type/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_type/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "test_custom_types" -version = "0.0.0" +version = "22.0.1" authors = ["Stellar Development Foundation "] license = "Apache-2.0" edition = "2021" diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/hello_world/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/hello_world/Cargo.toml index a13c98a39..a91a6ca62 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/hello_world/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/hello_world/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "test_hello_world" -version = "0.0.0" +version = "22.0.1" authors = ["Stellar Development Foundation "] license = "Apache-2.0" edition = "2021" diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/swap/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/swap/Cargo.toml index 495a52d71..15c45c98e 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/swap/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/swap/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "test_swap" -version = "0.0.0" +version = "22.0.1" authors = ["Stellar Development Foundation "] license = "Apache-2.0" edition = "2021" diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/token/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/token/Cargo.toml index 6456983e8..d4e7e7436 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/token/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/token/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "test_token" -version = "0.0.0" +version = "22.0.1" description = "Soroban standard token contract" authors = ["Stellar Development Foundation "] license = "Apache-2.0" diff --git a/cmd/crates/soroban-test/tests/it/help.rs b/cmd/crates/soroban-test/tests/it/help.rs index 12db8b9bd..7ddaf3afc 100644 --- a/cmd/crates/soroban-test/tests/it/help.rs +++ b/cmd/crates/soroban-test/tests/it/help.rs @@ -1,3 +1,5 @@ +use soroban_cli::commands::contract::arg_parsing::Error::HelpMessage; +use soroban_cli::commands::contract::invoke::Error::ArgParsing; use soroban_cli::commands::contract::{self, arg_parsing}; use soroban_test::TestEnv; @@ -5,7 +7,11 @@ use crate::util::{invoke_custom as invoke, CUSTOM_TYPES, DEFAULT_CONTRACT_ID}; async fn invoke_custom(func: &str, args: &str) -> Result { let e = &TestEnv::default(); - invoke(e, DEFAULT_CONTRACT_ID, func, args, &CUSTOM_TYPES.path()).await + let r = invoke(e, DEFAULT_CONTRACT_ID, func, args, &CUSTOM_TYPES.path()).await; + if let Err(ArgParsing(HelpMessage(e))) = r { + return Ok(e); + } + r } #[tokio::test] 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 f77bcb3b1..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,5 +1,3 @@ -use soroban_rpc::GetLatestLedgerResponse; - use soroban_cli::{ commands::{ contract::{self, fetch}, @@ -7,6 +5,7 @@ use soroban_cli::{ }, config::{locator, secret}, }; +use soroban_rpc::GetLatestLedgerResponse; use soroban_test::{AssertExt, TestEnv, LOCAL_NETWORK_PASSPHRASE}; use crate::integration::util::extend_contract; @@ -20,7 +19,7 @@ async fn invoke_view_with_non_existent_source_account() { let id = deploy_hello(sandbox).await; let world = "world"; let cmd = hello_world_cmd(&id, world); - let res = sandbox.run_cmd_with(cmd, "").await.unwrap().unwrap_right(); + let res = sandbox.run_cmd_with(cmd, "").await.unwrap(); assert_eq!(res, TxnResult::Res(format!(r#"["Hello",{world:?}]"#))); } @@ -167,7 +166,7 @@ fn hello_world_cmd(id: &str, arg: &str) -> contract::invoke::Cmd { async fn invoke_hello_world_with_lib(e: &TestEnv, id: &str) { let cmd = hello_world_cmd(id, "world"); - let res = e.run_cmd_with(cmd, "test").await.unwrap().unwrap_right(); + let res = e.run_cmd_with(cmd, "test").await.unwrap(); assert_eq!(res, TxnResult::Res(r#"["Hello","world"]"#.to_string())); } 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 0a0a103e8..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")) @@ -93,7 +108,7 @@ async fn payment() { "--destination", test1.as_str(), "--amount", - ONE_XLM.to_string().as_str(), + "10_000_000", ]) .assert() .success(); @@ -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/integration/util.rs b/cmd/crates/soroban-test/tests/it/integration/util.rs index 08cf19e65..486b00a1b 100644 --- a/cmd/crates/soroban-test/tests/it/integration/util.rs +++ b/cmd/crates/soroban-test/tests/it/integration/util.rs @@ -80,8 +80,7 @@ pub async fn deploy_contract( let res = sandbox .run_cmd_with(cmd, deployer.unwrap_or("test")) .await - .unwrap() - .unwrap_right(); + .unwrap(); match deploy { DeployKind::BuildOnly | DeployKind::SimOnly => match res.to_envelope() { commands::txn_result::TxnEnvelopeResult::TxnEnvelope(e) => { 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/crates/soroban-test/tests/it/util.rs b/cmd/crates/soroban-test/tests/it/util.rs index 7923f7429..7f652bb68 100644 --- a/cmd/crates/soroban-test/tests/it/util.rs +++ b/cmd/crates/soroban-test/tests/it/util.rs @@ -1,4 +1,3 @@ -use either::Either; use soroban_cli::{ commands::contract, config::{locator::KeyType, secret::Secret}, @@ -55,10 +54,7 @@ pub async fn invoke_custom( sandbox.cmd_with_config(&["--id", id, "--", func, arg], None); i.wasm = Some(wasm.to_path_buf()); let s = sandbox.run_cmd_with(i, TEST_ACCOUNT).await; - s.map(|r| match r { - Either::Left(help) => help, - Either::Right(tx) => tx.into_result().unwrap(), - }) + s.map(|tx| tx.into_result().unwrap()) } pub const DEFAULT_CONTRACT_ID: &str = "CDR6QKTWZQYW6YUJ7UP7XXZRLWQPFRV6SWBLQS4ZQOSAF4BOUD77OO5Z"; diff --git a/cmd/soroban-cli/src/commands/contract/arg_parsing.rs b/cmd/soroban-cli/src/commands/contract/arg_parsing.rs index 9f04e4427..27350bb74 100644 --- a/cmd/soroban-cli/src/commands/contract/arg_parsing.rs +++ b/cmd/soroban-cli/src/commands/contract/arg_parsing.rs @@ -1,3 +1,6 @@ +use crate::commands::contract::arg_parsing::Error::HelpMessage; +use crate::commands::txn_result::TxnResult; +use crate::config::{self}; use crate::xdr::{ self, Hash, InvokeContractArgs, ScAddress, ScSpecEntry, ScSpecFunctionV0, ScSpecTypeDef, ScVal, ScVec, @@ -6,17 +9,13 @@ use clap::error::ErrorKind::DisplayHelp; use clap::value_parser; use ed25519_dalek::SigningKey; use heck::ToKebabCase; +use soroban_spec_tools::Spec; use std::collections::HashMap; use std::convert::TryInto; use std::ffi::OsString; use std::fmt::Debug; use std::path::PathBuf; -use crate::commands::contract::arg_parsing::HostFunctionParameters::{HelpMessage, Params}; -use crate::commands::txn_result::TxnResult; -use crate::config::{self}; -use soroban_spec_tools::Spec; - #[derive(thiserror::Error, Debug)] pub enum Error { #[error("parsing argument {arg}: {error}")] @@ -43,13 +42,12 @@ pub enum Error { MissingArgument(String), #[error("")] MissingFileArg(PathBuf), -} - -pub enum HostFunctionParameters { - Params((String, Spec, InvokeContractArgs, Vec)), + #[error("")] HelpMessage(String), } +pub type HostFunctionParameters = (String, Spec, InvokeContractArgs, Vec); + pub fn build_host_function_parameters( contract_id: &stellar_strkey::Contract, slop: &[OsString], @@ -69,19 +67,19 @@ pub fn build_host_function_parameters( let long_help = cmd.render_long_help(); // try_get_matches_from returns an error if `help`, `--help` or `-h`are passed in the slop - // see clap documentation for more info: https://github.com/clap-rs/clap/blob/v4.1.8/src/builder/command.rs#L631 + // see clap documentation for more info: https://github.com/clap-rs/clap/blob/v4.1.8/src/builder/command.rs#L586 let maybe_matches = cmd.try_get_matches_from(slop); let Some((function, matches_)) = (match maybe_matches { Ok(mut matches) => &matches.remove_subcommand(), Err(e) => { // to not exit immediately (to be able to fetch help message in tests), check for an error if e.kind() == DisplayHelp { - return Ok(HelpMessage(e.to_string())); + return Err(HelpMessage(e.to_string())); } e.exit(); } }) else { - return Ok(HelpMessage(format!("{long_help}"))); + return Err(HelpMessage(format!("{long_help}"))); }; let func = spec.find_function(function)?; @@ -158,7 +156,7 @@ pub fn build_host_function_parameters( args: final_args, }; - Ok(Params((function.clone(), spec, invoke_args, signers))) + Ok((function.clone(), spec, invoke_args, signers)) } fn build_custom_cmd(name: &str, spec: &Spec) -> Result { diff --git a/cmd/soroban-cli/src/commands/contract/bindings.rs b/cmd/soroban-cli/src/commands/contract/bindings.rs index 1da946979..a91c966aa 100644 --- a/cmd/soroban-cli/src/commands/contract/bindings.rs +++ b/cmd/soroban-cli/src/commands/contract/bindings.rs @@ -1,4 +1,5 @@ pub mod json; +pub mod python; pub mod rust; pub mod typescript; @@ -12,6 +13,9 @@ pub enum Cmd { /// Generate a TypeScript / JavaScript package Typescript(typescript::Cmd), + + /// Generate Python bindings + Python(python::Cmd), } #[derive(thiserror::Error, Debug)] @@ -24,6 +28,9 @@ pub enum Error { #[error(transparent)] Typescript(#[from] typescript::Error), + + #[error(transparent)] + Python(#[from] python::Error), } impl Cmd { @@ -32,6 +39,7 @@ impl Cmd { Cmd::Json(json) => json.run()?, Cmd::Rust(rust) => rust.run()?, Cmd::Typescript(ts) => ts.run().await?, + Cmd::Python(python) => python.run()?, } Ok(()) } diff --git a/cmd/soroban-cli/src/commands/contract/bindings/python.rs b/cmd/soroban-cli/src/commands/contract/bindings/python.rs new file mode 100644 index 000000000..60a3e8dcb --- /dev/null +++ b/cmd/soroban-cli/src/commands/contract/bindings/python.rs @@ -0,0 +1,19 @@ +use std::fmt::Debug; + +use clap::Parser; + +#[derive(Parser, Debug, Clone)] +#[group(skip)] +pub struct Cmd {} + +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error("python binding generation is not implemented in the stellar-cli, but is available via the tool located here: https://github.com/lightsail-network/stellar-contract-bindings")] + NotImplemented, +} + +impl Cmd { + pub fn run(&self) -> Result<(), Error> { + Err(Error::NotImplemented) + } +} diff --git a/cmd/soroban-cli/src/commands/contract/bindings/typescript.rs b/cmd/soroban-cli/src/commands/contract/bindings/typescript.rs index 679e757f4..ea1f63eed 100644 --- a/cmd/soroban-cli/src/commands/contract/bindings/typescript.rs +++ b/cmd/soroban-cli/src/commands/contract/bindings/typescript.rs @@ -17,22 +17,22 @@ use crate::{ #[derive(Parser, Debug, Clone)] #[group(skip)] pub struct Cmd { - /// Path to optional wasm binary + /// Path to wasm file on local filesystem. You must either include this OR `--contract-id`. #[arg(long)] pub wasm: Option, + /// A contract ID/address on a network (if no network settings provided, Testnet will be assumed). You must either include this OR `--wasm`. + #[arg(long, visible_alias = "id")] + pub contract_id: Option, /// Where to place generated project #[arg(long)] pub output_dir: PathBuf, /// Whether to overwrite output directory if it already exists #[arg(long)] pub overwrite: bool, - /// The contract ID/address on the network - #[arg(long, visible_alias = "id")] - pub contract_id: String, - #[command(flatten)] - pub locator: locator::Args, #[command(flatten)] pub network: network::Args, + #[command(flatten)] + pub locator: locator::Args, } #[derive(thiserror::Error, Debug)] @@ -51,6 +51,9 @@ pub enum Error { #[error("--output-dir filepath not representable as utf-8: {0:?}")] NotUtf8(OsString), + #[error("must include either --wasm or --contract-id")] + MissingWasmOrContractId, + #[error(transparent)] Network(#[from] network::Error), @@ -84,34 +87,46 @@ impl NetworkRunnable for Cmd { ) -> Result<(), Error> { let print = Print::new(global_args.is_some_and(|a| a.quiet)); - let network = self.network.get(&self.locator).ok().unwrap_or_else(|| { - network::DEFAULTS - .get("testnet") - .expect("no network specified and testnet network not found") - .into() - }); - - let contract_id = self - .locator - .resolve_contract_id(&self.contract_id, &network.network_passphrase)? - .0; - let contract_address = ScAddress::Contract(Hash(contract_id)); - - let spec = if let Some(wasm) = &self.wasm { + let (spec, contract_address, rpc_url, network_passphrase) = if let Some(wasm) = &self.wasm { print.infoln("Loading contract spec from file..."); let wasm: wasm::Args = wasm.into(); - wasm.parse()?.spec + (wasm.parse()?.spec, None, None, None) } else { + let contract_id = self + .contract_id + .as_ref() + .ok_or(Error::MissingWasmOrContractId)?; + + let network = self.network.get(&self.locator).ok().unwrap_or_else(|| { + network::DEFAULTS + .get("testnet") + .expect("no network specified and testnet network not found") + .into() + }); + print.infoln(format!("Network: {}", network.network_passphrase)); + + let contract_id = self + .locator + .resolve_contract_id(contract_id, &network.network_passphrase)? + .0; + + let contract_address = ScAddress::Contract(Hash(contract_id)).to_string(); print.globeln(format!("Downloading contract spec: {contract_address}")); - get_remote_contract_spec( - &contract_id, - &self.locator, - &self.network, - global_args, - config, + + ( + get_remote_contract_spec( + &contract_id, + &self.locator, + &self.network, + global_args, + config, + ) + .await + .map_err(Error::from)?, + Some(contract_address), + Some(network.rpc_url), + Some(network.network_passphrase), ) - .await - .map_err(Error::from)? }; if self.output_dir.is_file() { return Err(Error::IsFile(self.output_dir.clone())); @@ -125,7 +140,6 @@ impl NetworkRunnable for Cmd { } std::fs::create_dir_all(&self.output_dir)?; let p: Project = self.output_dir.clone().try_into()?; - print.infoln(format!("Network: {}", network.network_passphrase)); let absolute_path = self.output_dir.canonicalize()?; let file_name = absolute_path .file_name() @@ -133,12 +147,14 @@ impl NetworkRunnable for Cmd { let contract_name = &file_name .to_str() .ok_or_else(|| Error::NotUtf8(file_name.to_os_string()))?; - print.infoln(format!("Embedding contract address: {contract_address}")); + if let Some(contract_address) = contract_address.clone() { + print.infoln(format!("Embedding contract address: {contract_address}")); + } p.init( contract_name, - &contract_address.to_string(), - &network.rpc_url, - &network.network_passphrase, + contract_address.as_deref(), + rpc_url.as_deref(), + network_passphrase.as_deref(), &spec, )?; print.checkln("Generated!"); diff --git a/cmd/soroban-cli/src/commands/contract/deploy/wasm.rs b/cmd/soroban-cli/src/commands/contract/deploy/wasm.rs index 8d6d9d253..bc4548b11 100644 --- a/cmd/soroban-cli/src/commands/contract/deploy/wasm.rs +++ b/cmd/soroban-cli/src/commands/contract/deploy/wasm.rs @@ -6,8 +6,6 @@ use crate::xdr::{ VecM, WriteXdr, }; use clap::{arg, command, Parser}; -use itertools::Either; -use itertools::Either::{Left, Right}; use rand::Rng; use regex::Regex; use soroban_spec_tools::contract as contract_spec; @@ -16,7 +14,8 @@ use std::ffi::OsString; use std::fmt::Debug; use std::num::ParseIntError; -use crate::commands::contract::arg_parsing::HostFunctionParameters; +use crate::commands::contract::arg_parsing::Error::HelpMessage; +use crate::commands::contract::deploy::wasm::Error::ArgParse; use crate::{ assembled::simulate_and_assemble_transaction, commands::{ @@ -129,12 +128,9 @@ pub enum Error { impl Cmd { pub async fn run(&self, global_args: &global::Args) -> Result<(), Error> { - let res = self.run_against_rpc_server(Some(global_args), None).await?; + let res = self.run_against_rpc_server(Some(global_args), None).await; match res { - Left(help) => { - println!("{help}"); - } - Right(res) => match res.to_envelope() { + Ok(res) => match res.to_envelope() { TxnEnvelopeResult::TxnEnvelope(tx) => { println!("{}", tx.to_xdr_base64(Limits::none())?); } @@ -152,6 +148,10 @@ impl Cmd { println!("{contract}"); } }, + Err(ArgParse(HelpMessage(help))) => { + println!("{help}"); + } + Err(e) => return Err(e), } Ok(()) @@ -173,14 +173,14 @@ fn alias_validator(alias: &str) -> Result { #[async_trait::async_trait] impl NetworkRunnable for Cmd { type Error = Error; - type Result = Either>; + type Result = TxnResult; #[allow(clippy::too_many_lines)] async fn run_against_rpc_server( &self, global_args: Option<&global::Args>, config: Option<&config::Args>, - ) -> Result>, Error> { + ) -> Result, Error> { let print = Print::new(global_args.map_or(false, |a| a.quiet)); let config = config.unwrap_or(&self.config); let wasm_hash = if let Some(wasm) = &self.wasm { @@ -260,12 +260,7 @@ impl NetworkRunnable for Cmd { &entries, config, )?; - match params { - HostFunctionParameters::Params(p) => Some(p.2), - HostFunctionParameters::HelpMessage(h) => { - return Ok(Left(h)); - } - } + Some(params.2) } } else { None @@ -285,7 +280,7 @@ impl NetworkRunnable for Cmd { if self.fee.build_only { print.checkln("Transaction built!"); - return Ok(Right(TxnResult::Txn(txn))); + return Ok(TxnResult::Txn(txn)); } print.infoln("Simulating deploy transaction…"); @@ -295,7 +290,7 @@ impl NetworkRunnable for Cmd { if self.fee.sim_only { print.checkln("Done!"); - return Ok(Right(TxnResult::Txn(txn))); + return Ok(TxnResult::Txn(txn)); } print.globeln("Submitting deploy transaction…"); @@ -316,7 +311,7 @@ impl NetworkRunnable for Cmd { print.checkln("Deployed!"); - Ok(Right(TxnResult::Res(contract_id))) + Ok(TxnResult::Res(contract_id)) } } diff --git a/cmd/soroban-cli/src/commands/contract/invoke.rs b/cmd/soroban-cli/src/commands/contract/invoke.rs index d56778451..a42f0a926 100644 --- a/cmd/soroban-cli/src/commands/contract/invoke.rs +++ b/cmd/soroban-cli/src/commands/contract/invoke.rs @@ -6,15 +6,13 @@ use std::str::FromStr; use std::{fmt::Debug, fs, io}; use clap::{arg, command, Parser, ValueEnum}; -use itertools::Either; -use itertools::Either::{Left, Right}; use soroban_rpc::{Client, SimulateHostFunctionResult, SimulateTransactionResponse}; use soroban_spec::read::FromWasmError; use super::super::events; use super::arg_parsing; -use crate::commands::contract::arg_parsing::HostFunctionParameters; -use crate::commands::contract::arg_parsing::HostFunctionParameters::HelpMessage; +use crate::commands::contract::arg_parsing::Error::HelpMessage; +use crate::commands::contract::invoke::Error::ArgParsing; use crate::{ assembled::simulate_and_assemble_transaction, commands::{ @@ -134,9 +132,9 @@ impl From for Error { impl Cmd { pub async fn run(&self, global_args: &global::Args) -> Result<(), Error> { - let res = self.invoke(global_args).await?; + let res = self.invoke(global_args).await; match res { - Right(res) => match res.to_envelope() { + Ok(res) => match res.to_envelope() { TxnEnvelopeResult::TxnEnvelope(tx) => { println!("{}", tx.to_xdr_base64(Limits::none())?); } @@ -144,17 +142,15 @@ impl Cmd { println!("{output}"); } }, - Left(help) => { + Err(ArgParsing(HelpMessage(help))) => { println!("{help}"); } + Err(e) => return Err(e), } Ok(()) } - pub async fn invoke( - &self, - global_args: &global::Args, - ) -> Result>, Error> { + pub async fn invoke(&self, global_args: &global::Args) -> Result, Error> { self.run_against_rpc_server(Some(global_args), None).await } @@ -217,13 +213,13 @@ impl Cmd { #[async_trait::async_trait] impl NetworkRunnable for Cmd { type Error = Error; - type Result = Either>; + type Result = TxnResult; async fn run_against_rpc_server( &self, global_args: Option<&global::Args>, config: Option<&config::Args>, - ) -> Result>, Error> { + ) -> Result, Error> { let config = config.unwrap_or(&self.config); let network = config.get_network()?; tracing::trace!(?network); @@ -234,11 +230,7 @@ impl NetworkRunnable for Cmd { let spec_entries = self.spec_entries()?; if let Some(spec_entries) = &spec_entries { // For testing wasm arg parsing - let params = - build_host_function_parameters(&contract_id, &self.slop, spec_entries, config)?; - if let HelpMessage(s) = params { - return Ok(Left(s)); - } + build_host_function_parameters(&contract_id, &self.slop, spec_entries, config)?; } let client = network.rpc_client()?; @@ -255,10 +247,7 @@ impl NetworkRunnable for Cmd { let params = build_host_function_parameters(&contract_id, &self.slop, &spec_entries, config)?; - let (function, spec, host_function_params, signers) = match params { - HostFunctionParameters::Params(x) => x, - HelpMessage(s) => return Ok(Left(s)), - }; + let (function, spec, host_function_params, signers) = params; let should_send_tx = self .should_send_after_sim(host_function_params.clone(), client.clone()) @@ -285,13 +274,13 @@ impl NetworkRunnable for Cmd { account_id, )?); if self.fee.build_only { - return Ok(Right(TxnResult::Txn(tx))); + return Ok(TxnResult::Txn(tx)); } let txn = simulate_and_assemble_transaction(&client, &tx).await?; let assembled = self.fee.apply_to_assembled_txn(txn); let mut txn = Box::new(assembled.transaction().clone()); if self.fee.sim_only { - return Ok(Right(TxnResult::Txn(txn))); + return Ok(TxnResult::Txn(txn)); } let sim_res = assembled.sim_response(); if global_args.map_or(true, |a| !a.no_cache) { @@ -326,7 +315,7 @@ impl NetworkRunnable for Cmd { } }; crate::log::events(&events); - Ok(Right(output_to_string(&spec, &return_value, &function)?)) + Ok(output_to_string(&spec, &return_value, &function)?) } } 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 9cc3a62ff..acdfd6e2d 100644 --- a/cmd/soroban-cli/src/commands/tx/new/create_account.rs +++ b/cmd/soroban-cli/src/commands/tx/new/create_account.rs @@ -1,25 +1,31 @@ use clap::{command, Parser}; -use crate::{commands::tx, xdr}; +use crate::{commands::tx, tx::builder, xdr}; #[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)] +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 = "10000000")] - pub starting_balance: i64, + #[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, + 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 e0a029f02..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,7 +7,15 @@ use crate::{commands::tx, xdr}; pub struct Cmd { #[command(flatten)] pub tx: tx::Args, - /// Line to change, either 4 or 12 alphanumeric characters, or "native" if not specified + #[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. #[arg(long)] pub data_name: xdr::StringM<64>, /// Up to 64 bytes long hex string @@ -17,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 c626d9ca8..683b2731c 100644 --- a/cmd/soroban-cli/src/commands/tx/new/payment.rs +++ b/cmd/soroban-cli/src/commands/tx/new/payment.rs @@ -7,23 +7,29 @@ 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")] pub asset: builder::Asset, - /// Amount of the aforementioned asset to send. + /// Amount of the aforementioned asset to send. e.g. `10_000_000` (1 XLM) #[arg(long)] - pub amount: i64, + 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(), - amount: cmd.amount, + amount: cmd.amount.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()) +} diff --git a/cmd/soroban-cli/src/tx/builder.rs b/cmd/soroban-cli/src/tx/builder.rs index ad22737ea..c84bb7124 100644 --- a/cmd/soroban-cli/src/tx/builder.rs +++ b/cmd/soroban-cli/src/tx/builder.rs @@ -1,6 +1,8 @@ +pub mod amount; pub mod asset; pub mod transaction; +pub use amount::Amount; pub use asset::Asset; pub use transaction::TxExt; diff --git a/cmd/soroban-cli/src/tx/builder/amount.rs b/cmd/soroban-cli/src/tx/builder/amount.rs new file mode 100644 index 000000000..d3c204f50 --- /dev/null +++ b/cmd/soroban-cli/src/tx/builder/amount.rs @@ -0,0 +1,35 @@ +use std::str::FromStr; + +#[derive(Clone, Debug, Copy)] +pub struct Amount(i64); + +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error("cannot start or end with `_`: {0}")] + CannotStartOrEndWithUnderscore(String), + #[error(transparent)] + IntParse(#[from] std::num::ParseIntError), +} + +impl FromStr for Amount { + type Err = Error; + + fn from_str(value: &str) -> Result { + if value.starts_with('_') || value.ends_with('_') { + return Err(Error::CannotStartOrEndWithUnderscore(value.to_string())); + } + Ok(Self(value.replace('_', "").parse::()?)) + } +} + +impl From for i64 { + fn from(builder: Amount) -> Self { + builder.0 + } +} + +impl From<&Amount> for i64 { + fn from(builder: &Amount) -> Self { + (*builder).into() + } +} diff --git a/deny.toml b/deny.toml index ae50f65ea..9817c3e79 100644 --- a/deny.toml +++ b/deny.toml @@ -308,9 +308,7 @@ skip = [ # testcontainers { crate = "idna", reason = "temp", version = "0.5.0" }, - - # { name = "hashbrown", version = "=0.13.2" }, - # { name = "syn", version = "=1.0.109" }, + { crate = "bitflags", reason = "too many", version = "=1.3.2" }, ] # Similarly to `skip` allows you to skip certain crates during duplicate # detection. Unlike skip, it also includes the entire tree of transitive