Skip to content

Commit

Permalink
Add a forc-tx plugin purely for constructing TXs from CLI (FuelLabs…
Browse files Browse the repository at this point in the history
…#3582)

This crate allows for constructing arbitrary transactions from the
command line. The constructed `forc_tx::Transaction` can be converted to
a `fuel_tx::Transaction` using the `TryFrom` implementation.

The key difference between the `forc_tx::Transaction` type differs in
that it accepts *paths* for fields like `bytecode`, `storage_slots`,
`predicate_data`, etc. These are loaded during the
`fuel_tx::Transaction`'s `try_from` constructor.

Addresses FuelLabs#3491.

Verbose Example
---------------

The following isn't a valid transaction, but shows what it looks like to
specify arguments including multiple inputs and outputs.

```console
forc tx create \
    --bytecode ./my-contract/out/debug/my-contract.bin \
    --storage-slots ./my-contract/out/debug/my-contract-storage_slots.json \
    --gas-limit 100 \
    --gas-price 0 \
    --maturity 0 \
    --witness ADFD \
    --witness DFDA \
    input coin \
        --utxo-id 0 \
        --output-ix 0 \
        --owner 0x0000000000000000000000000000000000000000000000000000000000000000 \
        --amount 100 \
        --asset-id 0x0000000000000000000000000000000000000000000000000000000000000000 \
        --tx-ptr 89ACBDEFBDEF \
        --witness-ix 0 \
        --maturity 0 \
        --predicate ./my-predicate/out/debug/my-predicate.bin \
        --predicate-data ./my-predicate.dat \
    input contract \
        --utxo-id 1 \
        --output-ix 1 \
        --balance-root 0x0000000000000000000000000000000000000000000000000000000000000000 \
        --state-root 0x0000000000000000000000000000000000000000000000000000000000000000 \
        --tx-ptr 89ACBDEFBDEF \
        --contract-id 0xCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC \
    input message \
        --msg-id 0xBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB \
        --sender 0x1111111111111111111111111111111111111111111111111111111111111111 \
        --recipient 0x2222222222222222222222222222222222222222222222222222222222222222 \
        --amount 1 \
        --nonce 1234 \
        --witness-ix 1 \
        --msg-data ./message.dat \
        --predicate ./my-predicate2/out/debug/my-predicate2.bin \
        --predicate-data ./my-predicate2.dat \
    output coin \
        --to 0x2222222222222222222222222222222222222222222222222222222222222222 \
        --amount 100 \
        --asset-id 0x0000000000000000000000000000000000000000000000000000000000000000 \
    output contract \
        --input-ix 1 \
        --balance-root 0x0000000000000000000000000000000000000000000000000000000000000000 \
        --state-root 0x0000000000000000000000000000000000000000000000000000000000000000 \
    output message \
        --recipient 0x2222222222222222222222222222222222222222222222222222222222222222 \
        --amount 100 \
    output change \
        --to 0x2222222222222222222222222222222222222222222222222222222222222222 \
        --amount 100 \
        --asset-id 0x0000000000000000000000000000000000000000000000000000000000000000 \
    output variable \
        --to 0x2222222222222222222222222222222222222222222222222222222222222222 \
        --amount 100 \
        --asset-id 0x0000000000000000000000000000000000000000000000000000000000000000 \
    output contract-created \
        --contract-id 0xCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC \
        --state-root 0x0000000000000000000000000000000000000000000000000000000000000000
```

The output of this command dumps the entire `fuel_tx::Transaction`
serialized to JSON to stdout. A `-o tx.json` argument can be provided
(before the transaction type) to write the tx to a file instead.

Follow-up
---------

- Currently, the CLI is a bit unwieldy due to requiring a custom
`try_parse` constructor which is required to parse multiple trailing
input/output subcommands. This is necessary because clap doesn't appear
to allow multiple trailing subcommands by default. We should see if it's
possible to manually implement clap's Subcommand for some custom type in
a manner that allows us the same behaviour but without breaking clap's
generated CLI.
- Possibly add forc-aware defaults, i.e. infer unambiguous defaults for
bytecode, storage slots, etc from the project within the current or
parent directory.
- Base `forc-run`, `forc-deploy` transaction construction on components
from `forc-tx`.
- Add CI tests for `forc tx` command that actually constructs and
submits a transaction to a node. This might be a lot easier to write
once we have something like a `forc submit` command that allows
submitting a transaction from the command line.

Co-authored-by: Joshua Batty <[email protected]>
  • Loading branch information
mitchmindtree and JoshuaBatty authored Jan 18, 2023
1 parent 555f34e commit 7c3331d
Show file tree
Hide file tree
Showing 6 changed files with 781 additions and 1 deletion.
4 changes: 3 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ jobs:
cargo install --debug --path ./forc-plugins/forc-fmt
cargo install --debug --path ./forc-plugins/forc-lsp
cargo install --debug --path ./forc-plugins/forc-client
cargo install --debug --path ./forc-plugins/forc-tx
cargo install --debug forc-explore
- name: Install mdbook-forc-documenter
uses: actions-rs/cargo@v1
Expand Down Expand Up @@ -409,6 +410,7 @@ jobs:
./.github/workflows/scripts/verify_tag.sh ${{ github.ref_name }} forc-plugins/forc-doc/Cargo.toml
./.github/workflows/scripts/verify_tag.sh ${{ github.ref_name }} forc-plugins/forc-fmt/Cargo.toml
./.github/workflows/scripts/verify_tag.sh ${{ github.ref_name }} forc-plugins/forc-lsp/Cargo.toml
./.github/workflows/scripts/verify_tag.sh ${{ github.ref_name }} forc-plugins/forc-tx/Cargo.toml
./.github/workflows/scripts/verify_tag.sh ${{ github.ref_name }} forc-test/Cargo.toml
./.github/workflows/scripts/verify_tag.sh ${{ github.ref_name }} forc-tracing/Cargo.toml
./.github/workflows/scripts/verify_tag.sh ${{ github.ref_name }} forc-util/Cargo.toml
Expand Down Expand Up @@ -636,7 +638,7 @@ jobs:
ZIP_FILE_NAME=forc-binaries-${{ env.PLATFORM_NAME }}_${{ env.ARCH }}.tar.gz
echo "ZIP_FILE_NAME=$ZIP_FILE_NAME" >> $GITHUB_ENV
mkdir -pv ./forc-binaries
for BINARY in forc forc-fmt forc-lsp forc-deploy forc-run forc-doc; do
for BINARY in forc forc-fmt forc-lsp forc-deploy forc-run forc-doc forc-tx; do
cp "target/${{ matrix.job.target }}/release/$BINARY" ./forc-binaries
done
tar -czvf $ZIP_FILE_NAME ./forc-binaries
Expand Down
11 changes: 11 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ members = [
"forc-plugins/forc-doc",
"forc-plugins/forc-fmt",
"forc-plugins/forc-lsp",
"forc-plugins/forc-tx",
"forc-test",
"forc-tracing",
"forc-util",
Expand Down
23 changes: 23 additions & 0 deletions forc-plugins/forc-tx/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[package]
name = "forc-tx"
version = "0.33.0"
authors = ["Fuel Labs <[email protected]>"]
edition = "2021"
homepage = "https://fuel.network/"
license = "Apache-2.0"
repository = "https://github.com/FuelLabs/sway"
description = "A `forc` plugin for constructing transactions."

[lib]
path = "src/lib.rs"

[[bin]]
name = "forc-tx"
path = "src/main.rs"

[dependencies]
anyhow = "1"
clap = { version = "3", features = ["derive", "env"] }
fuel-tx = { version = "0.23", features = ["serde"] }
serde = "1.0"
serde_json = { version = "1" }
Loading

0 comments on commit 7c3331d

Please sign in to comment.