[
  {
    "path": ".editorconfig",
    "content": "[*.toml]\nindent_style = space\nindent_size = 2\n"
  },
  {
    "path": ".github/CODEOWNERS",
    "content": "* @FuelLabs/client \n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "<!--\nList the issues this PR closes (if any) in a bullet list format, e.g.:\n- Closes #ABCD\n- Closes #EFGH\n-->\n\n# Release notes\n\n<!--\nUse this only if this PR requires a mention in the Release\nNotes Summary. Valuable features and critical fixes are good\nexamples. For everything else, please delete the whole section.\n-->\n\nIn this release, we:\n\n- Did this and that <!-- edit this text only -->\n\n# Summary\n\n<!--\nPlease write a summary of your changes and why you made them.\nNot all PRs will be complex or substantial enough to require this\nsection, so you can remove it if you think it's unnecessary.\n-->\n\n# Breaking Changes\n\n<!--\nIf the PR has breaking changes, please detail them in this section\nand remove this comment.\n\nRemove this section if there are no breaking changes.\n-->\n\n# Checklist\n\n- [ ] All **changes** are **covered** by **tests** (or not applicable)\n- [ ] All **changes** are **documented** (or not applicable)\n- [ ] I **reviewed** the **entire PR** myself (preferably, on GH UI)\n- [ ] I **described** all **Breaking Changes** (or there's none)\n"
  },
  {
    "path": ".github/workflows/ci.yml",
    "content": "name: CI\n\non:\n  push:\n    branches:\n      - master\n  pull_request:\n  release:\n    types: [ published ]\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}\n  cancel-in-progress: true\n\nenv:\n  CARGO_TERM_COLOR: always\n  DASEL_VERSION: https://github.com/TomWright/dasel/releases/download/v2.3.6/dasel_linux_amd64\n  RUSTFLAGS: \"-D warnings\"\n  FUEL_CORE_VERSION: 0.47.1\n  FUEL_CORE_PATCH_BRANCH: \"\"\n  FUEL_CORE_PATCH_REVISION: \"\"\n  RUST_VERSION: 1.93.0\n  FORC_VERSION: 0.69.1\n  FORC_PATCH_BRANCH: \"\"\n  FORC_PATCH_REVISION: \"\"\n  NEXTEST_HIDE_PROGRESS_BAR: \"true\"\n  NEXTEST_STATUS_LEVEL: \"fail\"\n\njobs:\n  setup-test-projects:\n    runs-on: buildjet-4vcpu-ubuntu-2204\n    steps:\n      - uses: actions/checkout@v3\n      - name: Install toolchain\n        uses: dtolnay/rust-toolchain@master\n        with:\n          toolchain: ${{ env.RUST_VERSION }}\n        # selecting a toolchain either by action or manual `rustup` calls should happen\n        # before the cache plugin, as it uses the current rustc version as its cache key\n      - uses: buildjet/cache@v3\n        with:\n          prefix-key: \"v1-rust\"\n\n      - name: Set git config\n        run: |\n          git config --global core.bigfilethreshold 100m\n\n      - name: Install forc and forc-fmt\n        run: |\n          if [[ -n $FORC_PATCH_BRANCH ]]; then\n            cargo install --locked forc forc-fmt --git https://github.com/FuelLabs/sway --branch $FORC_PATCH_BRANCH\n          elif [[ -n $FORC_PATCH_REVISION ]]; then\n            cargo install --locked forc forc-fmt --git https://github.com/FuelLabs/sway --rev $FORC_PATCH_REVISION\n          else\n            curl -sSLf https://github.com/FuelLabs/sway/releases/download/v${{ env.FORC_VERSION }}/forc-binaries-linux_amd64.tar.gz -L -o forc.tar.gz\n            tar -xvf forc.tar.gz\n            chmod +x forc-binaries/forc\n            mv forc-binaries/forc /usr/local/bin/forc\n            mv forc-binaries/forc-fmt /usr/local/bin/forc-fmt\n          fi\n\n      - name: Check format of Sway test projects\n        run: forc fmt --check --path e2e\n\n      - name: Build Sway test projects\n        run: forc build --release --terse --error-on-warnings --path e2e\n\n      - uses: actions/upload-artifact@v4\n        with:\n          retention-days: 2\n          name: sway-examples\n          path: |\n            e2e/sway/**/out/*\n\n  get-workspace-members:\n    runs-on: buildjet-4vcpu-ubuntu-2204\n    outputs:\n      members: ${{ steps.set-members.outputs.members }}\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@v3\n      - id: set-members\n        run: |\n          # install dasel\n          curl -sSLf \"$DASEL_VERSION\" -L -o dasel && chmod +x dasel\n          mv ./dasel /usr/local/bin/dasel\n          members=$(cat Cargo.toml | dasel -r toml -w json 'workspace.members' | jq -r \".[]\" | xargs -I '{}' dasel -f {}/Cargo.toml 'package.name' | jq -R '[.]' | jq -s -c 'add')\n          echo \"members=$members\" >> $GITHUB_OUTPUT\n\n  verify-rust-version:\n    runs-on: buildjet-4vcpu-ubuntu-2204\n    steps:\n      - uses: actions/checkout@v3\n      # Ensure CI is using the same minimum toolchain specified in fuels Cargo.toml\n      - run: |\n          curl -sSLf \"$DASEL_VERSION\" -L -o dasel && chmod +x dasel\n          mv ./dasel /usr/local/bin/dasel\n          MIN_VERSION=$(cat Cargo.toml | dasel -r toml 'workspace.package.rust-version' -w plain)\n          RUST_VERSION=\"${{ env.RUST_VERSION }}\"\n          echo \"Comparing minimum supported toolchain ($MIN_VERSION) with ci toolchain (RUST_VERSION)\"\n          test \"$MIN_VERSION\" == \"$RUST_VERSION\"\n\n  # Fetch Fuel Core and upload as artifact, useful when we build the core from a\n  # revision so that we can repeat flaky tests without rebuilding the core.\n  fetch-fuel-core:\n    runs-on: buildjet-4vcpu-ubuntu-2204\n    steps:\n      - uses: dtolnay/rust-toolchain@master\n        with:\n          toolchain: ${{ env.RUST_VERSION }}\n          targets: wasm32-unknown-unknown\n\n        # selecting a toolchain either by action or manual `rustup` calls should happen\n        # before the cache plugin, as it uses the current rustc version as its cache key\n      - uses: buildjet/cache@v3\n        continue-on-error: true\n        with:\n          key: \"fuel-core-build\"\n      - name: Install Fuel Core\n        run: |\n          if [[ -n $FUEL_CORE_PATCH_BRANCH ]]; then\n            cargo install --locked fuel-core-bin --git https://github.com/FuelLabs/fuel-core --branch \"$FUEL_CORE_PATCH_BRANCH\" --root fuel-core-install\n          elif [[ -n $FUEL_CORE_PATCH_REVISION ]]; then\n            cargo install --locked fuel-core-bin --git https://github.com/FuelLabs/fuel-core --rev \"$FUEL_CORE_PATCH_REVISION\" --root fuel-core-install\n\n          else\n            curl -sSLf https://github.com/FuelLabs/fuel-core/releases/download/v${{ env.FUEL_CORE_VERSION }}/fuel-core-${{ env.FUEL_CORE_VERSION }}-x86_64-unknown-linux-gnu.tar.gz -L -o fuel-core.tar.gz\n            tar -xvf fuel-core.tar.gz\n            chmod +x fuel-core-${{ env.FUEL_CORE_VERSION }}-x86_64-unknown-linux-gnu/fuel-core\n            mkdir -p fuel-core-install/bin\n            mv fuel-core-${{ env.FUEL_CORE_VERSION }}-x86_64-unknown-linux-gnu/fuel-core fuel-core-install/bin/fuel-core\n          fi\n\n      - uses: actions/upload-artifact@v4\n        with:\n          name: fuel-core\n          path: fuel-core-install/bin/fuel-core\n\n  # Ensure workspace is publishable\n  publish-crates-check:\n    runs-on: buildjet-4vcpu-ubuntu-2204\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@v3\n\n      - uses: dtolnay/rust-toolchain@master\n        with:\n          toolchain: ${{ env.RUST_VERSION }}\n\n      - name: Publish crate check\n        uses: FuelLabs/publish-crates@v1\n        with:\n          dry-run: true\n          check-repo: false\n          ignore-unpublished-changes: true\n\n  cargo-verifications:\n    needs:\n      - setup-test-projects\n      - verify-rust-version\n      - get-workspace-members\n      - publish-crates-check\n      - fetch-fuel-core\n    runs-on: buildjet-4vcpu-ubuntu-2204\n    strategy:\n      matrix:\n        cargo_command: [ check ]\n        args: [ --all-features ]\n        package: ${{fromJSON(needs.get-workspace-members.outputs.members)}}\n        include:\n          - cargo_command: fmt\n            args: --all --verbose -- --check\n          - cargo_command: clippy\n            args: --all-targets\n            download_sway_artifacts: sway-examples\n          - cargo_command: nextest\n            args: run --all-targets --features \"default fuel-core-lib coin-cache\" --workspace --cargo-quiet --no-fail-fast\n            download_sway_artifacts: sway-examples\n            install_fuel_core: true\n          - cargo_command: nextest\n            args: run --all-targets --workspace --cargo-quiet --no-fail-fast\n            download_sway_artifacts: sway-examples\n            install_fuel_core: true\n          - cargo_command: test\n            args: --doc --workspace\n          - cargo_command: machete\n            args: --skip-target-dir\n          - command: test_wasm\n            args:\n          - command: check_fuel_core_version\n            args:\n          - command: check_doc_anchors_valid\n            args:\n          - command: check_doc_unresolved_links\n            args:\n          - command: check_typos\n            args:\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@v3\n        with:\n          ref: ${{ github.event.pull_request.head.sha }}\n      - uses: dtolnay/rust-toolchain@master\n        with:\n          toolchain: ${{ env.RUST_VERSION }}\n          components: clippy,rustfmt\n          targets: wasm32-unknown-unknown\n\n        # selecting a toolchain either by action or manual `rustup` calls should happen\n        # before the cache plugin, as it uses the current rustc version as its cache key\n      - uses: buildjet/cache@v3\n        continue-on-error: true\n        with:\n          path: |\n            ~/.cargo/registry\n            ~/.cargo/git\n            target\n          key: \"${{ matrix.cargo_command }} ${{ matrix.args }} ${{ matrix.package }}\"\n\n      - name: Download Fuel Core\n        if: ${{ matrix.install_fuel_core }}\n        uses: actions/download-artifact@v4\n        with:\n          name: fuel-core\n      - name: Install Fuel Core\n        if: ${{ matrix.install_fuel_core }}\n        run: |\n          chmod +x fuel-core\n          mv fuel-core /usr/local/bin/fuel-core\n\n      - name: Download sway example artifacts\n        if: ${{ matrix.download_sway_artifacts }}\n        uses: actions/download-artifact@v4\n        with:\n          name: ${{ matrix.download_sway_artifacts }}\n          # Needed because `upload-artifact` will remove 'e2e/sway' because it is shared between all matched files\n          path: e2e/sway/\n\n      - name: Install nextest\n        if: ${{ matrix.cargo_command == 'nextest' }}\n        uses: taiki-e/install-action@nextest\n\n      - name: Install cargo-machete\n        if: ${{ matrix.cargo_command == 'machete' }}\n        uses: taiki-e/install-action@cargo-machete\n\n      - name: Cargo (workspace-level)\n        if: ${{ matrix.cargo_command && !matrix.package }}\n        run: cargo ${{ matrix.cargo_command }} ${{ matrix.args }}\n\n      - name: Cargo (package-level)\n        if: ${{ matrix.cargo_command && matrix.package }}\n        run: cargo ${{ matrix.cargo_command }} -p ${{ matrix.package }} ${{ matrix.args }}\n\n      - name: Install NodeJS for WASM testing\n        if: ${{ matrix.command == 'test_wasm' }}\n        uses: actions/setup-node@v3\n        with:\n          node-version: 22.8.0\n\n      # Until we fix the \"missing env error\"\n      # - name: Test WASM\n      #   if: ${{ matrix.command == 'test_wasm' }}\n      #   run: |\n      #     curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh\n      #     cd wasm-tests\n      #     wasm-pack test --node\n\n      - name: Check that fuel_core version.rs file is up to date\n        if: ${{ matrix.command == 'check_fuel_core_version' }}\n        run: cargo run --bin fuel-core-version -- --manifest-path ./Cargo.toml verify\n\n      - name: Check for invalid documentation anchors\n        if: ${{ matrix.command == 'check_doc_anchors_valid' }}\n        run: cargo run --bin check-docs\n\n      - name: Check for unresolved documentation links\n        if: ${{ matrix.command == 'check_doc_unresolved_links' }}\n        run: |\n          ! cargo doc --document-private-items |& grep -A 6  \"warning: unresolved link to\"\n\n      - name: Check for typos\n        if: ${{ matrix.command == 'check_typos' }}\n        uses: crate-ci/typos@v1.29.5\n\n  publish:\n    needs:\n      - cargo-verifications\n      - publish-crates-check\n    # Only do this job if publishing a release\n    if: github.event_name == 'release' && github.event.action == 'published'\n    runs-on: buildjet-4vcpu-ubuntu-2204\n\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@v3\n\n      - uses: dtolnay/rust-toolchain@master\n        with:\n          toolchain: ${{ env.RUST_VERSION }}\n\n      - name: Verify tag version\n        run: |\n          curl -sSLf \"$DASEL_VERSION\" -L -o dasel && chmod +x dasel\n          mv ./dasel /usr/local/bin/dasel\n          ./.github/workflows/scripts/verify_tag.sh ${{ github.ref_name }} Cargo.toml\n      - name: Publish crate\n        uses: FuelLabs/publish-crates@v1\n        with:\n          publish-delay: 30000\n          registry-token: ${{ secrets.CARGO_REGISTRY_TOKEN }}\n"
  },
  {
    "path": ".github/workflows/docs.yml",
    "content": "name: Docs\n\non:\n  push:\n    branches:\n      - master\n  pull_request:\n  release:\n    types: [published]\n\njobs:\n  test:\n    uses: FuelLabs/github-actions/.github/workflows/mdbook-docs.yml@master\n    with:\n      docs-src-path: \"docs/src\"\n      pre-command: 'cargo run --package versions-replacer -- ./docs --manifest-path ./Cargo.toml --filename-regex \"\\.md$\"'\n      spellcheck-config-path: 'docs/.spellcheck.yml'\n"
  },
  {
    "path": ".github/workflows/gh-pages.yml",
    "content": "name: github pages\n\non:\n  push:\n    branches:\n      - master\n    tags:\n      - v*\n\njobs:\n  deploy:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v3\n\n      - name: Setup mdBook\n        uses: peaceiris/actions-mdbook@v1\n        with:\n          mdbook-version: \"0.4.15\"\n\n      - run: mdbook build docs\n\n      - name: Deploy master\n        uses: peaceiris/actions-gh-pages@v3\n        with:\n          github_token: ${{ secrets.GITHUB_TOKEN }}\n          publish_dir: ./docs/book\n          destination_dir: master\n          cname: rust.fuel.network\n        if: github.ref == 'refs/heads/master'\n\n      - name: Get tag\n        id: branch_name\n        run: |\n          echo ::set-output name=BRANCH_NAME::${GITHUB_REF#refs/tags/}\n        if: startsWith(github.ref, 'refs/tags')\n\n      - name: Deploy tag\n        uses: peaceiris/actions-gh-pages@v3\n        with:\n          github_token: ${{ secrets.GITHUB_TOKEN }}\n          publish_dir: ./docs/book\n          destination_dir: ${{ steps.branch_name.outputs.BRANCH_NAME }}\n          cname: rust.fuel.network\n        if: startsWith(github.ref, 'refs/tags')\n\n      - name: Create latest HTML redirect file\n        if: startsWith(github.ref, 'refs/tags')\n        run: |\n          mkdir ./latest\n          cat > ./latest/index.html <<EOF\n          <!DOCTYPE html>\n          <meta charset=\"utf-8\">\n          <meta http-equiv=\"refresh\" content=\"0; URL=../${{ steps.branch_name.outputs.BRANCH_NAME }}/\">\n          <link rel=\"canonical\" href=\"../${{ steps.branch_name.outputs.BRANCH_NAME }}/\">\n          EOF\n\n      - name: Set latest to point to tag\n        uses: peaceiris/actions-gh-pages@v3\n        with:\n          github_token: ${{ secrets.GITHUB_TOKEN }}\n          publish_dir: ./latest/\n          destination_dir: ./latest/\n          cname: rust.fuel.network\n        if: startsWith(github.ref, 'refs/tags')\n"
  },
  {
    "path": ".github/workflows/repo-plan.toml",
    "content": "[current-repo]\nname = \"fuels-rs\"\nowner = \"FuelLabs\"\n\n[repo.fuels-rs.details]\nname = \"fuels-rs\"\nowner = \"FuelLabs\"\n\n[repo.fuel-core.details]\nname = \"fuel-core\"\nowner = \"FuelLabs\"\n\n[repo.fuels-rs]\ndependencies = [\"fuel-core\"]\n"
  },
  {
    "path": ".github/workflows/scripts/verify_tag.sh",
    "content": "#!/usr/bin/env bash\nset -e\n\nerr() {\n    echo -e \"\\e[31m\\e[1merror:\\e[0m $@\" 1>&2;\n}\n\nstatus() {\n    WIDTH=12\n    printf \"\\e[32m\\e[1m%${WIDTH}s\\e[0m %s\\n\" \"$1\" \"$2\"\n}\n\nREF=$1\nMANIFEST=$2\n\nif [ -z \"$REF\" ]; then\n    err \"Expected ref to be set\"\n    exit 1\nfi\n\nif [ -z \"$MANIFEST\" ]; then\n    err \"Expected manifest to be set\"\n    exit 1\nfi\n\n# strip preceding 'v' if it exists on tag\nREF=${REF/#v}\nTOML_VERSION=$(cat $MANIFEST | dasel -r toml -w plain 'workspace.package.version')\n\nif [ \"$TOML_VERSION\" != \"$REF\" ]; then\n    err \"Crate version $TOML_VERSION, doesn't match tag version $REF\"\n    exit 1\nelse\n  status \"Crate version matches tag $TOML_VERSION\"\nfi\n"
  },
  {
    "path": ".gitignore",
    "content": "# Generated by Cargo\n# will have compiled files and executables\ntarget/\n\n# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries\n# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html\nCargo.lock\n\n# These are backup files generated by rustfmt\n**/*.rs.bk\n\n# Don't add the generated MDBook artifacts\ndocs/book/\n\n# Don't add Forc lock files\n**/Forc.lock\n\n# Don't add out/ files from test Sway projects.\ne2e/sway/**/out/\ne2e/sway/**/.gitignore\n\n.env\n\noutput_changelog.md\n"
  },
  {
    "path": ".markdownlint.yaml",
    "content": "\"default\": true # Default state for all rules\n\"MD013\": false # Disable rule for line length\n\"MD033\": false # Disable rule banning inline HTML"
  },
  {
    "path": ".markdownlintignore",
    "content": "README.md\nscripts/check-docs"
  },
  {
    "path": "Cargo.toml",
    "content": "[workspace]\n# Use the new resolver to prevent dev-deps and build-deps from enabling debugging or test features in production.\n#\n# > If you are using a virtual workspace, you will still need to explicitly set the resolver field in the [workspace]\n#   definition if you want to opt-in to the new resolver.\n# https://doc.rust-lang.org/edition-guide/rust-2021/default-cargo-resolver.html#details\nresolver = \"2\"\nmembers = [\n  \"e2e\",\n  \"examples/codec\",\n  \"examples/contracts\",\n  \"examples/cookbook\",\n  \"examples/debugging\",\n  \"examples/macros\",\n  \"examples/predicates\",\n  \"examples/providers\",\n  \"examples/rust_bindings\",\n  \"examples/types\",\n  \"examples/wallets\",\n  \"packages/fuels\",\n  \"packages/fuels-accounts\",\n  \"packages/fuels-code-gen\",\n  \"packages/fuels-core\",\n  \"packages/fuels-macros\",\n  \"packages/fuels-programs\",\n  \"packages/fuels-test-helpers\",\n  \"scripts/change-log\",\n  \"scripts/check-docs\",\n  \"scripts/fuel-core-version\",\n  \"scripts/versions-replacer\",\n  \"wasm-tests\",\n]\n\n[workspace.package]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nedition = \"2024\"\nhomepage = \"https://fuel.network/\"\nreadme = \"README.md\"\nlicense = \"Apache-2.0\"\nrepository = \"https://github.com/FuelLabs/fuels-rs\"\nrust-version = \"1.93.0\"\nversion = \"0.76.0\"\n\n[workspace.dependencies]\nInflector = \"0.11.4\"\nanyhow = { version = \"1.0\", default-features = false }\ndialoguer = { version = \"0.11\", default-features = false }\nasync-trait = { version = \"0.1.74\", default-features = false }\nbytes = { version = \"1.5.0\", default-features = false }\nchrono = \"0.4.31\"\ncynic = { version = \">=3.1.0, <3.13.0\", default-features = false }\ntest-case = { version = \"3.3\", default-features = false }\neth-keystore = \"0.5.0\"\nflate2 = { version = \"1.0\", default-features = false }\nfuel-abi-types = \"0.15.3\"\nfutures = \"0.3.29\"\nhex = { version = \"0.4.3\", default-features = false }\nitertools = \"0.12.0\"\nportpicker = \"0.1.1\"\npretty_assertions = { version = \"1.4\", default-features = false }\nproc-macro2 = \"1.0.70\"\nquote = \"1.0.33\"\nrand = { version = \"0.8.5\", default-features = false, features = [\n  \"std_rng\",\n  \"getrandom\",\n] }\nregex = \"1.10.2\"\nreqwest = { version = \"0.12\", default-features = false }\nsemver = \"1.0.20\"\nserde = { version = \"1.0.193\", default-features = false }\nserde_json = \"1.0.108\"\nserde_with = { version = \"3.4.0\", default-features = false }\nauto_impl = { version = \"1.0\", default-features = false }\nsha2 = { version = \"0.10.8\", default-features = false }\nsyn = \"2.0.39\"\ntai64 = { version = \"4.0.0\", default-features = false }\ntar = { version = \"0.4\", default-features = false }\ntempfile = { version = \"3.8.1\", default-features = false }\nthiserror = { version = \"1.0.50\", default-features = false }\ntokio = { version = \"1.34.0\", default-features = false }\ntracing = \"0.1.40\"\ntrybuild = \"1.0.85\"\nuint = { version = \"0.9.5\", default-features = false }\nwhich = { version = \"6.0.0\", default-features = false }\nzeroize = \"1.7.0\"\noctocrab = { version = \"0.43\", default-features = false }\ndotenv = { version = \"0.15\", default-features = false }\ntoml = { version = \"0.8\", default-features = false }\nmockall = { version = \"0.13\", default-features = false }\ngoogle-cloud-kms = { version = \"0.6\", default-features = false }\naws-config = { version = \"1\", default-features = false }\naws-sdk-kms = { version = \"1\", default-features = false }\ntestcontainers = { version = \"0.23\", default-features = false }\nk256 = { version = \"0.13\", default-features = false }\n\n# Dependencies from the `fuel-core` repository:\nfuel-core = { version = \"0.47.1\", default-features = false, features = [\n  \"wasm-executor\",\n] }\nfuel-core-chain-config = { version = \"0.47.1\", default-features = false }\nfuel-core-client = { version = \"0.47.1\", default-features = false }\nfuel-core-poa = { version = \"0.47.1\", default-features = false }\nfuel-core-services = { version = \"0.47.1\", default-features = false }\nfuel-core-types = { version = \"0.47.1\", default-features = false }\n\n# Dependencies from the `fuel-vm` repository:\nfuel-asm = { version = \"0.65.0\" }\nfuel-crypto = { version = \"0.65.0\" }\nfuel-merkle = { version = \"0.65.0\" }\nfuel-storage = { version = \"0.65.0\" }\nfuel-tx = { version = \"0.65.0\" }\nfuel-types = { version = \"0.65.0\" }\nfuel-vm = { version = \"0.65.0\" }\n\n# Workspace projects\nfuels = { version = \"0.76.0\", path = \"./packages/fuels\", default-features = false }\nfuels-accounts = { version = \"0.76.0\", path = \"./packages/fuels-accounts\", default-features = false }\nfuels-code-gen = { version = \"0.76.0\", path = \"./packages/fuels-code-gen\", default-features = false }\nfuels-core = { version = \"0.76.0\", path = \"./packages/fuels-core\", default-features = false }\nfuels-macros = { version = \"0.76.0\", path = \"./packages/fuels-macros\", default-features = false }\nfuels-programs = { version = \"0.76.0\", path = \"./packages/fuels-programs\", default-features = false }\nfuels-test-helpers = { version = \"0.76.0\", path = \"./packages/fuels-test-helpers\", default-features = false }\nversions-replacer = { version = \"0.76.0\", path = \"./scripts/versions-replacer\", default-features = false }\n"
  },
  {
    "path": "LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "README.md",
    "content": "# fuels-rs\n\n[![build](https://github.com/FuelLabs/fuels-rs/actions/workflows/ci.yml/badge.svg)](https://github.com/FuelLabs/fuels-rs/actions/workflows/ci.yml)\n[![crates.io](https://img.shields.io/crates/v/fuels?label=latest)](https://crates.io/crates/fuels)\n[![docs](https://docs.rs/fuels/badge.svg)](https://docs.rs/fuels)\n[![discord](https://img.shields.io/badge/chat%20on-discord-orange?&logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2)](https://discord.gg/xfpK4Pe)\n\nRust SDK for Fuel. It can be used for a variety of things, including but not limited to:\n\n- Compiling, deploying, and testing [Sway](https://github.com/FuelLabs/sway) contracts;\n- Launching a local Fuel network;\n- Crafting and signing transactions with hand-crafted scripts or contract calls;\n- Generating type-safe Rust bindings of contract methods;\n- And more, `fuels-rs` is still in active development.\n\n## Documentation\n\nSee [the `fuels-rs` book](https://fuellabs.github.io/fuels-rs/latest/)\n\n## Features\n\n- [x] Launch Fuel nodes\n- [x] Deploy contracts\n- [x] Interact with deployed contracts\n- [x] Type-safe Sway contracts bindings code generation\n- [x] Run Sway scripts\n- [x] CLI for common operations\n- [x] Local test wallets\n- [ ] Wallet integration\n- [ ] Events querying/monitoring\n\n## FAQ\n\n### What dependencies do I need?\n\n- [The latest `stable` Rust toolchain](https://docs.fuel.network/guides/installation/#installing-rust);\n- [`forc` and `fuel-core` binaries](https://docs.fuel.network/guides/installation/#installing-the-fuel-toolchain-using-fuelup).\n\n### How can I run the SDK tests?\n\nFirst, build the test projects using `forc`:\n\n```shell\nforc build --release --path e2e\n```\n\nThen you can run the SDK tests with:\n\n```shell\ncargo test\n```\n\nYou can also run specific tests. The following example will run all integration tests in `types.rs` whose names contain `in_vector` and show their outputs:\n\n```shell\ncargo test --test types in_vector -- --show-output\n```\n\n### How to run WASM tests?\n\nYou need to have wasm32 as a target, if you don't already:\n\n```shell\n rustup target add wasm32-unknown-unknown\n```\n\nYou also need `wasm-pack`, if you don't already:\n\n```shell\ncargo install wasm-pack\n```\n\nNavigate to `packages/wasm-tests` and run `wasm-pack test`.\n\n### What to do if my tests are failing on `master`\n\nBefore doing anything else, try all these commands:\n\n```shell\ncargo clean\nrm Cargo.lock\nforc build --release --path e2e\ncargo test\n```\n\n### Why is the prefix `fuels` and not `fuel`?\n\nIn order to make the SDK for Fuel feel familiar with those coming from the [ethers.js](https://github.com/ethers-io/ethers.js) ecosystem, this project opted for an `s` at the end. The `fuels-*` family of SDKs is inspired by The Ethers Project.\n\n### How can I run the docs locally?\n\nInstall `mdbook` by running:\n\n```shell\ncargo install mdbook\n```\n\nNext, navigate to the `docs` folder and run the command below to start a local server and open a new tab in your browser.\n\n```shell\nmdbook serve --open\n```\n\nYou can build the book by running:\n\n```shell\nmdbook build\n```\n"
  },
  {
    "path": "SECURITY.md",
    "content": "# Fuel Security Policy\n\nThank you for helping make the Fuel ecosystem safe for everyone. The Fuel team take security bugs very seriously. We appreciate your efforts to responsibly disclose your findings, and will make every effort to acknowledge your contributions.\n\n## Reporting Security Issues\n\nIf you believe you have found a security vulnerability in any Fuel-owned repository, please report it to us through coordinated disclosure.\n\n**Please do not report security vulnerabilities through public GitHub issues, discussions, or pull requests.**\n\nInstead, please use the GitHub Security Advisory [\"Report a Vulnerability\"](https://github.com/FuelLabs/fuels-rs/security/advisories/new) tab.\n\nThe Fuel team will send a response indicating the next steps in handling your report. After the initial reply to your report, the team will keep you informed of the progress towards a fix and full announcement, and may ask for additional information or guidance.\n\nPlease include as much of the information listed below as you can to help us better understand and resolve the issue:\n\n* The type of issue (e.g., buffer overflow, SQL injection, or cross-site scripting)\n* Full paths of source file(s) related to the manifestation of the issue\n* The location of the affected source code (tag/branch/commit or direct URL)\n* Any special configuration required to reproduce the issue\n* Step-by-step instructions to reproduce the issue\n* Proof-of-concept or exploit code (if possible)\n* Impact of the issue, including how an attacker might exploit the issue\n\nThis information will help us triage your report more quickly.\n\nReport security bugs in third-party modules to the person or team maintaining the module.\n\n## Non-Security Issues\n\nIf the issue is not security-related, please report it publicly by opening a [GitHub Issue](https://github.com/FuelLabs/fuels-rs/issues/new).\n"
  },
  {
    "path": "_typos.toml",
    "content": "[files]\nextend-exclude = [\"packages/fuels-accounts/src/schema/schema.sdl\"]"
  },
  {
    "path": "ci_checks.sh",
    "content": "#!/usr/bin/env bash\n\n# Requires installed:\n# The latest version of the `forc`,`forc-fmt` and `fuel-core`.\n# `cargo install fuel-core-bin --git https://github.com/FuelLabs/fuel-core --tag v0.18.1 --locked`\n# `cargo install forc --git https://github.com/FuelLabs/sway --tag v0.38.0 --locked`\n# `cargo install forc-fmt --git https://github.com/FuelLabs/sway --tag v0.38.0 --locked`\n# Note, if you need a custom branch, you can replace `--tag {RELEASE}` with the `--branch {BRANCH_NAME}`.\n\ncargo fmt --all -- --check &&\n\tforc fmt --check --path e2e &&\n\tforc build --release --terse --path e2e &&\n\tcargo clippy --all-targets &&\n\tforc build --release --terse --path e2e &&\n\tcargo clippy --all-targets --all-features &&\n\tcargo test --all-targets --all-features &&\n\tcargo test --all-targets --all-features --workspace &&\n\tcargo test --all-targets --workspace &&\n\tcargo run --bin check-docs &&\n\t$(cargo doc |& grep -A 6 \"warning: unresolved link to\")\n"
  },
  {
    "path": "docs/.spellcheck.yml",
    "content": "matrix:\n    - name: SPCheck\n      aspell:\n        lang: en\n      dictionary:\n        encoding: utf-8\n        wordlists:\n          - docs/spell-check-custom-words.txt\n      pipeline:\n        - pyspelling.filters.context:\n            context_visible_first: true\n            escapes: \\\\[\\\\`~]\n            delimiters:\n            # Ignore all code blocks\n            - open: '(?s)^(?P<open> *`{3,}\\s*(\\w+\\s*,?\\s*)+.*?)$'\n              close: '^( *`{3,})$'\n        - pyspelling.filters.markdown:\n            markdown_extensions:\n              - pymdownx.superfences:\n        - pyspelling.filters.html:\n            comments: false\n            ignores:\n              - code\n              - pre\n      sources:\n        - 'docs/*.md'\n        - 'docs/src/*.md'\n        - 'docs/src/**/*.md'\n      default_encoding: utf-8\n  "
  },
  {
    "path": "docs/book.toml",
    "content": "[book]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nlanguage = \"en\"\nmultilingual = false\nsrc = \"src\"\ntitle = \"The Fuel Rust SDK\"\n\n[output.html]\ngit-repository-url = \"https://github.com/FuelLabs/fuels-rs\"\n\n[rust]\nedition = \"2021\"\n"
  },
  {
    "path": "docs/spell-check-custom-words.txt",
    "content": "ABI\nABIs\nALU\nAPIs\nASM\nAST\nAssemblyScript\nBitwise\nBooleans\nBrowserStack\nCEI\nCLI\nCardinality\nChangelog\nCodec\nCollateralized\nDApp\nDCA\nDEX\nDOT\nDSL\nDeserialization\nDockerized\nEOA\nERC\nETH\nEVM\nEVM's\nEthereum\nEthereum's\nFVM\nFuelLabs\nFuelVM\nFuelVM's\nFuelup\nGitHub\nGithub\nGraphQL\nGraphViz\nHD\nHomebrew\nIDE\nIDEs\nIPFS\nIaaS\nInfura\nIntrinsics\nJSON\nJWT\nKMS\nKeystore\nKms\nLSP\nMacOS\nMacbook\nMerkle\nMiB\nOrchestrator\nPRs\nPoA\nPoS\nPoW\nPostgreSQL\nPostgres\nRPC\nRocksDB\nSDK\nSDK's\nSDKs\nSHA\nSQLx\nSRC\nSauceLabs\nSchemas\nSepolia\nStructs\nSubcommands\nSubcurrency\nSuperABIs\nSupertraits\nSway\nTAI\nTLDR\nTODO\nTOML\nTypeChain\nTypeScript\nUI\nUTF\nUTXO\nUTXOs\nUpdatable\nUtils\nVM\nVMs\nVS\nVSCode\nWASM\nWebAssembly\nWorkspaces\nYAML\nabigen\nargs\narity\nasync\nbackend\nbackends\nbacktrace\nbacktraces\nblockchain\nblockchain's\nblockchains\nboolean\nbytecode\ncalldata\ncodebase\ncodec\ncodespace\ncodespaces\ncollateralized\ncompositional\nconfig\nconfigurables\ncryptographic\ncryptographically\ncustomizable\ncustomizations\ndApp\ndApps\ndapp\ndecrypt\ndeployable\ndereference\ndereferenced\ndereferencing\ndeserializing\ndestructuring\ndeterministically\ndev\ndropdown\nentrancy\nenum\nenums\nenv\nforc\nformatter\nfrontend\nfuelup\nfullstack\ngraphQL\ngraphql\ngrowable\nhoc\nhttp\nhttps\nincrementor\nindexable\ninitializer\ninitializers\ninlines\ninlining\ninstantiation\ninteroperable\nintrinsics\njs\nkeccak\nkms\nlocalhost\nlookups\nmacOS\nmainnet\nmempool\nmerkle\nmonomorphization\nmonorepo\nmonorepos\nnamespace\nnamespaces\nnatively\nneovim\nnpm\nnvm\nonboarding\norchestrator\nparams\npnpm\npre\nprerelease\nqueryable\nquickstart\nrelayer\nrelayers\nrepo\nrepos\nroadmap\nrunnable\nruntime\nruntimes\nschemas\nsemver\nstateful\nstruct\nstruct's\nstructs\nsubcommand\nsubcommands\nsubcurrency\nsubmodule\nsuperABI\nsuperABIs\nsuperset\nsupertrait\nsupertraits\ntestnet\ntestnets\ntoolchain\ntoolchains\ntuple's\nturbofish\ntypeclass\nunary\nurql\nvalidator\nvalidators\nworkspace\nworkspaces\n"
  },
  {
    "path": "docs/src/SUMMARY.md",
    "content": "# Summary\n\n[The Fuel Rust SDK](./index.md)\n\n- [Getting Started](./getting-started.md)\n- [Connecting to a Fuel node](./connecting/index.md)\n  - [Connecting to the Testnet or an external node](./connecting/external-node.md)\n  - [Running a short-lived Fuel node with the SDK](./connecting/short-lived.md)\n  - [RocksDB](./connecting/rocksdb.md)\n  - [Querying the blockchain](./connecting/querying.md)\n  - [Retrying upon errors](./connecting/retrying.md)\n- [Accounts](./accounts.md)\n- [Managing wallets](./wallets/index.md)\n  - [Using private keys](./wallets/private_key_signer.md)\n  - [Keystore](./wallets/keystore.md)\n  - [Using KMS](./wallets/kms.md)\n  - [Using a fake signer/impersonating an account](./wallets/fake_signer.md)\n  - [Querying](./wallets/checking-balances-and-coins.md)\n  - [Testing](./wallets/test-wallets.md)\n  - [Locking](./wallets/access.md)\n  - [Signing](./wallets/signing.md)\n- [Generating bindings with `abigen!`](./abigen/index.md)\n  - [The JSON ABI file](abigen/the-json-abi-file.md)\n  - [The `abigen!` macro](abigen/the-abigen-macro.md)\n- [Deploying contracts](./deploying/index.md)\n  - [Configurable constants](./deploying/configurable-constants.md)\n  - [Storage slots](./deploying/storage-slots.md)\n  - [Interacting with contracts](./deploying/interacting-with-contracts.md)\n  - [The FuelVM Binary file](./deploying/the-fuelvm-binary-file.md)\n  - [Large contracts](./deploying/large_contracts.md)\n- [Calling contracts](./calling-contracts/index.md)\n  - [Connecting wallets](./calling-contracts/calls-with-different-wallets.md)\n  - [Transaction policies](./calling-contracts/tx-policies.md)\n  - [Call parameters](./calling-contracts/call-params.md)\n  - [Custom asset transfer](./calling-contracts/custom-asset-transfer.md)\n  - [Custom inputs and outputs](./calling-contracts/custom-inputs-outputs.md)\n  - [Call response](./calling-contracts/call-response.md)\n  - [Logs](./calling-contracts/logs.md)\n  - [Variable outputs and messages](./calling-contracts/variable-outputs.md)\n  - [Simulating calls](./calling-contracts/simulation.md)\n  - [Calling other contracts](./calling-contracts/other-contracts.md)\n  - [Multiple contract calls](./calling-contracts/multicalls.md)\n  - [Transaction dependency estimation](./calling-contracts/tx-dependency-estimation.md)\n  - [Estimating cost](./calling-contracts/cost-estimation.md)\n  - [Low-level calls](./calling-contracts/low-level-calls.md)\n- [Running scripts](./running-scripts.md)\n- [Predicates](./predicates/index.md)\n  - [Signatures example](./predicates/send-spend-predicate.md)\n- [Pre-uploading code](./preuploading-code.md)\n- [Custom transactions](./custom-transactions/index.md)\n  - [Transaction builders](./custom-transactions/transaction-builders.md)\n  - [Custom contract and script calls](./custom-transactions/custom-calls.md)\n- [Types](./types/index.md)\n  - [`Bytes32`](./types/bytes32.md)\n  - [`Address`](./types/address.md)\n  - [`ContractId`](./types/contract-id.md)\n  - [`AssetId`](./types/asset-id.md)\n  - [Structs and enums](./types/custom_types.md)\n  - [`String`](./types/string.md)\n  - [`Bits256`](./types/bits256.md)\n  - [`Bytes`](./types/bytes.md)\n  - [`B512`](./types/B512.md)\n  - [`EvmAddress`](./types/evm_address.md)\n  - [Vectors](./types/vectors.md)\n  - [Converting types](./types/conversion.md)\n- [Codec](./codec/index.md)\n  - [Encoding](./codec/encoding.md)\n  - [Decoding](./codec/decoding.md)\n- [API Reference](./reference.md)\n- [Testing](./testing/index.md)\n  - [Testing basics](./testing/basics.md)\n  - [The `setup_program_test!` macro](testing/the-setup-program-test-macro.md)\n  - [Tweaking the blockchain](./testing/chains.md)\n- [Cookbook](./cookbook/index.md)\n  - [Custom consensus parameters](./cookbook/custom-chain.md)\n  - [Deposit and Withdraw](./cookbook/deposit-and-withdraw.md)\n  - [Transfer all assets](./cookbook/transfer-all-assets.md)\n- [Debugging](./debugging/index.md)\n  - [The Function selector](./debugging/function-selector.md)\n  - [Decoding script transactions](./debugging/decoding-script-transactions.md)\n- [Glossary](./glossary.md)\n- [Contributing](./contributing/CONTRIBUTING.md)\n  - [Integration tests structure](./contributing/tests-structure.md)\n- [Command Line Interfaces](./cli/index.md)\n  - [`fuels-abi-cli`](./cli/fuels-abi-cli.md)\n"
  },
  {
    "path": "docs/src/abigen/index.md",
    "content": "# Generating bindings with abigen\n\nYou might have noticed this snippet in the previous sections:\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:abigen_example}}\n```\n\n<!-- This section should explain the purpose of the abigen -->\n<!-- abigen:example:start -->\nThe SDK lets you transform ABI methods of a smart contract, specified as JSON objects (which you can get from [Forc](https://github.com/FuelLabs/sway/tree/master/forc)), into Rust structs and methods that are type-checked at compile time.\nIn order to call your contracts, scripts or predicates, you first need to generate the Rust bindings for them.\n<!-- abigen:example:end -->\n\nThe following subsections contain more details about the `abigen!` syntax and the code generated from it.\n"
  },
  {
    "path": "docs/src/abigen/the-abigen-macro.md",
    "content": "# abigen\n\n<!-- This section explain the `abigen!` macro -->\n<!-- abigen:example:start -->\n`abigen!` is a procedural macro -- it generates code. It accepts inputs in the format of:\n\n```text\nProgramType(name=\"MyProgramType\", abi=\"my_program-abi.json\")...\n```\n\nwhere:\n\n- `ProgramType` is one of: `Contract`, `Script` or `Predicate`,\n\n- `name` is the name that will be given to the generated bindings,\n\n- `abi` is either a path to the JSON ABI file or its actual contents.\n<!-- abigen:example:end -->\n\n---\nSo, an `abigen!` which generates bindings for two contracts and one script looks like this:\n\n```rust,ignore\n{{#include ../../../examples/macros/src/lib.rs:multiple_abigen_program_types}}\n```\n\n## How does the generated code look?\n\nA rough overview:\n\n```rust,ignore\npub mod abigen_bindings {\n    pub mod contract_a_mod {\n        struct SomeCustomStruct{/*...*/};\n        // other custom types used in the contract\n\n        struct ContractA {/*...*/};\n        impl ContractA {/*...*/};\n        // ...\n    }\n    pub mod contract_b_mod {\n        // ...\n    }\n    pub mod my_script_mod {\n        // ...\n    }\n    pub mod my_predicate_mod{\n        // ...\n    }\n    pub mod shared_types{\n        // ...\n    }\n}\n\npub use contract_a_mod::{/*..*/};\npub use contract_b_mod::{/*..*/};\npub use my_predicate_mod::{/*..*/};\npub use shared_types::{/*..*/};\n```\n\nEach `ProgramType` gets its own `mod` based on the `name` given in the `abigen!`. Inside the respective mods, the custom types used by that program are generated, and the bindings through which the actual calls can be made.\n\nOne extra `mod` called `shared_types` is generated if `abigen!` detects that the given programs share types. Instead of each `mod` regenerating the type for itself, the type is lifted out into the `shared_types` module, generated only once, and then shared between all program bindings that use it. Reexports are added to each mod so that even if a type is deemed shared, you can still access it as though each `mod` had generated the type for itself (i.e. `my_contract_mod::SharedType`).\n\nA type is deemed shared if its name and definition match up. This can happen either because you've used the same library (a custom one or a type from the `stdlib`) or because you've happened to define the exact same type.\n\nFinally, `pub use` statements are inserted, so you don't have to fully qualify the generated types. To avoid conflict, only types that have unique names will get a `pub use` statement. If you find `rustc` can't find your type, it might just be that there is another generated type with the same name. To fix the issue just qualify the path by doing `abigen_bindings::whatever_contract_mod::TheType`.\n\n> **Note:**\n> It is **highly** encouraged that you generate all your bindings in one `abigen!` call. Doing it in this manner will allow type sharing and avoid name collisions you'd normally get when calling `abigen!` multiple times inside the same namespace. If you choose to proceed otherwise, keep in mind the generated code overview presented above and appropriately separate the `abigen!` calls into different modules to resolve the collision.\n\n## Using the bindings\n\nLet's look at a contract with two methods: `initialize_counter(arg: u64) -> u64` and `increment_counter(arg: u64) -> u64`, with the following JSON ABI:\n\n```json,ignore\n{{#include ../../../examples/rust_bindings/src/abi.json}}\n```\n\nBy doing this:\n\n```rust,ignore\n{{#include ../../../examples/rust_bindings/src/lib.rs:use_abigen}}\n```\n\nor this:\n\n```rust,ignore\n{{#include ../../../examples/rust_bindings/src/lib.rs:abigen_with_string}}\n```\n\nyou'll generate this (shortened for brevity's sake):\n\n```rust,ignore\n{{#include ../../../examples/rust_bindings/src/rust_bindings_formatted.rs}}\n```\n\n> **Note:** that is all **generated** code. No need to write any of that. Ever. The generated code might look different from one version to another, this is just an example to give you an idea of what it looks like.\n\nThen, you're able to use it to call the actual methods on the deployed contract:\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:use_deployed_contract}}\n```\n"
  },
  {
    "path": "docs/src/abigen/the-json-abi-file.md",
    "content": "# The JSON ABI file\n\n<!-- This section should talk about the importance of the ABI -->\n<!-- abi:example:start -->\nWhether you want to deploy or connect to a pre-existing smart contract, the JSON ABI file is extremely important: it's what tells the SDK about the [ABI methods](https://docs.fuel.network/guides/quickstart/building-a-smart-contract/#abi) in your smart contracts.\n<!-- abi:example:end -->\n\nFor the same example Sway code as above:\n\n```Rust\ncontract;\n\nabi MyContract {\n    fn test_function() -> bool;\n}\n\nimpl MyContract for Contract {\n    fn test_function() -> bool {\n        true\n    }\n}\n```\n\nThe JSON ABI file looks like this:\n\n```json\n$ cat out/release/my-test-abi.json\n[\n  {\n    \"type\": \"function\",\n    \"inputs\": [],\n    \"name\": \"test_function\",\n    \"outputs\": [\n      {\n        \"name\": \"\",\n        \"type\": \"bool\",\n        \"components\": null\n      }\n    ]\n  }\n]\n```\n\nThe Fuel Rust SDK will take this file as input and generate equivalent methods (and custom types if applicable) that you can call from your Rust code.\n"
  },
  {
    "path": "docs/src/accounts.md",
    "content": "# Accounts\n\nThe `ViewOnlyAccount` trait provides a common interface to query balances.\n\nThe `Account` trait, in addition to the above, also provides a way to transfer assets. When performing actions in the SDK that lead to a transaction, you will typically need to provide an account that will be used to allocate resources required by the transaction, including transaction fees.\n\nThe traits are implemented by the following types:\n\n- [`Wallet`](./wallets/index.md)\n- [`Predicate`](./predicates/index.md)\n\n## Transferring assets\n\nAn account implements the following methods for transferring assets:\n\n- `transfer`\n- `force_transfer_to_contract`\n- `withdraw_to_base_layer`\n\nThe following examples are provided for a `Wallet` account. A `Predicate` account would work similarly, but you might need to set its predicate data before attempting to spend resources owned by it.\n\nWith `wallet.transfer` you can initiate a transaction to transfer an asset from your account to a target address.\n\n```rust,ignore\n{{#include ../../examples/wallets/src/lib.rs:wallet_transfer}}\n```\n\nYou can transfer assets to a contract via `wallet.force_transfer_to_contract`.\n\n```rust,ignore\n{{#include ../../examples/wallets/src/lib.rs:wallet_contract_transfer}}\n```\n\nFor transferring assets to the base layer chain, you can use `wallet.withdraw_to_base_layer`.\n\n```rust,ignore\n{{#include ../../examples/wallets/src/lib.rs:wallet_withdraw_to_base}}\n```\n\nThe above example creates an `Address` from a string. Next, it calls `wallet.withdraw_to_base_layer` by providing the address, the amount to be transferred, and the transaction policies. Lastly, to verify that the transfer succeeded, the relevant message proof is retrieved with `provider.get_message_proof,` and the amount and the recipient are verified.\n"
  },
  {
    "path": "docs/src/calling-contracts/call-params.md",
    "content": "# Call parameters\n\n<!-- This section should explain what the call params are and how to configure them -->\n<!-- call_params:example:start -->\nThe parameters for a contract call are:\n\n1. Amount\n2. Asset ID\n3. Gas forwarded\n<!-- call_params:example:end -->\n\nYou can use these to forward coins to a contract. You can configure these parameters by creating an instance of [`CallParameters`](https://docs.rs/fuels/latest/fuels/programs/calls/struct.CallParameters.html) and passing it to a chain method called `call_params`.\n<!-- use_call_params:example:end -->\n\nFor instance, suppose the following contract that uses Sway's `msg_amount()` to return the amount sent in that transaction.\n\n```rust,ignore\n{{#include ../../../e2e/sway/contracts/contract_test/src/main.sw:msg_amount}}\n```\n\nThen, in Rust, after setting up and deploying the above contract, you can configure the amount being sent in the transaction like this:\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:call_parameters}}\n```\n\n<!-- This section should explain why `call_params` returns a result -->\n<!-- payable:example:start -->\n`call_params` returns a result to ensure you don't forward assets to a contract method that isn't payable.\n<!-- payable:example:end -->\nIn the following example, we try to forward an amount of `100` of the base asset to `non_payable`. As its name suggests, `non_payable` isn't annotated with `#[payable]` in the contract code. Passing `CallParameters` with an amount other than `0` leads to an error:\n\n```rust,ignore\n{{#include ../../../e2e/tests/contracts.rs:non_payable_params}}\n```\n\n> **Note:** forwarding gas to a contract call is always possible, regardless of the contract method being non-payable.\n\nYou can also use `CallParameters::default()` to use the default values:\n\n```rust,ignore\n{{#include ../../../packages/fuels-core/src/utils/constants.rs:default_call_parameters}}\n```\n\nThis way:\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:call_parameters_default}}\n```\n\n<!-- This section should explain what the `gas_forwarded` parameter does -->\n<!-- gas:example:start -->\nThe `gas_forwarded` parameter defines the limit for the actual contract call as opposed to the gas limit for the whole transaction. This means that it is constrained by the transaction limit. If it is set to an amount greater than the available gas, all available gas will be forwarded.\n<!-- gas:example:end -->\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:call_params_gas}}\n```\n\n<!-- This section should explain the default forwarding behavior for a call -->\n<!-- forwarding:example:start -->\nIf you don't set the call parameters or use `CallParameters::default()`, the transaction gas limit will be forwarded instead.\n<!-- forwarding:example:end -->\n"
  },
  {
    "path": "docs/src/calling-contracts/call-response.md",
    "content": "# Call response\n\n<!-- This section should why you have to chain `.call().await.unwrap()` so often -->\n<!-- chaining:example:start -->\nYou've probably noticed that you're often chaining `.call().await.unwrap()`. That's because:\n\n1. You have to choose between `.call()` and `.simulate()` (more on this in the next section).\n2. Contract calls are asynchronous, so you can choose to either `.await` it or perform concurrent tasks, making full use of Rust's async.\n3. `.unwrap()` the `Result<CallResponse, Error>` returned by the contract call.\n<!-- chaining:example:end -->\n\n<!-- This section should preface what the `CallResponse` is -->\n<!-- call_resp:example:start -->\nOnce you unwrap the `CallResponse`, you have access to this struct:\n<!-- call_resp:example:end -->\n\n```rust,ignore\n{{#include ../../../packages/fuels-programs/src/responses/call.rs:call_response}}\n```\n\n<!-- This section should explain the fields of the `CallResponse` struct -->\n<!-- call_resp_fields:example:start -->\nWhere `value` will hold the value returned by its respective contract method, represented by the exact type returned by the FuelVM, E.g., if your contract returns a FuelVM's `u64`, `value`'s `D` will be a `u64`. If it's a FuelVM's tuple `(u8,bool)`, then `D` will be a `(u8,bool)`. If it's a custom type, for instance, a Sway struct `MyStruct` containing two components, a `u64`, and a `b256`, `D` will be a struct generated at compile-time, called `MyStruct` with `u64` and a `[u8; 32]` (the equivalent of `b256` in Rust).\n\n- `receipts` will hold all [receipts](https://docs.fuel.network/docs/specs/abi/receipts/) generated by that specific contract call.\n- `gas_used` is the amount of gas consumed by the contract call.\n- `tx_id` will hold the ID of the corresponding submitted transaction.\n<!-- call_resp_fields:example:end -->\n\n## Error handling\n\n<!-- This section should explain how to use the `is_ok` and `is_err` methods for a call response -->\n<!-- call_resp_ok:example:start -->\nYou can use the `is_ok` and `is_err` methods to check if a contract call `Result` is `Ok` or contains an error. These methods will return either `true` or `false`.\n<!-- call_resp_ok:example:end -->\n\n<!-- This section should show an example of how to use the `is_ok` and `is_err` methods for a call response -->\n<!-- call_resp_ok_code:example:start -->\n```rust, ignore\nlet is_ok = response.is_ok();\nlet is_error = response.is_err();\n```\n<!-- call_resp_ok_code:example:end -->\n\n<!-- This section should explain how to use the `unwrap_err` method for a call response -->\n<!-- call_resp_error:example:start -->\nIf `is_err` returns `true`, you can use the `unwrap_err` method to unwrap the error message.\n<!-- call_resp_error:example:end -->\n\n<!-- This section should show an example of how to unwrap a call response error -->\n<!-- call_resp_error_code:example:start -->\n```rust, ignore\nif response.is_err() {\n    let err = response.unwrap_err();\n    println!(\"ERROR: {:?}\", err);\n};\n```\n<!-- call_resp_error_code:example:end -->\n"
  },
  {
    "path": "docs/src/calling-contracts/calls-with-different-wallets.md",
    "content": "# Calls with different wallets\n\n<!-- This section should explain how to call a contract with a certain wallet -->\n<!-- wallet:example:start -->\nYou can use the `with_account()` method on an existing contract instance as a shorthand for creating a new instance connected to the provided wallet. This lets you make contracts calls with different wallets in a chain like fashion.\n<!-- wallet:example:end-->\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:connect_wallet}}\n```\n\n> **Note:** connecting a different wallet to an existing instance ignores its set provider in favor of the provider used to deploy the contract. If you have two wallets connected to separate providers (each communicating with a separate fuel-core), the one assigned to the deploying wallet will also be used for contract calls. This behavior is only relevant if multiple providers (i.e. fuel-core instances) are present and can otherwise be ignored.\n"
  },
  {
    "path": "docs/src/calling-contracts/cost-estimation.md",
    "content": "# Estimating contract call cost\n\nWith the function `estimate_transaction_cost(tolerance: Option<f64>, block_horizon: Option<u32>)` provided by `CallHandler`, you can get a cost estimation for a specific call. The return type, `TransactionCost`, is a struct that contains relevant information for the estimation:\n\n```rust,ignore\n{{#include ../../../packages/fuels-accounts/src/provider.rs:transaction_cost}}\n```\n\n> **Note** `script_gas` refers to the part of the gas spent on the script execution.\n\nBelow are examples that show how to get the estimated transaction cost from single and multi call transactions.\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:contract_call_cost_estimation}}\n```\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:multi_call_cost_estimation}}\n```\n\nThe transaction cost estimation can be used to set the gas limit for an actual call, or to show the user the estimated cost.\n\n> **Note** The same estimation interface is available for scripts.\n"
  },
  {
    "path": "docs/src/calling-contracts/custom-asset-transfer.md",
    "content": "# Custom asset transfer\n\n<!-- This section should explain the `add_custom_asset()` method -->\n<!-- transfer:example:start -->\nThe SDK provides the option to transfer assets within the same transaction, when making a contract call. By using `add_custom_asset()` you specify the asset ID, the amount, and the destination address:\n<!-- transfer:example:end -->\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:add_custom_assets}}\n```\n"
  },
  {
    "path": "docs/src/calling-contracts/custom-inputs-outputs.md",
    "content": "# Custom inputs and outputs\n\nIf you need to add specific inputs and outputs to contract calls, you can use the `with_inputs` and `with_outputs` methods.\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:add_custom_inputs_outputs}}\n```\n\n> **Note:** if custom inputs include coins that need to be signed, use the `add_signer` method to add the appropriate signer.\n"
  },
  {
    "path": "docs/src/calling-contracts/index.md",
    "content": "# Calling contracts\n\nOnce you've deployed your contract, as seen in the previous sections, you'll likely want to:\n\n1. Call contract methods;\n2. Configure call parameters and transaction policies;\n3. Forward coins and gas in your contract calls;\n4. Read and interpret returned values and logs.\n\nHere's an example. Suppose your Sway contract has two ABI methods called `initialize_counter(u64)` and `increment_counter(u64)`. Once you've deployed it the contract, you can call these methods like this:\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:use_deployed_contract}}\n```\n\nThe example above uses all the default configurations and performs a simple contract call.\n\nFurthermore, if you need to separate submission from value retrieval for any reason, you can do so as follows:\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:submit_response_contract}}\n```\n\nNext, we'll see how we can further configure the many different parameters in a contract call.\n"
  },
  {
    "path": "docs/src/calling-contracts/logs.md",
    "content": "# Logs\n\nWhenever you log a value within a contract method, the resulting log entry is added to the log receipt and the variable type is recorded in the contract's ABI. The SDK lets you parse those values into Rust types.\n\nConsider the following contract method:\n\n```rust,ignore\n{{#include ../../../e2e/sway/logs/contract_logs/src/main.sw:produce_logs}}\n```\n\nYou can access the logged values in Rust by calling `decode_logs_with_type::<T>` from a `CallResponse`, where `T` is the type of the logged variables you want to retrieve. The result will be a `Vec<T>`:\n\n```rust,ignore\n{{#include ../../../e2e/tests/logs.rs:produce_logs}}\n```\n\nYou can use the `decode_logs()` function to retrieve a `LogResult` struct containing a `results` field that is a vector of `Result<String>` values representing the success or failure of decoding each log.\n\n```rust, ignore\n{{#include ../../../e2e/tests/logs.rs:decode_logs}}\n```\n\nDue to possible performance hits, it is not recommended to use `decode_logs()` outside of a debugging scenario.\n\n> **Note:** String slices cannot be logged directly. Use the `__to_str_array()` function to convert it to a `str[N]` first.\n"
  },
  {
    "path": "docs/src/calling-contracts/low-level-calls.md",
    "content": "# Low-level calls\n\n<!-- This section should explain what low-level calls are and how to do them -->\nWith low-level calls, you can specify the parameters of your calls at runtime and make indirect calls through other contracts.\n\nYour caller contract should call `std::low_level_call::call_with_function_selector`, providing:\n\n- target contract ID\n- function selector encoded as `Bytes`\n- calldata encoded as `Bytes`\n- whether the calldata contains only a single value argument (e.g. a `u64`)\n- `std::low_level_call::CallParams`\n\n```rust,ignore\n{{#include ../../../e2e/sway/contracts/low_level_caller/src/main.sw:low_level_call_contract}}\n```\n\nOn the SDK side, you can construct an encoded function selector using `fuels::core::encode_fn_selector`, and encoded calldata using the `fuels::core::calldata!` macro.\n\nE.g. to call the following function on the target contract:\n\n```rust,ignore\n{{#include ../../../e2e/sway/contracts/contract_test/src/main.sw:low_level_call}}\n```\n\nyou would construct the function selector and the calldata as such, and provide them to the caller contract (like the one above):\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:low_level_call}}\n```\n\n> Note: the `calldata!` macro uses the default `EncoderConfig` configuration under the hood.\n"
  },
  {
    "path": "docs/src/calling-contracts/multicalls.md",
    "content": "# Multiple contract calls\n\nWith `CallHandler`, you can execute multiple contract calls within a single transaction. To achieve this, you first prepare all the contract calls that you want to bundle:\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:multi_call_prepare}}\n```\n\nYou can also set call parameters, variable outputs, or external contracts for every contract call, as long as you don't execute it with `call()` or `simulate()`.\n\n> **Note:** if custom inputs or outputs have been added to the separate calls, the input and output order will follow the order how the calls are added to the multi-call.\n\nNext, you provide the prepared calls to your `CallHandler` and optionally configure transaction policies:\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:multi_call_build}}\n```\n\n> **Note:** any transaction policies configured on separate contract calls are disregarded in favor of the parameters provided to the multi-call `CallHandler`.\n\nFurthermore, if you need to separate submission from value retrieval for any reason, you can do so as follows:\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:submit_response_multicontract}}\n```\n\n## Output values\n\nTo get the output values of the bundled calls, you need to provide explicit type annotations when saving the result of `call()` or `simulate()` to a variable:\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:multi_call_values}}\n```\n\nYou can also interact with the `CallResponse` by moving the type annotation to the invoked method:\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:multi_contract_call_response}}\n```\n"
  },
  {
    "path": "docs/src/calling-contracts/other-contracts.md",
    "content": "# Calling other contracts\n\nIf your contract method is calling other contracts you will have to add the appropriate `Inputs` and `Outputs` to your transaction. For your convenience, the `CallHandler` provides methods that prepare those inputs and outputs for you. You have two methods that you can use: `with_contracts(&[&contract_instance, ...])` and `with_contract_ids(&[&contract_id, ...])`.\n\n`with_contracts(&[&contract_instance, ...])` requires contract instances that were created using the `abigen` macro. When setting the external contracts with this method, logs and require revert errors originating from the external contract can be propagated and decoded by the calling contract.\n\n```rust,ignore\n{{#include ../../../e2e/tests/contracts.rs:external_contract}}\n```\n\n If however, you do not need to decode logs or you do not have a contract instance that was generated using the `abigen` macro you can use `with_contract_ids(&[&contract_id, ...])` and provide the required contract ids.\n\n```rust,ignore\n{{#include ../../../e2e/tests/contracts.rs:external_contract_ids}}\n```\n"
  },
  {
    "path": "docs/src/calling-contracts/simulation.md",
    "content": "# Simulating calls\n\nSometimes you want to simulate a call to a contract without changing the state of the blockchain. This can be achieved by calling `.simulate` instead of `.call` and passing in the desired execution context:\n\n* `.simulate(Execution::realistic())` simulates the transaction in a manner that closely resembles a real call. You need a wallet with base assets to cover the transaction cost, even though no funds will be consumed. This is useful for validating that a real call would succeed if made at that moment. It allows you to debug issues with your contract without spending gas.\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:simulate}}\n```\n\n* `.simulate(Execution::state_read_only())` disables many validations, adds fake gas, extra variable outputs, blank witnesses, etc., enabling you to read state even with an account that has no funds.\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:simulate_read_state}}\n```\n\nIf the node supports historical execution (the node is using `rocksdb` and the `historical_execution` flag has been set), then both execution types can be chained with `at_height` to simulate the call at a specific block height.\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:simulate_read_state_at_height}}\n```\n"
  },
  {
    "path": "docs/src/calling-contracts/tx-dependency-estimation.md",
    "content": "# Transaction dependency estimation\n\nPreviously, we mentioned that a contract call might require you to manually specify external contracts, variable outputs, or output messages. The SDK can also attempt to estimate and set these dependencies for you at the cost of running multiple simulated calls in the background.\n\nThe following example uses a contract call that calls an external contract and later mints assets to a specified address. Calling it without including the dependencies will result in a revert:\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:dependency_estimation_fail}}\n```\n\nAs mentioned in previous chapters, you can specify the external contract and add an output variable to resolve this:\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:dependency_estimation_manual}}\n```\n\nBut this requires you to know the contract ID of the external contract and the needed number of output variables. Alternatively, by chaining\n\n- `.with_variable_output_policy(VariableOutputPolicy::EstimateMinimum)` and\n- `.determine_missing_contracts()`\n\nthe dependencies will be estimated by the SDK and set automatically.\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:dependency_estimation}}\n```\n\n> **Note:** Both `with_variable_output_policy` and `determine_missing_contracts` can also be used when working with script calls or multi calls. `determine_missing_contracts()` will not enable logging from an external contract. For more information, see [here](./other-contracts.md).\n"
  },
  {
    "path": "docs/src/calling-contracts/tx-policies.md",
    "content": "# Transaction policies\n\n<!-- This section should explain what tx policies are and how to configure them -->\n<!-- tx_policies:example:start -->\nTransaction policies are defined as follows:\n\n```rust,ignore\n{{#include ../../../packages/fuels-core/src/types/wrappers/transaction.rs:tx_policies_struct}}\n```\n\nWhere:\n\n1. **Tip** - amount to pay the block producer to prioritize the transaction.\n2. **Witness Limit** - The maximum amount of witness data allowed for the transaction.\n3. **Maturity** - Block until which the transaction cannot be included.\n4. **Expiration** - Block after which the transaction cannot be included.\n5. **Max Fee** - The maximum fee payable by this transaction.\n6. **Script Gas Limit** - The maximum amount of gas the transaction may consume for executing its script code.\n\nWhen the **Script Gas Limit** is not set, the Rust SDK will estimate the consumed gas in the background and set it as the limit.\n\nIf the **Witness Limit** is not set, the SDK will set it to the size of all witnesses and signatures defined in the transaction builder.\n\nYou can configure these parameters by creating an instance of `TxPolicies` and passing it to a chain method called `with_tx_policies`:\n<!-- tx_policies:example:end-->\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:tx_policies}}\n```\n\n<!-- This section should explain how to use the default tx policy -->\n<!-- tx_policies_default:example:start -->\nYou can also use `TxPolicies::default()` to use the default values.\n<!-- tx_policies_default:example:end -->\n\nThis way:\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:tx_policies_default}}\n```\n\nAs you might have noticed, `TxPolicies` can also be specified when deploying contracts or transferring assets by passing it to the respective methods.\n"
  },
  {
    "path": "docs/src/calling-contracts/variable-outputs.md",
    "content": "# Output variables\n\n<!-- This section should explain variable outputs  -->\n<!-- variable_outputs:example:start -->\nSometimes, the contract you call might transfer funds to a specific address, depending on its execution. The underlying transaction for such a contract call has to have the appropriate number of [variable outputs](https://docs.fuel.network/docs/specs/tx-format/output/#outputvariable) to succeed.\n<!-- variable_outputs:example:end -->\n\nLet's say you deployed a contract with the following method:\n\n```rust,ignore\n{{#include ../../../e2e/sway/contracts/token_ops/src/main.sw:variable_outputs}}\n```\n\nWhen calling `transfer_coins_to_output` with the SDK, you can specify the number of variable outputs:\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:variable_outputs}}\n```\n\n<!-- This section should explain what the `with_variable_output_policy` method does -->\n<!-- with_variable_output_policy:example:start -->\n`with_variable_output_policy` sets the policy regarding variable outputs. You can either set the number of variable outputs yourself by providing `VariableOutputPolicy::Exactly(n)` or let the SDK estimate it for you with `VariableOutputPolicy::EstimateMinimum`. A variable output indicates that the amount and the owner may vary based on transaction execution.\n<!-- with_variable_output_policy:example:end -->\n\n> **Note:** that the Sway `lib-std` function `mint_to_address` calls `transfer_to_address` under the hood, so you need to call `with_variable_output_policy` in the Rust SDK tests like you would for `transfer_to_address`.\n"
  },
  {
    "path": "docs/src/cli/fuels-abi-cli.md",
    "content": "# `fuels-abi-cli`\n\nSimple CLI program to encode Sway function calls and decode their output. The ABI being encoded and decoded is specified [here](https://docs.fuel.network/docs/specs/abi/).\n\n## Usage\n\n```plaintext\nsway-abi-cli 0.1.0\nFuelVM ABI coder\n\nUSAGE:\n    sway-abi-cli <SUBCOMMAND>\n\nFLAGS:\n    -h, --help       Prints help information\n    -V, --version    Prints version information\n\nSUBCOMMANDS:\n    codegen   Output Rust types file\n    decode    Decode ABI call result\n    encode    Encode ABI call\n    help      Prints this message or the help of the given subcommand(s)\n```\n\n## Examples\n\nYou can choose to encode only the given params or you can go a step further and have a full JSON ABI file and encode the whole input to a certain function call defined in the JSON file.\n\n### Encoding params only\n\n```console\n$ cargo run -- encode params -v bool true\n0000000000000001\n```\n\n```console\n$ cargo run -- encode params -v bool true -v u32 42 -v u32 100\n0000000000000001000000000000002a0000000000000064\n```\n\nNote that for every parameter you want to encode, you must pass a `-v` flag followed by the type, and then the value: `-v <type_1> <value_1> -v <type_2> <value_2> -v <type_n> <value_n>`\n\n### Encoding function call\n\n`example/simple.json`:\n\n```json\n[\n  {\n    \"type\":\"function\",\n    \"inputs\":[\n      {\n        \"name\":\"arg\",\n        \"type\":\"u32\"\n      }\n    ],\n    \"name\":\"takes_u32_returns_bool\",\n    \"outputs\":[\n      {\n        \"name\":\"\",\n        \"type\":\"bool\"\n      }\n    ]\n  }\n]\n```\n\n```console\n$ cargo run -- encode function examples/simple.json takes_u32_returns_bool -p 4\n000000006355e6ee0000000000000004\n```\n\n`example/array.json`\n\n```json\n[\n  {\n    \"type\":\"function\",\n    \"inputs\":[\n      {\n        \"name\":\"arg\",\n        \"type\":\"u16[3]\"\n      }\n    ],\n    \"name\":\"takes_array\",\n    \"outputs\":[\n      {\n        \"name\":\"\",\n        \"type\":\"u16[2]\"\n      }\n    ]\n  }\n]\n```\n\n```console\n$ cargo run -- encode function examples/array.json takes_array -p '[1,2]'\n00000000f0b8786400000000000000010000000000000002\n```\n\nNote that the first word (8 bytes) of the output is reserved for the function selector, which is captured in the last 4 bytes, which is simply the 256hash of the function signature.\n\nExample with nested struct:\n\n```json\n[\n  {\n    \"type\":\"contract\",\n    \"inputs\":[\n      {\n        \"name\":\"MyNestedStruct\",\n        \"type\":\"struct\",\n        \"components\":[\n          {\n            \"name\":\"x\",\n            \"type\":\"u16\"\n          },\n          {\n            \"name\":\"y\",\n            \"type\":\"struct\",\n            \"components\":[\n              {\n                \"name\":\"a\",\n                \"type\":\"bool\"\n              },\n              {\n                \"name\":\"b\",\n                \"type\":\"u8[2]\"\n              }\n            ]\n          }\n        ]\n      }\n    ],\n    \"name\":\"takes_nested_struct\",\n    \"outputs\":[\n\n    ]\n  }\n]\n```\n\n```console\n$ cargo run -- encode function examples/nested_struct.json takes_nested_struct -p '(10, (true, [1,2]))'\n00000000e8a04d9c000000000000000a000000000000000100000000000000010000000000000002\n```\n\n### Decoding params only\n\nSimilar to encoding parameters only:\n\n```console\n$ cargo run -- decode params -t bool -t u32 -t u32 0000000000000001000000000000002a0000000000000064\nBool(true)\nU32(42)\nU32(100)\n```\n\n### Decoding function output\n\n```console\n$ cargo run -- decode function examples/simple.json takes_u32_returns_bool 0000000000000001\nBool(true)\n```\n"
  },
  {
    "path": "docs/src/cli/index.md",
    "content": "# `fuels-rs` Rust Workspaces\n\nThis section gives you a little overview of the role and function of every workspace in the `fuels-rs` repository.\n\n- [`fuels-abi-cli`](./fuels-abi-cli.md)\n"
  },
  {
    "path": "docs/src/codec/decoding.md",
    "content": "# Decoding\n\nBe sure to read the [prerequisites](./index.md#prerequisites-for-decodingencoding) to decoding.\n\nDecoding is done via the [`ABIDecoder`](https://docs.rs/fuels/latest/fuels/core/codec/struct.ABIDecoder.html):\n\n```rust,ignore\n{{#include ../../../examples/codec/src/lib.rs:decoding_example}}\n```\n\nFirst into a [`Token`](https://docs.rs/fuels/latest/fuels/types/enum.Token.html), then via the [`Tokenizable`](https://docs.rs/fuels/latest/fuels/core/traits/trait.Tokenizable.html) trait, into the desired type.\n\nIf the type came from [`abigen!`](../abigen/index.md) (or uses the [`::fuels::macros::TryFrom`](https://docs.rs/fuels/latest/fuels/macros/derive.TryFrom.html) derivation) then you can also use `try_into` to convert bytes into a type that implements both [`Parameterize`](https://docs.rs/fuels/latest/fuels/core/traits/trait.Parameterize.html) and [`Tokenizable`](https://docs.rs/fuels/latest/fuels/core/traits/trait.Tokenizable.html):\n\n```rust,ignore\n{{#include ../../../examples/codec/src/lib.rs:decoding_example_try_into}}\n```\n\nUnder the hood, [`try_from_bytes`](https://docs.rs/fuels/latest/fuels/core/codec/fn.try_from_bytes.html) is being called, which does what the preceding example did.\n\n## Configuring the decoder\n\nThe decoder can be configured to limit its resource expenditure:\n\n```rust,ignore\n{{#include ../../../examples/codec/src/lib.rs:configuring_the_decoder}}\n```\n\n<!-- TODO: Add a link once a release is made -->\n<!-- https://docs.rs/fuels/latest/fuels/core/codec/struct.DecoderConfig.html -->\nFor an explanation of each configuration value visit the `DecoderConfig`.\n\n<!-- TODO: add a link once a release is made -->\n<!-- https://docs.rs/fuels/latest/fuels/core/codec/struct.DecoderConfig.html -->\nThe default values for the `DecoderConfig` are:\n\n```rust,ignore\n{{#include ../../../packages/fuels-core/src/codec/abi_decoder.rs:default_decoder_config}}\n```\n\n## Configuring the decoder for contract/script calls\n\nYou can also configure the decoder used to decode the return value of the contract method:\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:contract_decoder_config}}\n```\n\nThe same method is available for script calls.\n"
  },
  {
    "path": "docs/src/codec/encoding.md",
    "content": "# Encoding\n\nBe sure to read the [prerequisites](./index.md#prerequisites-for-decodingencoding) to encoding.\n\nEncoding is done via the [`ABIEncoder`](https://docs.rs/fuels/latest/fuels/core/codec/struct.ABIEncoder.html):\n\n```rust,ignore\n{{#include ../../../examples/codec/src/lib.rs:encoding_example}}\n```\n\nThere is also a shortcut-macro that can encode multiple types which implement [`Tokenizable`](https://docs.rs/fuels/latest/fuels/core/traits/trait.Tokenizable.html):\n\n```rust,ignore\n{{#include ../../../examples/codec/src/lib.rs:encoding_example_w_macro}}\n```\n\n## Configuring the encoder\n\nThe encoder can be configured to limit its resource expenditure:\n\n```rust,ignore\n{{#include ../../../examples/codec/src/lib.rs:configuring_the_encoder}}\n```\n\nThe default values for the `EncoderConfig` are:\n\n```rust,ignore\n{{#include ../../../packages/fuels-core/src/codec/abi_encoder.rs:default_encoder_config}}\n```\n\n## Configuring the encoder for contract/script calls\n\nYou can also configure the encoder used to encode the arguments of the contract method:\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:contract_encoder_config}}\n```\n\nThe same method is available for script calls.\n"
  },
  {
    "path": "docs/src/codec/index.md",
    "content": "# Codec\n\nEncoding and decoding are done as per [the fuel spec](https://docs.fuel.network/docs/specs/abi/argument-encoding/). To this end, `fuels` makes use of the [`ABIEncoder`](https://docs.rs/fuels/latest/fuels/core/codec/struct.ABIEncoder.html) and the [`ABIDecoder`](https://docs.rs/fuels/latest/fuels/core/codec/struct.ABIDecoder.html).\n\n## Prerequisites for decoding/encoding\n\nTo encode a type, you must first convert it into a [`Token`](https://docs.rs/fuels/latest/fuels/types/enum.Token.html). This is commonly done by implementing the [`Tokenizable`](https://docs.rs/fuels/latest/fuels/core/traits/trait.Tokenizable.html) trait.\n\nTo decode, you also need to provide a [`ParamType`](https://docs.rs/fuels/latest/fuels/types/param_types/enum.ParamType.html) describing the schema of the type in question. This is commonly done by implementing the [Parameterize](https://docs.rs/fuels/latest/fuels/core/traits/trait.Parameterize.html) trait.\n\nAll types generated by the [`abigen!`](../abigen/index.md) macro implement both the [`Tokenizable`](https://docs.rs/fuels/latest/fuels/core/traits/trait.Tokenizable.html) and [`Parameterize`](https://docs.rs/fuels/latest/fuels/core/traits/trait.Parameterize.html) traits.\n\n`fuels` also contains implementations for:\n\n- [`Tokenizable`](https://docs.rs/fuels/latest/fuels/core/traits/trait.Tokenizable.html) for the `fuels`-owned types listed [here](https://docs.rs/fuels/latest/fuels/core/traits/trait.Tokenizable.html#implementers) as well as [for some foreign types](https://docs.rs/fuels/latest/fuels/core/traits/trait.Tokenizable.html#foreign-impls) (such as `u8`, `u16`, `std::vec::Vec<T: Tokenizable>`, etc.).\n- [`Parameterize`](https://docs.rs/fuels/latest/fuels/core/traits/trait.Parameterize.html) for the `fuels`-owned types listed [here](https://docs.rs/fuels/latest/fuels/core/traits/trait.Parameterize.html#implementers) as well as [for some foreign types](https://docs.rs/fuels/latest/fuels/core/traits/trait.Parameterize.html#foreign-impls) (such as `u8`, `u16`, `std::vec::Vec<T: Parameterize>`, etc.).\n\n## Deriving the traits\n\nBoth [`Tokenizable`](https://docs.rs/fuels/latest/fuels/core/traits/trait.Tokenizable.html) and [`Parameterize`](https://docs.rs/fuels/latest/fuels/core/traits/trait.Parameterize.html) can be derived for `struct`s and `enum`s if all inner types implement the derived traits:\n\n```rust,ignore\n{{#include ../../../examples/macros/src/lib.rs:deriving_traits}}\n```\n\n> Note:\n> Deriving [`Tokenizable`](https://docs.rs/fuels/latest/fuels/core/traits/trait.Tokenizable.html) on `enum`s requires that all variants also implement [`Parameterize`](https://docs.rs/fuels/latest/fuels/core/traits/trait.Parameterize.html).\n\n### Tweaking the derivation\n\n#### Changing the location of imports\n\nThe derived code expects that the `fuels` package is accessible through `::fuels`. If this is not the case then the derivation macro needs to be given the locations of `fuels::types` and `fuels::core`.\n\n```rust,ignore\n{{#include ../../../examples/macros/src/lib.rs:deriving_traits_paths}}\n```\n\n#### Generating no-std code\n\nIf you want `no-std` generated code:\n\n```rust,ignore\n{{#include ../../../examples/macros/src/lib.rs:deriving_traits_nostd}}\n```\n"
  },
  {
    "path": "docs/src/connecting/external-node.md",
    "content": "# Connecting to the Testnet or an external node\n\nWe can interact with the `Testnet` node by using the following example.\n\n```rust,ignore\n{{#include ../../../examples/providers/src/lib.rs:connect_to_testnet}}\n```\n>\n> For detailed information about various testnet networks and their optimal toolchain configurations for your project, please visit the following link:\n>\n> [networks](https://fuelbook.fuel.network/master/networks/networks.html)\n\nIn the code example, we connected a new provider to the Testnet node and created a new wallet from a private key.\n\n> **Note:** New wallets on the Testnet will not have any assets! They can be obtained by providing the wallet address to the faucet at\n>\n>[faucet-testnet.fuel.network](https://faucet-testnet.fuel.network)\n>\n> Once the assets have been transferred to the wallet, you can reuse it in other tests by providing the private key!\n>\n> In addition to the faucet, there is a block explorer for the Testnet at\n>\n> [block-explorer](https://fuellabs.github.io/block-explorer-v2)\n\nIf you want to connect to another node just change the URL or IP and port. For example, to connect to a local node that was created with `fuel-core` you can use:\n\n```rust,ignore\n{{#include ../../../examples/providers/src/lib.rs:local_node_address}}\n```\n"
  },
  {
    "path": "docs/src/connecting/index.md",
    "content": "# Connecting to a Fuel node\n\n<!-- This section should explain at a high level the main ways to connect to a node with the Rust SDK and when they are appropriate to use-->\n<!-- rs_node:example:start -->\nAt a high level, you can use the Fuel Rust SDK to build Rust-based applications that can run computations on the Fuel Virtual Machine through interactions with smart contracts written in Sway.\n\nFor this interaction to work, the SDK must be able to communicate with a `fuel-core` node; you have two options at your disposal:\n\n1. Use the testnet or run a Fuel node (using `fuel-core`) and instantiate a provider that points to that node's IP and port.\n2. Use the SDK's native `launch_provider_and_get_wallet()` that runs a short-lived test Fuel node;\n\nThe second option is ideal for smart contract testing, as you can quickly spin up and tear down nodes between specific test cases.\n\nFor application building, you should use the first option.\n<!-- rs_node:example:end -->\n"
  },
  {
    "path": "docs/src/connecting/querying.md",
    "content": "# Querying the blockchain\n\nOnce you set up a provider, you can interact with the Fuel blockchain. Here are a few examples of what you can do with a provider; for a more in-depth overview of the API, check the [official provider API documentation](https://docs.rs/fuels/latest/fuels/accounts/provider/struct.Provider.html).\n\n- [Set up](#set-up)\n- [Get all coins from an address](#get-all-coins-from-an-address)\n- [Get spendable resources owned by an address](#get-spendable-resources-owned-by-an-address)\n- [Get balances from an address](#get-balances-from-an-address)\n\n## Set up\n\nYou might need to set up a test blockchain first. You can skip this step if you're connecting to an external blockchain.\n\n```rust,ignore\n{{#include ../../../examples/providers/src/lib.rs:setup_test_blockchain}}\n```\n\n## Get all coins from an address\n\nThis method returns all unspent coins (of a given asset ID) from a wallet.\n\n```rust,ignore\n{{#include ../../../examples/providers/src/lib.rs:get_coins}}\n```\n\n## Get spendable resources owned by an address\n\nThe following example shows how to fetch resources owned by an address. First, you create a  `ResourceFilter` which specifies the target address, asset ID, and amount. You can also define UTXO IDs and message IDs that should be excluded when retrieving the resources:\n\n```rust,ignore\n{{#include ../../../packages/fuels-accounts/src/provider.rs:resource_filter}}\n```\n\nThe example uses default values for the asset ID and the exclusion lists. This resolves to the base asset ID and empty vectors for the ID lists respectively:\n\n```rust,ignore\n{{#include ../../../examples/providers/src/lib.rs:get_spendable_resources}}\n```\n\n## Get balances from an address\n\nGet all the spendable balances of all assets for an address. This is different from getting the coins because we only return the numbers (the sum of UTXOs coins amount for each asset ID) and not the UTXOs coins themselves.\n\n```rust,ignore\n{{#include ../../../examples/providers/src/lib.rs:get_balances}}\n```\n"
  },
  {
    "path": "docs/src/connecting/retrying.md",
    "content": "# Retrying requests\n\nThe [`Provider`](https://docs.rs/fuels/0.62.0/fuels/accounts/provider/struct.Provider.html) can be configured to retry a request upon receiving a `io::Error`.\n\n> Note: Currently all node errors are received as `io::Error`s. So, if configured, a retry will happen even if, for example, a transaction failed to verify.\n\nWe can configure the number of retry attempts and the retry strategy as detailed below.\n\n## `RetryConfig`\n\nThe retry behavior can be altered by giving a custom `RetryConfig`. It allows for configuring the maximum number of attempts and the interval strategy used.\n\n```rust, ignore\n{{#include ../../../packages/fuels-accounts/src/provider/retry_util.rs:retry_config}}\n```\n\n```rust, ignore\n{{#include ../../../examples/providers/src/lib.rs:configure_retry}}\n```\n\n## Interval strategy - `Backoff`\n\n`Backoff` defines different strategies for managing intervals between retry attempts.\nEach strategy allows you to customize the waiting time before a new attempt based on the number of attempts made.\n\n### Variants\n\n- `Linear(Duration)`: `Default` Increases the waiting time linearly with each attempt.\n- `Exponential(Duration)`: Doubles the waiting time with each attempt.\n- `Fixed(Duration)`: Uses a constant waiting time between attempts.\n\n```rust, ignore\n{{#include ../../../packages/fuels-accounts/src/provider/retry_util.rs:backoff}}\n```\n"
  },
  {
    "path": "docs/src/connecting/rocksdb.md",
    "content": "# RocksDB\n\nRocksDB enables the preservation of the blockchain's state locally, facilitating its future utilization.\n\nTo create or use a local database, follow these instructions:\n\n```rust,ignore\n{{#include ../../../examples/cookbook/src/lib.rs:create_or_use_rocksdb}}\n```\n\n> Note: If the specified database does not exist, a new database will be created at that path. To utilize the code snippets above, either the `fuel-core` binary must be present, or both the `fuel-core-lib` and `rocksdb` features need to be enabled.\n"
  },
  {
    "path": "docs/src/connecting/short-lived.md",
    "content": "# Running a short-lived Fuel node with the SDK\n\nYou can use the SDK to spin up a local, ideally short-lived Fuel node. Then, you can instantiate a Fuel client, pointing to this node.\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:instantiate_client}}\n```\n\nThis approach is ideal for contract testing.\n\nYou can also use the test helper `setup_test_provider()` for this:\n\n```rust,ignore\n{{#include ../../../examples/wallets/src/lib.rs:create_random_wallet}}\n```\n\nYou can also use `launch_provider_and_get_wallet()`, which abstracts away the `setup_test_provider()` and the wallet creation, all in one single method:\n\n```rust,ignore\nlet wallet = launch_provider_and_get_wallet().await?;\n```\n\n## Features\n\n### Fuel-core lib\n\nThe `fuel-core-lib` feature allows us to run a `fuel-core` node without installing the `fuel-core` binary on the local machine. Using the `fuel-core-lib` feature flag entails downloading all the dependencies needed to run the fuel-core node.\n\n```rust,ignore\nfuels = { version = \"0.76.0\", features = [\"fuel-core-lib\"] }\n```\n\n### RocksDB\n\nThe `rocksdb` is an additional feature that, when combined with `fuel-core-lib`, provides persistent storage capabilities while using `fuel-core` as a library.\n\n```rust,ignore\nfuels = { version = \"0.76.0\", features = [\"rocksdb\"] }\n```\n"
  },
  {
    "path": "docs/src/contributing/CONTRIBUTING.md",
    "content": "# Contributing to the Fuel Rust SDK\n\nThanks for your interest in contributing to the Fuel Rust SDK!\n\nThis document outlines the process for installing dependencies, setting up for development, and conventions for contributing.`\n\nIf you run into any difficulties getting started, you can always ask questions on our [Discourse](https://forum.fuel.network/).\n\n## Finding something to work on\n\nYou may contribute to the project in many ways, some of which involve coding knowledge and some which do not. A few examples include:\n\n- Reporting bugs\n- Adding new features or bug fixes for which there is already an open issue\n- Making feature requests\n\nCheck out our [Help Wanted](https://github.com/FuelLabs/fuels-rs/labels/help%20wanted) or [Good First Issues](https://github.com/FuelLabs/fuels-rs/labels/good%20first%20issue) to find a suitable task.\n\nIf you are planning something big, for example, changes related to multiple components or changes to current behaviors, make sure to [open an issue](https://github.com/FuelLabs/fuels-rs/issues/new) to discuss with us before starting on the implementation.\n\n## Contribution flow\n\nThis is a rough outline of what a contributor's workflow looks like:\n\n- Make sure what you want to contribute is already tracked as an issue.\n  - We may discuss the problem and solution in the issue.\n- Create a Git branch from where you want to base your work. This is usually master.\n- Write code, add test cases, and commit your work.\n- Run tests and make sure all tests pass.\n- Add the breaking label to your PR if the PR contains any breaking changes.\n- Push your changes to a branch in your fork of the repository and submit a pull request.\n  - Make sure to mention the issue created in step 1 in the commit message.\n- Your PR will be reviewed, and some changes may be requested.\n  - Your PR must be re-reviewed and approved once you've made changes.\n  - Use GitHub's 'update branch' button if the PR becomes outdated.\n  - If there are conflicts, you can merge and resolve them locally. Then push to your PR branch. Any changes to the branch will require a re-review.\n- Our CI system (Github Actions) automatically tests all authorized pull requests.\n- Use GitHub to merge the PR once approved.\n\nThanks for your contributions!\n\n## Linking issues\n\nPull requests should be linked to at least one issue in the same repo.\n\nIf the pull request resolves the relevant issues, and you want GitHub to close these issues automatically after it merged into the default branch, you can use the syntax (`KEYWORD #ISSUE-NUMBER`) like this:\n\n```sh\nclose #123\n```\n\nIf the pull request links an issue but does not close it, you can use the keyword `ref` like this:\n\n```sh\nref #456\n```\n\nMultiple issues should use full syntax for each issue and be separated by a comma, like:\n\n```sh\nclose #123, ref #456\n```\n"
  },
  {
    "path": "docs/src/contributing/tests-structure.md",
    "content": "# Integration tests structure in `fuels-rs`\n\nThe integration tests of `fuels-rs` cover almost all aspects of the SDK and have grown significantly as more functionality was added. To make the tests and associated `Sway` projects more manageable they were split into several categories. A category consist of a `.rs` file for the tests and, if needed, a separate directory for the `Sway` projects.\n\nCurrently have the following structure:\n\n```shell\n  .\n  ├─  bindings/\n  ├─  contracts/\n  ├─  logs/\n  ├─  predicates/\n  ├─  storage/\n  ├─  types/\n  ├─  bindings.rs\n  ├─  contracts.rs\n  ├─  from_token.rs\n  ├─  logs.rs\n  ├─  predicates.rs\n  ├─  providers.rs\n  ├─  scripts.rs\n  ├─  storage.rs\n  ├─  types.rs\n  └─  wallets.rs\n```\n\nEven though test organization is subjective, please consider these guidelines before adding a new category:\n\n- Add a new category when creating a new section in the `Fuels Rust SDK` book - e.g. `Types`\n- Add a new category if there are more than 3 test and more than 100 lines of code and they form a group of tests - e.g. `storage.rs`\n\n Otherwise, we recommend putting the integration test inside the existing categories above.\n"
  },
  {
    "path": "docs/src/cookbook/custom-chain.md",
    "content": "# Custom chain\n\nThis example demonstrates how to start a short-lived Fuel node with custom consensus parameters for the underlying chain.\n\nFirst, we have to import `ConsensusParameters` and `ChainConfig`:\n\n```rust,ignore\n{{#include ../../../examples/cookbook/src/lib.rs:custom_chain_import}}\n```\n\nNext, we can define some values for the consensus parameters:\n\n```rust,ignore\n{{#include ../../../examples/cookbook/src/lib.rs:custom_chain_consensus}}\n```\n\nBefore we can start a node, we probably also want to define some genesis coins and assign them to an address:\n\n```rust,ignore\n{{#include ../../../examples/cookbook/src/lib.rs:custom_chain_coins}}\n```\n\nFinally, we call `setup_test_provider()`, which starts a node with the given configurations and returns a\nprovider attached to that node:\n\n```rust,ignore\n{{#include ../../../examples/cookbook/src/lib.rs:custom_chain_provider}}\n```\n"
  },
  {
    "path": "docs/src/cookbook/deposit-and-withdraw.md",
    "content": "# Deposit and withdraw\n\nConsider the following contract:\n\n```rust,ignore\n{{#include ../../../e2e/sway/contracts/liquidity_pool/src/main.sw}}\n```\n\nAs its name suggests, it represents a simplified example of a liquidity pool contract. The method `deposit()` expects you to supply an arbitrary amount of the `BASE_TOKEN`. As a result, it mints double the amount of the liquidity asset to the calling address. Analogously, if you call `withdraw()` supplying it with the liquidity asset, it will transfer half that amount of the `BASE_TOKEN` back to the calling address except for deducting it from the contract balance instead of minting it.\n\nThe first step towards interacting with any contract in the Rust SDK is calling the `abigen!` macro to generate type-safe Rust bindings for the contract methods:\n\n```rust,ignore\n{{#include ../../../examples/cookbook/src/lib.rs:liquidity_abigen}}\n```\n\nNext, we set up a wallet with custom-defined assets. We give our wallet some of the contracts `BASE_TOKEN` and the default asset (required for contract deployment):\n\n```rust,ignore\n{{#include ../../../examples/cookbook/src/lib.rs:liquidity_wallet}}\n```\n\nHaving launched a provider and created the wallet, we can deploy our contract and create an instance of its methods:\n\n```rust,ignore\n{{#include ../../../examples/cookbook/src/lib.rs:liquidity_deploy}}\n```\n\nWith the preparations out of the way, we can finally deposit to the liquidity pool by calling `deposit()` via the contract instance. Since we have to transfer assets to the contract, we create the appropriate `CallParameters` and chain them to the method call. To receive the minted liquidity pool asset, we have to append a variable output to our contract call.\n\n```rust,ignore\n{{#include ../../../examples/cookbook/src/lib.rs:liquidity_deposit}}\n```\n\nAs a final demonstration, let's use all our liquidity asset balance to withdraw from the pool and confirm we retrieved the initial amount. For this, we get our liquidity asset balance and supply it to the `withdraw()` call via `CallParameters`.\n\n```rust,ignore\n{{#include ../../../examples/cookbook/src/lib.rs:liquidity_withdraw}}\n```\n"
  },
  {
    "path": "docs/src/cookbook/index.md",
    "content": "# Cookbook\n\nThis section covers more advanced use cases that can be satisfied by combining various features of the Rust SDK. As such, it assumes that you have already made yourself familiar with the previous chapters of this book.\n\n> **Note** This section is still a work in progress and more recipes may be added in the future.\n"
  },
  {
    "path": "docs/src/cookbook/transfer-all-assets.md",
    "content": "# Transfer all assets\n\nThe `transfer()` method lets you transfer a single asset, but what if you needed to move all of your assets to a different wallet? You could repeatably call `transfer()`, initiating a transaction each time, or you bundle all the transfers into a single transaction. This chapter guides you through crafting your custom transaction for transferring all assets owned by a wallet.\n\nLets quickly go over the setup:\n\n```rust,ignore\n{{#include ../../../examples/cookbook/src/lib.rs:transfer_multiple_setup}}\n```\n\nWe prepare two wallets with randomized addresses. Next, we want one of our wallets to have some random assets, so we set them up with `setup_multiple_assets_coins()`.\n\nTransactions require us to define input and output coins. Let's assume we do not know the assets owned by `wallet_1`. We retrieve its balances, i.e. tuples consisting of a string representing the asset ID and the respective amount. This lets us use the helpers `get_asset_inputs_for_amount()`, `get_asset_outputs_for_amount()` to create the appropriate inputs and outputs.\n\nWe transfer only a part of the base asset balance so that the rest can cover transaction fees:\n\n```rust,ignore\n{{#include ../../../examples/cookbook/src/lib.rs:transfer_multiple_input}}\n```\n\nAll that is left is to build the transaction via `ScriptTransactionBuilder`, have `wallet_1` add a witness to it and we can send it. We confirm this by checking the number of balances present in the receiving wallet and their amount:\n\n```rust,ignore\n{{#include ../../../examples/cookbook/src/lib.rs:transfer_multiple_transaction}}\n```\n"
  },
  {
    "path": "docs/src/custom-transactions/custom-calls.md",
    "content": "# Custom contract and script calls\n\nWhen preparing a contract call via `CallHandler`, the Rust SDK uses a transaction builder in the background. You can fetch this builder and customize it before submitting it to the network. After the transaction is executed successfully, you can use the corresponding `CallHandler` to generate a [call response](../calling-contracts/call-response.md). The call response can be used to decode return values and logs. Below are examples for both contract and script calls.\n\n## Custom contract call\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:contract_call_tb}}\n```\n\n## Custom script call\n\n```rust,ignore\n{{#include ../../../e2e/tests/scripts.rs:script_call_tb}}\n```\n"
  },
  {
    "path": "docs/src/custom-transactions/index.md",
    "content": "# Custom transactions\n\nUntil now, we have used helpers to create transactions, send them with a provider, and parse the results. However, sometimes we must make custom transactions with specific inputs, outputs, witnesses, etc. In the next chapter, we will show how to use the Rust SDKs transaction builders to accomplish this.\n"
  },
  {
    "path": "docs/src/custom-transactions/transaction-builders.md",
    "content": "# Transaction Builders\n\nThe Rust SDK simplifies the creation of **Create** and **Script** transactions through two handy builder structs `CreateTransactionBuilder`, `ScriptTransactionBuilder`, and the `TransactionBuilder` trait.\n\nCalling `build(&provider)` on a builder will result in the corresponding `CreateTransaction` or `ScriptTransaction` that can be submitted to the network.\n\n## Role of the transaction builders\n\n> **Note** This section contains additional information about the inner workings of the builders. If you are just interested in how to use them, you can skip to the next section.\n\nThe builders take on the heavy lifting behind the scenes, offering two standout advantages: handling predicate data offsets and managing witness indexing.\n\nWhen your transaction involves predicates with dynamic data as inputs, like vectors, the dynamic data contains a pointer pointing to the beginning of the raw data. This pointer's validity hinges on the order of transaction inputs, and any shifting could render it invalid. However, the transaction builders conveniently postpone the resolution of these pointers until you finalize the build process.\n\nSimilarly, adding signatures for signed coins requires the signed coin input to hold an index corresponding to the signature in the witnesses array. These indexes can also become invalid if the witness order changes. The Rust SDK again defers the resolution of these indexes until the transaction is finalized. It handles the assignment of correct index witnesses behind the scenes, sparing you the hassle of dealing with indexing intricacies during input definition.\n\nAnother added benefit of the builder pattern is that it guards against changes once the transaction is finalized. The transactions resulting from a builder don't permit any changes to the struct that could cause the transaction ID to be modified. This eliminates the headache of calculating and storing a transaction ID for future use, only to accidentally modify the transaction later, resulting in a different transaction ID.\n\n## Creating a custom transaction\n\nHere is an example outlining some of the features of the transaction builders.\n\nIn this scenario, we have a predicate that holds some bridged asset with ID **bridged_asset_id**. It releases it's locked assets if the transaction sends **ask_amount** of the base asset to the **receiver** address:\n\n```rust,ignore\n{{#include ../../../examples/cookbook/src/lib.rs:custom_tx_receiver}}\n```\n\nOur goal is to create a transaction that will use our hot wallet to transfer the **ask_amount** to the **receiver** and then send the unlocked predicate assets to a second wallet that acts as our cold storage.\n\nLet's start by instantiating a builder. Since we don't plan to deploy a contract, the `ScriptTransactionBuilder` is the appropriate choice:\n\n```rust,ignore\n{{#include ../../../examples/cookbook/src/lib.rs:custom_tx}}\n```\n\nNext, we need to define transaction inputs of the base asset that sum up to **ask_amount**. We also need transaction outputs that will assign those assets to the predicate address and thereby unlock it. The methods `get_asset_inputs_for_amount` and `get_asset_outputs_for_amount` can help with that. We need to specify the asset ID, the target amount, and the target address:\n\n```rust,ignore\n{{#include ../../../examples/cookbook/src/lib.rs:custom_tx_io_base}}\n```\n\nLet's repeat the same process but this time for transferring the assets held by the predicate to our cold storage:\n\n```rust,ignore\n{{#include ../../../examples/cookbook/src/lib.rs:custom_tx_io_other}}\n```\n\nWe combine all of the inputs and outputs and set them on the builder:\n\n```rust,ignore\n{{#include ../../../examples/cookbook/src/lib.rs:custom_tx_io}}\n```\n\nAs we have used coins that require a signature, we have to add the signer to the transaction builder with:\n\n```rust,ignore\n{{#include ../../../examples/cookbook/src/lib.rs:custom_tx_add_signer}}\n```\n\n> **Note** The signature is not created until the transaction is finalized with `build(&provider)`\n\nWe need to do one more thing before we stop thinking about transaction inputs. Executing the transaction also incurs a fee that is paid with the base asset. Our base asset inputs need to be large enough so that the total amount covers the transaction fee and any other operations we are doing. The `ViewOnlyAccount` trait lets us use `adjust_for_fee()` for adjusting the transaction inputs if needed to cover the fee. The second argument to `adjust_for_fee()` is the total amount of the base asset that we expect our transaction to spend regardless of fees. In our case, this is the **ask_amount** we are transferring to the predicate.\n\n```rust,ignore\n{{#include ../../../examples/cookbook/src/lib.rs:custom_tx_adjust}}\n```\n\n> **Note** It is recommended to add signers before calling `adjust_for_fee()` as the estimation will include the size of the witnesses.\n\nWe can also define transaction policies. For example, we can set the maturity and expiration with:\n\n```rust,ignore\n{{#include ../../../examples/cookbook/src/lib.rs:custom_tx_policies}}\n```\n\nOur builder needs a signature from the hot wallet to unlock its coins before we call `build()` and submit the resulting transaction through the provider:\n\n```rust,ignore\n{{#include ../../../examples/cookbook/src/lib.rs:custom_tx_build}}\n```\n\nFinally, we verify the transaction succeeded and that the cold storage indeed holds the bridged asset now:\n\n```rust,ignore\n{{#include ../../../examples/cookbook/src/lib.rs:custom_tx_verify}}\n```\n\n## Building a transaction without signatures\n\nIf you need to build the transaction without signatures, which is useful when estimating transaction costs or simulations, you can change the build strategy used:\n\n```rust,ignore\n{{#include ../../../e2e/tests/contracts.rs:tb_no_signatures_strategy}}\n```\n\n> **Note** In contrast to adding signers to a transaction builder, when signing a built transaction, you must ensure that the order of signatures matches the order of signed inputs. Multiple signed inputs with the same owner will have the same witness index.\n"
  },
  {
    "path": "docs/src/debugging/decoding-script-transactions.md",
    "content": "# Decoding script transactions\n\nThe SDK offers some tools that can help you make fuel script transactions more\nhuman readable. You can determine whether the script transaction is:\n\n* calling a contract method(s),\n* is a loader script and you can see the blob id\n* is neither of the above\n\nIn the case of contract call(s), if you have the ABI file, you can also decode\nthe arguments to the function by making use of the `AbiFormatter`:\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:decoding_script_transactions}}\n```\n\nprints:\n\n```text\nThe script called: initialize_counter(42)\n```\n\nThe `AbiFormatter` can also decode configurables, refer to the rust docs for\nmore information.\n"
  },
  {
    "path": "docs/src/debugging/function-selector.md",
    "content": "# Function selector\n\nWhenever you call a contract method the SDK will generate a function selector according to the fuel specs which will be\nused by the node to identify which method we wish to execute.\n\nIf, for whatever reason, you wish to generate the function selector yourself you can do so:\n\n```rust,ignore\n{{#include ../../../examples/debugging/src/lib.rs:example_fn_selector}}\n```\n"
  },
  {
    "path": "docs/src/debugging/index.md",
    "content": "# Debugging\n\n> **note** This section is still a work in progress.\n\n- [The Function Selector](./function-selector.md)\n"
  },
  {
    "path": "docs/src/deploying/configurable-constants.md",
    "content": "# Configurable constants\n\nIn Sway, you can define `configurable` constants which can be changed during the contract deployment in the SDK. Here is an example how the constants are defined.\n\n```rust,ignore\n{{#include ../../../e2e/sway/contracts/configurables/src/main.sw}}\n```\n\nEach of the configurable constants will get a dedicated `with` method in the SDK. For example, the constant `STR_4` will get the `with_STR_4` method which accepts the same type as defined in the contract code. Below is an example where we chain several `with` methods and deploy the contract with the new constants.\n\n```rust,ignore\n{{#include ../../../e2e/tests/configurables.rs:contract_configurables}}\n```\n"
  },
  {
    "path": "docs/src/deploying/index.md",
    "content": "# Deploying contracts\n\nThere are two main ways of working with contracts in the SDK: deploying a contract with SDK or using the SDK to interact with existing contracts.\n\n## Deploying a contract binary\n\n<!-- This section should explain the artifacts produced by `forc build`  -->\n<!-- build:example:start -->\nOnce you've written a contract in Sway and compiled it with `forc build`, you'll have in your hands two important artifacts: the compiled binary file and the JSON ABI file.\n<!-- build:example:end -->\n> Note: Read [here](https://docs.fuel.network/guides/quickstart/) for more on how to work with Sway.\n\nBelow is how you can deploy your contracts using the SDK. For more details about each component in this process, read [The abigen macro](../abigen/the-abigen-macro.md), [The FuelVM binary file](./the-fuelvm-binary-file.md), and [The JSON ABI file](../abigen/the-json-abi-file.md).\n\n<!-- This section should explain how to load and deploy a contract  -->\n<!-- deploy:example:start -->\nFirst, the `Contract::load_from` function is used to load a contract binary with a `LoadConfiguration`. If you are only interested in a single instance of your contract, use the default configuration: `LoadConfiguration::default()`. After the contract binary is loaded, you can use the `deploy()` method to deploy the contract to the blockchain.\n<!-- deploy:example:end -->\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:deploy_contract}}\n```\n\nAlternatively, you can use `LoadConfiguration` to configure how the contract is loaded. `LoadConfiguration` let's you:\n\n- Load the same contract binary with `Salt` to get a new `contract_id`\n- Change the contract's storage slots\n- Update the contract's configurables\n\n> Note: The next section will give more information on how `configurables` can be used.\n\nAdditionally, you can set custom `TxParameters` when deploying the loaded contract.\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:deploy_with_parameters}}\n```\n\nAfter the contract is deployed, you can use the contract's methods like this:\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:use_deployed_contract}}\n```\n\n> Note: When redeploying an existing `Contract`, ensure that you initialize it with a unique salt to prevent deployment failures caused by a contract ID collision. To accomplish this, utilize the `with_salt` method to clone the existing `Contract` with a new salt.\n"
  },
  {
    "path": "docs/src/deploying/interacting-with-contracts.md",
    "content": "# Interacting with contracts\n\nIf you already have a deployed contract and want to call its methods using the SDK, but without deploying it again, all you need is the contract ID of your deployed contract. You can skip the whole deployment setup and call `::new(contract_id, wallet)` directly. For example:\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:deployed_contracts}}\n```\n"
  },
  {
    "path": "docs/src/deploying/large_contracts.md",
    "content": "# Deploying Large Contracts\n\nIf your contract exceeds the size limit for a single deployment:\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:show_contract_is_too_big}}\n```\n\nyou can deploy it in segments using a partitioned approach:\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:deploy_via_loader}}\n```\n\nWhen you convert a standard contract into a loader contract, the following changes occur:\n\n* The original contract code is replaced with the loader contract code.\n* The original contract code is split into blobs, which will be deployed via blob transactions before deploying the contract itself.\n* The new loader code, when invoked, loads these blobs into memory and executes your original contract.\n\nAfter deploying the loader contract, you can interact with it just as you would with a standard contract:\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:use_loader}}\n```\n\nA helper function is available to deploy your contract normally if it is within the size limit, or as a loader contract if it exceeds the limit:\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:auto_convert_to_loader}}\n```\n\nYou also have the option to separate the blob upload from the contract deployment for more granular control:\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:upload_blobs_then_deploy}}\n```\n\nAlternatively, you can manually split your contract code into blobs and then create and deploy a loader:\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:manual_blobs_then_deploy}}\n```\n\nOr you can upload the blobs yourself and proceed with just the loader deployment:\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:manual_blob_upload_then_deploy}}\n```\n\n## Blob Size Considerations\n\nThe size of a Blob transaction is constrained by three factors:\n\n<!--Needed to disable lints because the multiline ordered list is messing with the linter. It keeps suggesting that each item is a start of a new list.-->\n<!-- markdownlint-disable -->\n1. The maximum size of a single transaction:\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:show_max_tx_size}}\n```\n\n2. The maximum gas usage for a single transaction:\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:show_max_tx_gas}}\n```\n\n3. The maximum HTTP body size accepted by the Fuel node.\n\nTo estimate an appropriate size for your blobs, you can run:\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:estimate_max_blob_size}}\n```\n<!-- markdownlint-restore -->\n\nHowever, keep in mind the following limitations:\n\n* The estimation only considers the maximum transaction size, not the max gas usage or HTTP body limit.\n* It does not account for any size increase that may occur after the transaction is funded.\n\nTherefore, it is advisable to make your blobs a few percent smaller than the estimated maximum size.\n"
  },
  {
    "path": "docs/src/deploying/storage-slots.md",
    "content": "# Overriding storage slots\n\nIf you use storage in your contract, the default storage values will be generated in a JSON file (e.g. `my_contract-storage_slots.json`) by the Sway compiler. These are loaded automatically for you when you load a contract binary. If you wish to override some of the defaults, you need to provide the corresponding storage slots manually:\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:storage_slots_override}}\n```\n\nIf you don't have the slot storage file (`my_contract-storage_slots.json` example from above) for some reason, or you don't wish to load any of the default values, you can disable the auto-loading of storage slots:\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:storage_slots_disable_autoload}}\n```\n"
  },
  {
    "path": "docs/src/deploying/the-fuelvm-binary-file.md",
    "content": "# The FuelVM binary file\n\nThe command `forc build` compiles your Sway code and generates the bytecode: the binary code that the Fuel Virtual Machine will interpret. For instance, the smart contract below:\n\n```Rust\ncontract;\n\nabi MyContract {\n    fn test_function() -> bool;\n}\n\nimpl MyContract for Contract {\n    fn test_function() -> bool {\n        true\n    }\n}\n```\n\nAfter `forc build`, will have a binary file that contains:\n\n```terminal\n$ cat out/release/my-test.bin\nG4]�]D`I]C�As@\n           6]C�$@!QK%\n```\n\nThis seems very unreadable! But, `forc` has a nice interpreter for this bytecode: `forc parse-bytecode`, which will interpret that binary data and output the equivalent FuelVM assembly:\n\n```terminal\n$ forc parse-bytecode out/release/my-test.bin\nhalf-word   byte   op                raw           notes\n        0   0      JI(4)             90 00 00 04   jump to byte 16\n        1   4      NOOP              47 00 00 00\n        2   8      Undefined         00 00 00 00   data section offset lo (0)\n        3   12     Undefined         00 00 00 34   data section offset hi (52)\n        4   16     LW(63, 12, 1)     5d fc c0 01\n        5   20     ADD(63, 63, 12)   10 ff f3 00\n        6   24     LW(17, 6, 73)     5d 44 60 49\n        7   28     LW(16, 63, 1)     5d 43 f0 01\n        8   32     EQ(16, 17, 16)    13 41 14 00\n        9   36     JNZI(16, 11)      73 40 00 0b   conditionally jump to byte 44\n       10   40     RVRT(0)           36 00 00 00\n       11   44     LW(16, 63, 0)     5d 43 f0 00\n       12   48     RET(16)           24 40 00 00\n       13   52     Undefined         00 00 00 00\n       14   56     Undefined         00 00 00 01\n       15   60     Undefined         00 00 00 00\n       16   64     XOR(20, 27, 53)   21 51 bd 4b\n```\n\nIf you want to deploy your smart contract using the SDK, this binary file is important; it's what we'll be sending to the FuelVM in a transaction.\n"
  },
  {
    "path": "docs/src/getting-started.md",
    "content": "# Getting Started\n\n## Installation Guide\n\nPlease visit the Fuel [installation guide](https://docs.fuel.network/guides/installation) to install the Fuel toolchain binaries and prerequisites.\n\n`forc` is Sway equivalent of Rust's `cargo`. `fuel-core` is a Fuel full node implementation.\n\nThere are two main ways you can use the Fuel Rust SDK:\n\n1. Creating a new Sway project with `forc` and running the tests\n2. Creating a standalone project and importing the `fuels-rs` crate\n\n## Creating a new project with Forc\n\nYou can create a new Sway project with\n\n```shell\nforc new <Project name>\n```\n\nOr you can initialize a project within an existing folder with\n\n```shell\nforc init\n```\n\n### Adding a Rust integration test to the Sway project\n\nNow that we have a new project, we can add a Rust integration test using a `cargo generate` template.\nIf `cargo generate` is not already installed, you can install it with:\n\n<!-- This section should have the command to install cargo generate -->\n<!-- cargo_gen_install:example:start -->\n```shell\ncargo install cargo-generate\n```\n<!-- cargo_gen_install:example:end -->\n\n> **Note** You can learn more about cargo generate by visiting its [repository](https://github.com/cargo-generate/cargo-generate).\n\nLet's generate the default test harness with the following command:\n\n<!-- This section should have the command to cargo generate a test harness -->\n<!-- cargo_gen:example:start -->\n```shell\ncargo generate --init fuellabs/sway templates/sway-test-rs --name <Project name> --force\n```\n<!-- cargo_gen:example:end -->\n\n<!-- This section should explain the `--force` flag -->\n<!-- force_flag:example:start -->\n`--force` forces your `--name` input to retain your desired casing for the `{{project-name}}` placeholder in the template. Otherwise, `cargo-generate` automatically converts it to kebab-case. With `--force`, this means that both `my_fuel_project` and `my-fuel-project` are valid project names, depending on your needs.\n<!-- force_flag:example:end -->\n\nBefore running test, we need to build the Sway project with:\n\n```shell\nforc build\n```\n\nAfterwards, we can run the test with:\n\n<!-- This section should have the command to run a test -->\n<!-- run_test:example:start -->\n```shell\ncargo test\n```\n<!-- run_test:example:end -->\n\n> **Note** If you need to capture output from the tests, use one of the following commands:\n\n<!-- This section should have the command to run a test with no capture -->\n<!-- run_test_nocap:example:start -->\n```shell\ncargo test -- --nocapture\n```\n<!-- run_test_nocap:example:end -->\n\n## Importing the Fuel Rust SDK\n\nAdd these dependencies on your `Cargo.toml`:\n\n```toml\nfuels = \"0.66.0\"\n```\n\n> **Note** We're using version `0.66.0` of the SDK, which is the latest version at the time of this writing.\n\nAnd then, in your Rust file that's going to make use of the SDK:\n\n```rust,ignore\nuse fuels::prelude::*;\n```\n\n## The Fuel Rust SDK source code\n\nAnother way to experience the SDK is to look at the source code. The `e2e/tests/` folder is full of integration tests that go through almost all aspects of the SDK.\n\n> **Note** Before running the tests, we need to build all the Sway test projects. The file `packages/fuels/Forc.toml` contains a `[workspace], which members are the paths to all integration tests.\n> To build these tests, run the following command:\n\n```shell\nforc build --release --path e2e\n```\n\n> `forc` can also be used to clean and format the test projects. Check the `help` output for more info.\n\nAfter building the projects, we can run the tests with\n\n```shell\ncargo test\n```\n\nIf you need all targets and all features, you can run\n\n```shell\ncargo test --all-targets --all-features\n```\n\n> **Note** If you need to capture output from the tests, you can run\n\n```shell\ncargo test -- --nocapture\n```\n\n## More in-depth Fuel and Sway knowledge\n\nRead [The Sway Book](https://docs.fuel.network/docs/sway/) for more in-depth knowledge about Sway, the official smart contract language for the Fuel Virtual Machine.\n"
  },
  {
    "path": "docs/src/glossary.md",
    "content": "# Glossary\n\n## Contract\n\n<!-- This section should define a contract -->\n<!-- rs_contract:example:start -->\n\nA contract, in the SDK, is an abstraction that represents a connection to a specific smart contract deployed on the Fuel Network. This contract instance can be used as a regular Rust object, with methods attached to it that reflect those in its smart contract equivalent.\n\n<!-- rs_contract:example:end -->\n\n## Provider\n\n<!-- This section should define a provider -->\n<!-- rs_provider:example:start -->\n\nA Provider is a struct that provides an abstraction for a connection to a Fuel node. It provides read-only access to the node. You can use this provider as-is or through the wallet.\n\n<!-- rs_provider:example:end -->\n"
  },
  {
    "path": "docs/src/index.md",
    "content": "# The Fuel Rust SDK\n\n<!-- This section should explain what the Fuel Rust SDK can be used for -->\n<!-- fuels_rs:example:start -->\nThe Fuel Rust SDK can be used for a variety of things, including:\n\n- Compiling, deploying, and testing [Sway](https://github.com/FuelLabs/sway) contracts\n- Using the testnet or running a local Fuel node\n- Crafting and signing transactions with hand-crafted scripts or contract calls\n- Generating type-safe Rust bindings of contract ABI methods\n<!-- fuels_rs:example:end -->\n\nThis book is an overview of the different things one can achieve using the Rust SDK, and how to implement them. Keep in mind that both the SDK and the documentation are works-in-progress!\n"
  },
  {
    "path": "docs/src/predicates/index.md",
    "content": "# Predicates\n\nPredicates, in Sway, are programs that return a Boolean value and do not have any side effects (they are pure). A predicate address can own assets. The predicate address is generated from the compiled byte code and is the same as the `P2SH` address used in Bitcoin. Users can seamlessly send assets to the predicate address as they do for any other address. To spend the predicate funds, the user has to provide the original `byte code` of the predicate together with the `predicate data`. The `predicate data` will be used when executing the `byte code`, and the funds can be transferred if the predicate is validated successfully.\n\n## Instantiating predicates\n\nLet's consider the following predicate example:\n\n```rust,ignore\n{{#include ../../../e2e/sway/predicates/basic_predicate/src/main.sw}}\n```\n\nWe will look at a complete example of using the SDK to send and receive funds from a predicate.\n\nFirst, we set up the wallets and a node instance. The call to the `abigen!` macro will generate all the types specified in the predicate plus two custom structs:\n\n- an encoder with an `encode_data`  function that will conveniently encode all the arguments of the main function for us.\n- a configurables struct which holds methods for setting all the configurables mentioned in the predicate\n\n> Note: The `abigen!` macro will append `Encoder` and `Configurables` to the predicate's `name` field. Fox example, `name=\"MyPredicate\"` will result in two structs called `MyPredicateEncoder` and `MyPredicateConfigurables`.\n\n```rust,ignore\n{{#include ../../../examples/predicates/src/lib.rs:predicate_data_setup}}\n```\n\nOnce we've compiled our predicate with `forc build`, we can create a `Predicate` instance via `Predicate::load_from`. The resulting data from `encode_data` can then be set on the loaded predicate.\n\n```rust,ignore\n{{#include ../../../examples/predicates/src/lib.rs:with_predicate_data}}\n```\n\nNext, we lock some assets in this predicate using the first wallet:\n\n```rust,ignore\n{{#include ../../../examples/predicates/src/lib.rs:predicate_data_lock_amount}}\n```\n\nThen we can transfer assets owned by the predicate via the [Account](../accounts.md) trait:\n\n```rust,ignore\n{{#include ../../../examples/predicates/src/lib.rs:predicate_data_unlock}}\n```\n\n## Configurable constants\n\nSame as contracts and scripts, you can define configurable constants in `predicates`, which can be changed during the predicate execution. Here is an example of how the constants are defined.\n\n```rust,ignore\n{{#include ../../../e2e/sway/predicates/predicate_configurables/src/main.sw:predicate_configurables}}\n```\n\nEach configurable constant will get a dedicated `with` method in the SDK. For example, the constant `U8` will get the `with_U8` method which accepts the same type defined in sway. Below is an example where we chain several `with` methods and update the predicate with the new constants.\n\n```rust,ignore\n{{#include ../../../e2e/tests/predicates.rs:predicate_configurables}}\n```\n"
  },
  {
    "path": "docs/src/predicates/send-spend-predicate.md",
    "content": "# Signatures in predicates example\n\nThis is a more involved example where the predicate accepts three signatures and matches them to three predefined public keys. The `ec_recover_address` function is used to recover the public key from the signatures. If two of the three extracted public keys match the predefined public keys, the funds can be spent. Note that the signature order has to match the order of the predefined public keys.\n\n```rust,ignore\n{{#include ../../../e2e/sway/predicates/signatures/src/main.sw}}\n```\n\nLet's use the SDK to interact with the predicate. First, let's create three signers with specific keys. Their hashed public keys are already hard-coded in the predicate. Then we create the receiver signer, which we will use to spend the predicate funds.\n\n```rust,ignore\n{{#include ../../../examples/predicates/src/lib.rs:predicate_signers}}\n```\n\nNext, let's add some coins, start a provider and create the wallets.\n\n```rust,ignore\n{{#include ../../../examples/predicates/src/lib.rs:predicate_coins}}\n```\n\nNow we can use the predicate abigen to create a predicate encoder instance for us. To spend the funds now locked in the predicate, we must provide two out of three signatures whose public keys match the ones we defined in the predicate. In this example, the signatures are generated from an array of zeros.\n\n```rust,ignore\n{{#include ../../../examples/predicates/src/lib.rs:predicate_load}}\n```\n\nNext, we transfer some assets from a wallet to the created predicate. We also confirm that the funds are indeed transferred.\n\n```rust,ignore\n{{#include ../../../examples/predicates/src/lib.rs:predicate_receive}}\n```\n\nWe can use the `transfer` method from the [Account](../accounts.md) trait to transfer the assets. If the predicate data is correct, the `receiver` wallet will get the funds, and we will verify that the amount is correct.\n\n```rust,ignore\n{{#include ../../../examples/predicates/src/lib.rs:predicate_spend}}\n```\n"
  },
  {
    "path": "docs/src/preuploading-code.md",
    "content": "# Pre-uploading code\n\nIf you have a script or predicate that is larger than normal or which you plan\non calling often, you can pre-upload its code as a blob to the network and run a\nloader script/predicate instead. The loader can be configured with the\nscript/predicate configurables, so you can change how the script/predicate is\nconfigured on each run without having large transactions due to the code\nduplication.\n\n## Scripts\n\nA high level pre-upload:\n\n```rust,ignore\n{{#include ../../e2e/tests/scripts.rs:preload_high_level}}\n```\n\nThe upload of the blob is handled inside of the `convert_into_loader` method. If you\nwant more fine-grained control over it, you can create the script transaction\nmanually:\n\n```rust,ignore\n{{#include ../../e2e/tests/scripts.rs:preload_low_level}}\n```\n\n## Predicates\n\nYou can prepare a predicate for pre-uploading without doing network requests:\n\n```rust,ignore\n{{#include ../../e2e/tests/predicates.rs:preparing_the_predicate}}\n```\n\nOnce you want to execute the predicate, you must beforehand upload the blob\ncontaining its code:\n\n```rust,ignore\n{{#include ../../e2e/tests/predicates.rs:uploading_the_blob}}\n```\n\nBy pre-uploading the predicate code, you allow for cheaper calls to the predicate\nfrom subsequent callers.\n"
  },
  {
    "path": "docs/src/reference.md",
    "content": "# API Reference\n\nFor a more in-depth look at the APIs provided by the Fuel Rust SDK, head over to the [official documentation](https://docs.rs/fuels/latest/fuels/). In the actual Rust docs, you can see the most up-to-date information about the API, which is synced with the code as it changes.\n"
  },
  {
    "path": "docs/src/running-scripts.md",
    "content": "# Running scripts\n\nYou can run a script using its JSON-ABI and the path to its binary file. You can run the scripts with arguments. For this, you have to use the `abigen!` macro seen [previously](./abigen/the-abigen-macro.md).\n\n```rust,ignore\n{{#include ../../e2e/tests/scripts.rs:script_with_arguments}}\n```\n\nFurthermore, if you need to separate submission from value retrieval for any reason, you can do so as follows:\n\n```rust,ignore\n{{#include ../../e2e/tests/scripts.rs:submit_response_script}}\n```\n\n## Running scripts with transaction policies\n\nThe method for passing transaction policies is the same as [with contracts](./calling-contracts/tx-policies.md). As a reminder, the workflow would look like this:\n\n```rust,ignore\n{{#include ../../e2e/tests/scripts.rs:script_with_tx_policies}}\n```\n\n## Custom inputs and outputs\n\nIf you need to add specific inputs and outputs to script calls, you can use the `with_inputs` and `with_outputs` methods.\n\n```rust,ignore\n{{#include ../../e2e/tests/scripts.rs:script_custom_inputs_outputs}}\n```\n\n> **Note:** if custom inputs include coins that need to be signed, use the `add_signer` method to add the appropriate signer.\n\n## Logs\n\nScript calls provide the same logging functions, `decode_logs()` and `decode_logs_with_type<T>()`, as contract calls. As a reminder, the workflow looks like this:\n\n```rust,ignore\n{{#include ../../e2e/tests/logs.rs:script_logs}}\n```\n\n## Calling contracts from scripts\n\nScripts use the same interfaces for setting external contracts as [contract methods](./calling-contracts/other-contracts.md).\n\nBelow is an example that uses `with_contracts(&[&contract_instance, ...])`.\n\n```rust,ignore\n{{#include ../../e2e/tests/logs.rs:external_contract}}\n```\n\nAnd this is an example that uses `with_contract_ids(&[&contract_id, ...])`.\n\n```rust,ignore\n{{#include ../../e2e/tests/logs.rs:external_contract_ids}}\n```\n\n## Configurable constants\n\nSame as contracts, you can define `configurable` constants in `scripts` which can be changed during the script execution. Here is an example how the constants are defined.\n\n```rust,ignore\n{{#include ../../e2e/sway/scripts/script_configurables/src/main.sw}}\n```\n\nEach configurable constant will get a dedicated `with` method in the SDK. For example, the constant `STR_4` will get the `with_STR_4` method which accepts the same type defined in sway. Below is an example where we chain several `with` methods and execute the script with the new constants.\n\n```rust,ignore\n{{#include ../../e2e/tests/configurables.rs:script_configurables}}\n```\n"
  },
  {
    "path": "docs/src/testing/basics.md",
    "content": "# Testing Basics\n\nIf you're new to Rust, you'll want to review these important tools to help you build tests.\n\n## The `assert!` macro\n\n<!-- This section should explain the `assert!` macro -->\n<!-- assert:example:start -->\n\nYou can use the `assert!` macro to assert certain conditions in your test. This macro invokes `panic!()` and fails the test if the expression inside evaluates to `false`.\n\n<!-- assert:example:end -->\n\n<!-- This section should show an example of the `assert!` macro -->\n<!-- assert_code:example:start -->\n\n```rust, ignore\nassert!(value == 5);\n```\n\n<!-- assert_code:example:end -->\n\n## The `assert_eq!` macro\n\n<!-- This section should show an example of the `assert_eq!` macro -->\n<!-- assert_eq:example:start -->\n\nThe `assert_eq!` macro works a lot like the `assert` macro, however instead it accepts two values, and panics if those values are not equal.\n\n<!-- assert_eq:example:end -->\n\n<!-- This section should show an example of the `assert_eq!` macro -->\n<!-- assert_eq_code:example:start -->\n\n```rust, ignore\nassert_eq!(balance, 100);\n```\n\n<!-- assert_eq_code:example:end -->\n\n## The `assert_ne!` macro\n\n<!-- This section should show an example of the `assert_ne!` macro -->\n<!-- assert_ne:example:start -->\n\nThe `assert_ne!` macro works just like the `assert_eq!` macro, but it will panic if the two values are equal.\n\n<!-- assert_ne:example:end -->\n\n<!-- This section should show an example of the `assert_ne!` macro -->\n<!-- assert_ne_code:example:start -->\n\n```rust, ignore\nassert_ne!(address, 0);\n```\n\n<!-- assert_ne_code:example:end -->\n\n## The `println!` macro\n\n<!-- This section should explain how the `println!` macro can be used in tests -->\n<!--print_ln:example:start -->\n\nYou can use the `println!` macro to print values to the console.\n\n<!--print_ln:example:end -->\n\n<!-- This section should show an example of the `println!` macro -->\n<!--print_ln_code:example:start -->\n\n```rust, ignore\nprintln!(\"WALLET 1 ADDRESS {}\", wallet_1.address());\nprintln!(\"WALLET 1 ADDRESS {:?}\", wallet_1.address());\n```\n\n<!--print_ln_code:example:end -->\n\n<!-- This section should explain how `{}` and `{:?}` are used in the `println!` macro -->\n<!--print_ln_2:example:start -->\n\nUsing `{}` will print the value, and using `{:?}` will print the value plus its type.\n\nUsing `{:?}` will also allow you to print values that do not have the `Display` trait implemented but do have the `Debug` trait. Alternatively you can use the `dbg!` macro to print these types of variables.\n\n<!--print_ln_2:example:end -->\n\n<!-- This section should show an example of the `println!` and `dbg` macros -->\n<!--print_ln_dbg_code:example:start -->\n\n```rust, ignore\nprintln!(\"WALLET 1 PROVIDER {:?}\", wallet_1.provider());\ndbg!(\"WALLET 1 PROVIDER {}\", wallet_1.provider());\n```\n\n<!--print_ln_dbg_code:example:end -->\n\n<!-- This section should explain how implement custom fmt -->\n<!--fmt:example:start -->\n\nTo print more complex types that don't have it already, you can implement your own formatted display method with the `fmt` module from the Rust standard library.\n\n<!--fmt:example:end -->\n\n<!-- This section should show a code example of how implement custom fmt -->\n<!--fmt_code:example:start -->\n\n```rust, ignore\nuse std::fmt;\n\nstruct Point {\n    x: u64,\n    y: u64,\n}\n\n// add print functionality with the fmt module\nimpl fmt::Display for Point {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        write!(f, \"value of x: {}, value of y: {}\", self.x, self.y)\n    }\n}\n\nlet p = Point {x: 1, y: 2};\nprintln!(\"POINT: {}\", p);\n```\n\n<!--fmt_code:example:end -->\n\n## Run Commands\n\nYou can run your tests to see if they pass or fail with\n\n```shell\ncargo test\n```\n\n<!-- This section should when outputs are hidden and what the `nocapture` flag does -->\n<!--outputs:example:start -->\n\nOutputs will be hidden if the test passes. If you want to see outputs printed from your tests regardless of whether they pass or fail, use the `nocapture` flag.\n\n<!--outputs:example:end -->\n\n```shell\ncargo test -- --nocapture\n```\n"
  },
  {
    "path": "docs/src/testing/chains.md",
    "content": "# Increasing the block height\n\nYou can use `produce_blocks` to help achieve an arbitrary block height; this is useful when you want to do any testing regarding transaction maturity.\n\n> **Note**: For the `produce_blocks` API to work, it is imperative to have `manual_blocks_enabled = true` in the config for the running node. See example below.\n\n```rust,ignore\n{{#include ../../../e2e/tests/providers.rs:use_produce_blocks_to_increase_block_height}}\n```\n\nYou can also set a custom block time as the second, optional argument. Here is an example:\n\n```rust,ignore\n{{#include ../../../e2e/tests/providers.rs:use_produce_blocks_custom_time}}\n```\n"
  },
  {
    "path": "docs/src/testing/index.md",
    "content": "# `fuels-rs` Testing\n\n> **note** This section is still a work in progress.\n\n- [Testing Basics](./basics.md)\n- [`setup_program_test!` Macro](./the-setup-program-test-macro.md)\n- [Tweaking the Blockchain](./chains.md)\n"
  },
  {
    "path": "docs/src/testing/the-setup-program-test-macro.md",
    "content": "# The setup_program_test! macro\n\nWhen deploying contracts with the `abigen!` macro, as shown in the previous sections, the user can:\n\n- change the default configuration parameters\n- launch several providers\n- create multiple wallets\n- create specific assets, etc.\n\nHowever, it is often the case that we want to quickly set up a test with default values and work directly with contract or script instances. The `setup_program_test!` can do exactly that.\n\n---\n\nUsed to reduce boilerplate in integration tests. Accepts input in the form\nof `COMMAND(ARG...)...`\n\n`COMMAND` is either `Wallets`, `Abigen`, `LoadScript` or `Deploy`.\n\n`ARG` is either a:\n\n- name-value (e.g. `name=\"MyContract\"`), or,\n- a literal (e.g. `\"some_str_literal\"`, `true`, `5`, ...)\n- a sub-command (e.g. `Abigen(Contract(name=\"MyContract\", project=\"some_project\"))`)\n\nAvailable `COMMAND`s:\n\n## Options\n\nExample: `Options(profile=\"debug\")`\n\nDescription: Sets options from `ARG`s to be used by other `COMMAND`s.\n\nAvailable options:\n\n- `profile`: sets the `cargo` build profile. Variants: `\"release\"` (default),  `\"debug\"`\n\nCardinality: 0 or 1.\n\n## Wallets\n\nExample: `Wallets(\"a_wallet\", \"another_wallet\"...)`\n\nDescription: Launches a local provider and generates wallets with names taken from the provided `ARG`s.\n\nCardinality: 0 or 1.\n\n## Abigen\n\nExample:\n\n```rust,ignore\nAbigen(\n    Contract(\n        name = \"MyContract\",\n        project = \"some_folder\"\n    ),\n    Script(\n        name = \"MyScript\",\n        project = \"some_folder\"\n    ),\n    Predicate(\n        name = \"MyPredicate\",\n        project = \"some_folder\"\n    ),\n)\n```\n\nDescription: Generates the program bindings under the name `name`. `project` should point to root of the `forc` project. The project must be compiled in `release` mode (`--release` flag) for `Abigen` command to work.\n\nCardinality: 0 or N.\n\n## Deploy\n\nExample: `Deploy(name=\"instance_name\", contract=\"MyContract\", wallet=\"a_wallet\")`\n\nDescription: Deploys the `contract` (with salt) using `wallet`. Will create a contract instance accessible via `name`. Due to salt usage, the same contract can be deployed multiple times. Requires that an `Abigen` command be present with `name` equal to `contract`. `wallet` can either be one of the wallets in the `Wallets` `COMMAND` or the name of a wallet you've previously generated yourself.\n\nCardinality: 0 or N.\n\n## `LoadScript`\n\nExample: `LoadScript(name = \"script_instance\", script = \"MyScript\", wallet = \"wallet\")`\n\nDescription: Creates a script instance of `script` under `name` using `wallet`.\n\nCardinality: 0 or N.\n\n---\n\nThe setup code that you have seen in previous sections gets reduced to:\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:deploy_contract_setup_macro_short}}\n```\n\n> **Note** The same contract can be deployed several times as the macro deploys the contracts with salt. You can also deploy different contracts to the same provider by referencing the same wallet in the `Deploy` command.\n\n```rust,ignore\n{{#include ../../../e2e/tests/contracts.rs:contract_setup_macro_multi}}\n```\n\nIn this example, three contracts are deployed on the same provider using the `wallet` generated by the `Wallets` command. The second and third macros use the same contract but have different IDs because of the deployment with salt. Both of them can call the first contract by using their ID.\n\nIn addition, you can manually create the `wallet` variable and then use it inside the macro. This is useful if you want to create custom wallets or providers but still want to use the macro to reduce boilerplate code. Below is an example of this approach.\n\n```rust,ignore\n{{#include ../../../e2e/tests/contracts.rs:contract_setup_macro_manual_wallet}}\n```\n"
  },
  {
    "path": "docs/src/types/B512.md",
    "content": "# `B512`\n\nIn the Rust SDK, the `B512` definition matches the Sway standard library type with the same name and will be converted accordingly when interacting with contracts:\n\n```rust,ignore\n{{#include ../../../packages/fuels-core/src/types/core/bits.rs:b512}}\n```\n\nHere's an example:\n\n```rust,ignore\n{{#include ../../../e2e/tests/types_contracts.rs:b512_example}}\n```\n"
  },
  {
    "path": "docs/src/types/address.md",
    "content": "# `Address`\n\nLike `Bytes32`, `Address` is a wrapper on `[u8; 32]` with similar methods and implements the same traits (see [fuel-types documentation](https://docs.rs/fuel-types/latest/fuel_types/struct.Address.html)).\n\nThese are the main ways of creating an `Address`:\n\n```rust,ignore\n{{#include ../../../examples/types/src/lib.rs:address}}\n```\n"
  },
  {
    "path": "docs/src/types/asset-id.md",
    "content": "# `AssetId`\n\nLike `Bytes32`, `AssetId` is a wrapper on `[u8; 32]` with similar methods and implements the same traits (see [fuel-types documentation](https://docs.rs/fuel-types/0.49.0/fuel_types/struct.AssetId.html)).\n\nThese are the main ways of creating an `AssetId`:\n\n```rust,ignore\n{{#include ../../../examples/types/src/lib.rs:asset_id}}\n```\n"
  },
  {
    "path": "docs/src/types/bits256.md",
    "content": "# `Bits256`\n\nIn Fuel, a type called `b256` represents hashes and holds a 256-bit value. The Rust SDK represents `b256` as `Bits256(value)` where `value` is a `[u8; 32]`. If your contract method takes a `b256` as input, you must pass a `Bits256([u8; 32])` when calling it from the SDK.\n\nHere's an example:\n\n```rust,ignore\n{{#include ../../../e2e/tests/types_contracts.rs:256_arg}}\n```\n\nIf you have a hexadecimal value as a string and wish to convert it to `Bits256`, you may do so with `from_hex_str`:\n\n```rust,ignore\n{{#include ../../../packages/fuels-core/src/types/core/bits.rs:from_hex_str}}\n```\n"
  },
  {
    "path": "docs/src/types/bytes.md",
    "content": "# `Bytes`\n\nIn Fuel, a type called `Bytes` represents a collection of tightly-packed bytes. The Rust SDK represents `Bytes` as `Bytes(Vec<u8>)`. Here's an example of using `Bytes` in a contract call:\n\n```rust,ignore\n{{#include ../../../e2e/tests/types_contracts.rs:bytes_arg}}\n```\n\nIf you have a hexadecimal value as a string and wish to convert it to `Bytes`, you may do so with `from_hex_str`:\n\n```rust,ignore\n{{#include ../../../packages/fuels-core/src/types/core/bytes.rs:bytes_from_hex_str}}\n```\n"
  },
  {
    "path": "docs/src/types/bytes32.md",
    "content": "# `Bytes32`\n\nIn Sway and the FuelVM, `Bytes32` represents hashes. They hold a 256-bit (32-byte) value. `Bytes32` is a wrapper on a 32-sized slice of `u8`: `pub struct Bytes32([u8; 32]);`.\n\nThese are the main ways of creating a `Bytes32`:\n\n```rust,ignore\n{{#include ../../../examples/types/src/lib.rs:bytes32}}\n```\n\n`Bytes32` also implements the `fmt` module's `Debug`, `Display`, `LowerHex` and `UpperHex` traits. For example, you can get the display and hex representations with:\n\n```rust,ignore\n{{#include ../../../examples/types/src/lib.rs:bytes32_format}}\n```\n\nFor a full list of implemented methods and traits, see the [fuel-types documentation](https://docs.rs/fuel-types/latest/fuel_types/struct.Bytes32.html).\n\n> **Note:** In Fuel, there's a special type called `b256`, which is similar to `Bytes32`; also used to represent hashes, and it holds a 256-bit value. In Rust, through the SDK, this is represented as `Bits256(value)` where `value` is a `[u8; 32]`. If your contract method takes a `b256` as input, all you need to do is pass a `Bits256([u8; 32])` when calling it from the SDK.\n"
  },
  {
    "path": "docs/src/types/contract-id.md",
    "content": "# `ContractId`\n\nLike `Bytes32`, `ContractId` is a wrapper on `[u8; 32]` with similar methods and implements the same traits (see [fuel-types documentation](https://docs.rs/fuel-types/0.49.0/fuel_types/struct.ContractId.html)).\n\nThese are the main ways of creating a `ContractId`:\n\n```rust,ignore\n{{#include ../../../examples/types/src/lib.rs:contract_id}}\n```\n"
  },
  {
    "path": "docs/src/types/conversion.md",
    "content": "# Converting Types\n\nBelow you can find examples for common type conversions:\n\n- [Convert Between Native Types](#convert-between-native-types)\n- [Convert to `Bytes32`](#convert-to-bytes32)\n- [Convert to `Address`](#convert-to-address)\n- [Convert to `ContractId`](#convert-to-contractid)\n- [Convert to `Identity`](#convert-to-identity)\n- [Convert to `AssetId`](#convert-to-assetid)\n- [Convert to `str`](#convert-to-str)\n- [Convert to `Bits256`](#convert-to-bits256)\n- [Convert to `Bytes`](#convert-to-bytes)\n- [Convert to `B512`](#convert-to-b512)\n- [Convert to `EvmAddress`](#convert-to-evmaddress)\n\n## Convert Between Native Types\n\nYou might want to convert between the native types (`Bytes32`, `Address`, `ContractId`, and `AssetId`). Because these types are wrappers on `[u8; 32]`, converting is a matter of dereferencing one and instantiating the other using the dereferenced value. Here's an example:\n\n```rust,ignore\n{{#include ../../../examples/types/src/lib.rs:type_conversion}}\n```\n\n## Convert to `Bytes32`\n\nConvert a `[u8; 32]` array to `Bytes32`:\n\n```rust,ignore\n{{#include ../../../examples/types/src/lib.rs:array_to_bytes32}}\n```\n\nConvert a hex string to `Bytes32`:\n\n```rust,ignore\n{{#include ../../../examples/types/src/lib.rs:hex_string_to_bytes32}}\n```\n\n## Convert to `Address`\n\nConvert a `[u8; 32]` array to an `Address`:\n\n```rust,ignore\n{{#include ../../../examples/types/src/lib.rs:array_to_address}}\n```\n\nConvert a wallet to an `Address`:\n\n```rust,ignore\n{{#include ../../../examples/wallets/src/lib.rs:wallet_to_address}}\n```\n\nConvert a hex string to an `Address`:\n\n```rust,ignore\n{{#include ../../../examples/types/src/lib.rs:hex_string_to_address}}\n```\n\n## Convert to `ContractId`\n\nConvert a `[u8; 32]` array to `ContractId`:\n\n```rust,ignore\n{{#include ../../../examples/types/src/lib.rs:array_to_contract_id}}\n```\n\nConvert a hex string to a `ContractId`:\n\n```rust,ignore\n{{#include ../../../examples/types/src/lib.rs:string_to_contract_id}}\n```\n\nConvert a contract instance to a `ContractId`:\n\n```rust,ignore\n{{#include ../../../e2e/tests/logs.rs:instance_to_contract_id}}\n```\n\n## Convert to `Identity`\n\nConvert an `Address` to an `Identity`:\n\n```rust,ignore\n{{#include ../../../examples/types/src/lib.rs:address_to_identity}}\n```\n\nConvert a `ContractId` to an `Identity`:\n\n```rust,ignore\n{{#include ../../../examples/types/src/lib.rs:contract_id_to_identity}}\n```\n\n## Convert to `AssetId`\n\nConvert a `[u8; 32]` array to an `AssetId`:\n\n```rust,ignore\n{{#include ../../../examples/types/src/lib.rs:array_to_asset_id}}\n```\n\nConvert a hex string to an `AssetId`:\n\n```rust,ignore\n{{#include ../../../examples/types/src/lib.rs:string_to_asset_id}}\n```\n\n## Convert to `str`\n\nConvert a `ContractId` to a `str`:\n\n```rust,ignore\n{{#include ../../../examples/types/src/lib.rs:contract_id_to_str}}\n```\n\nConvert an `Address` to a `str`:\n\n```rust,ignore\n{{#include ../../../examples/types/src/lib.rs:address_to_str}}\n```\n\nConvert an `AssetId` to a `str`:\n\n```rust,ignore\n{{#include ../../../examples/types/src/lib.rs:asset_id_to_str}}\n```\n\nConvert `Bytes32` to a `str`:\n\n```rust,ignore\n{{#include ../../../examples/types/src/lib.rs:bytes32_to_str}}\n```\n\n## Convert to `Bits256`\n\nConvert a hex string to `Bits256`:\n\n```rust,ignore\n{{#include ../../../packages/fuels-core/src/types/core/bits.rs:hex_str_to_bits256}}\n```\n\nConvert a `ContractId` to `Bits256`:\n\n```rust,ignore\n{{#include ../../../examples/types/src/lib.rs:contract_id_to_bits256}}\n```\n\nConvert an `Address` to `Bits256`:\n\n```rust,ignore\n{{#include ../../../examples/types/src/lib.rs:address_to_bits256}}\n```\n\nConvert an `AssetId` to `Bits256`:\n\n```rust,ignore\n{{#include ../../../examples/types/src/lib.rs:asset_id_to_bits256}}\n```\n\n## Convert to `Bytes`\n\nConvert a string to `Bytes`:\n\n```rust,ignore\n{{#include ../../../packages/fuels-core/src/types/core/bytes.rs:hex_string_to_bytes32}}\n```\n\n## Convert to `B512`\n\nConvert two hex strings to `B512`:\n\n```rust,ignore\n{{#include ../../../e2e/tests/types_contracts.rs:b512_example}}\n```\n\n## Convert to `EvmAddress`\n\nConvert a `Bits256` address to an `EvmAddress`:\n\n```rust,ignore\n{{#include ../../../examples/types/src/lib.rs:b256_to_evm_address}}\n```\n"
  },
  {
    "path": "docs/src/types/custom_types.md",
    "content": "# Structs and enums\n\n<!-- This section should explain how to get the custom types from a Sway program -->\n<!-- custom_types:example:start -->\nThe structs and enums you define in your Sway code have equivalents automatically generated by the SDK's `abigen!` macro.\n<!-- custom_types:example:end -->\n\nFor instance, if in your Sway code you have a struct called `CounterConfig` that looks like this:\n\n```rust,ignore\nstruct CounterConfig {\n  dummy: bool,\n  initial_value: u64,\n}\n```\n\nAfter using the `abigen!` macro, `CounterConfig` will be accessible in your Rust file! Here's an example:\n\n```rust,ignore\n{{#include ../../../e2e/tests/types_contracts.rs:struct_generation}}\n```\n\nYou can freely use your custom types (structs or enums) within this scope. That also means passing custom types to functions and receiving custom types from function calls.\n\n## Generics\n\nThe Fuel Rust SDK supports both generic enums and generic structs. If you're already familiar with Rust, it's your typical `struct MyStruct<T>` type of generics support.\n\nFor instance, your Sway contract could look like this:\n\n```Rust\ncontract;\n\nuse std::hash::sha256;\n\nstruct SimpleGeneric<T> {\n    single_generic_param: T,\n}\n\nabi MyContract {\n  fn struct_w_generic(arg1: SimpleGeneric<u64>) -> SimpleGeneric<u64>;\n}\n\nimpl MyContract for Contract {\n    fn struct_w_generic(arg1: SimpleGeneric<u64>) -> SimpleGeneric<u64> {\n        let expected = SimpleGeneric {\n            single_generic_param: 123u64,\n        };\n\n        assert(arg1.single_generic_param == expected.single_generic_param);\n\n        expected\n    }\n}\n```\n\nYour Rust code would look like this:\n\n```rust,ignore\n{{#include ../../../e2e/tests/types_contracts.rs:generic}}\n```\n\n### Unused generic type parameters\n\nSway supports unused generic type parameters when declaring structs/enums:\n\n```Rust\nstruct SomeStruct<T, K> {\n  field: u64\n}\n\nenum SomeEnum<T, K> {\n  One: u64\n}\n\n```\n\nIf you tried the same in Rust you'd get complaints that `T` and `K` must be used or removed. When generating Rust bindings for such types we make use of the [`PhantomData`](https://doc.rust-lang.org/std/marker/struct.PhantomData.html#unused-type-parameters) type. The generated bindings for the above example would look something like this:\n\n```Rust\nstruct SomeStruct<T, K> {\n   pub field: u64,\n   pub _unused_generic_0: PhantomData<T>\n   pub _unused_generic_1: PhantomData<K>\n}\n\nenum SomeEnum<T, K> {\n  One(u64),\n  IgnoreMe(PhantomData<T>, PhantomData<K>)\n}\n```\n\nTo lessen the impact to developer experience you may use the `new` method to initialize a structure without bothering with the `PhantomData`s.:\n\n```rust,ignore\n{{#include ../../../examples/types/src/lib.rs:unused_generics_struct}}\n```\n\nIf your struct doesn't have any fields we'll also derive `Default`. As for enums all `PhantomData`s are placed inside a new variant called `IgnoreMe` which you'll need to ignore in your matches:\n\n```rust,ignore\n{{#include ../../../examples/types/src/lib.rs:unused_generics_enum}}\n```\n"
  },
  {
    "path": "docs/src/types/evm_address.md",
    "content": "# `EvmAddress`\n\nIn the Rust SDK, Ethereum Virtual Machine (EVM) addresses can be represented with the `EvmAddress` type. Its definition matches with the Sway standard library type with the same name and will be converted accordingly when interacting with contracts:\n\n```rust,ignore\n{{#include ../../../packages/fuels-core/src/types/core/bits.rs:evm_address}}\n```\n\nHere's an example:\n\n```rust,ignore\n{{#include ../../../e2e/tests/types_contracts.rs:evm_address_arg}}\n```\n\n> **Note:** when creating an `EvmAddress` from `Bits256`, the first 12 bytes will be cleared because an EVM address is only 20 bytes long.\n"
  },
  {
    "path": "docs/src/types/index.md",
    "content": "# Types\n\nThe FuelVM and Sway have many internal types. These types have equivalents in the SDK. This section discusses these types, how to use them, and how to convert them.\n"
  },
  {
    "path": "docs/src/types/string.md",
    "content": "# `String`\n\nThe Rust SDK represents Fuel's `String`s as `SizedAsciiString<LEN>`, where the generic parameter `LEN` is the length of a given string. This abstraction is necessary because all strings in Fuel and Sway are statically-sized, i.e., you must know the size of the string beforehand.\n\nHere's how you can create a simple string using `SizedAsciiString`:\n\n```rust,ignore\n{{#include ../../../packages/fuels-core/src/types/core/sized_ascii_string.rs:string_simple_example}}\n```\n\nTo make working with `SizedAsciiString`s easier, you can use `try_into()` to convert from Rust's `String` to `SizedAsciiString`, and you can use `into()` to convert from `SizedAsciiString` to Rust's `String`. Here are a few examples:\n\n```rust,ignore\n{{#include ../../../packages/fuels-core/src/types/core/sized_ascii_string.rs:conversion}}\n```\n\nIf your contract's method takes and returns, for instance, a Sway's `str[23]`. When using the SDK, this method will take and return a `SizedAsciiString<23>`.\n"
  },
  {
    "path": "docs/src/types/vectors.md",
    "content": "# Vectors\n\n## Passing in vectors\n\nYou can pass a Rust `std::vec::Vec` into your contract method transparently. The following code calls a Sway contract method which accepts a `Vec<SomeStruct<u32>>`.\n\n```rust,ignore\n{{#include ../../../e2e/tests/types_contracts.rs:passing_in_vec}}\n```\n\nYou can use a vector just like you would use any other type -- e.g. a `[Vec<u32>; 2]` or a `SomeStruct<Vec<Bits256>>` etc.\n\n## Returning vectors\n\nReturning vectors from contract methods is supported transparently, with the caveat that you cannot have them nested inside another type. This limitation is temporary.\n\n```rust,ignore\n{{#include ../../../e2e/tests/types_contracts.rs:returning_vec}}\n```\n\n> **Note: you can still interact with contracts containing methods that return vectors nested inside another type, just not interact with the methods themselves**\n"
  },
  {
    "path": "docs/src/wallets/access.md",
    "content": "# Wallet Access\n\nThe kinds of operations we can perform with a `Wallet` instance depend on\nwhether or not the wallet has a signer attached to it.\n\nIn order to differentiate between `Wallet` instances that have a signer\nand those that do not, we use the `Wallet<Unlocked<S>>` and `Wallet<Locked>` types\nrespectively.\n\n## Wallet States\n\nThe `Wallet<Unlocked<S>>` type represents a wallet that has a signer. A wallet must be of type `Wallet<Unlocked<S>>` in order to perform operations that involve signing messages or transactions.\n\nYou can learn more about signing [here](./signing.md).\n\nThe `Wallet<Locked>` type represents a wallet without a signer. Instead, `Wallet<Locked>` only knows its public address. A `Wallet<Locked>` cannot be used to sign transactions, however it may still perform a whole suite of useful operations including listing transactions, assets, querying balances, and so on.\n\n## Transitioning States\n\nA `Wallet<Unlocked<S>>` instance can be locked using the `lock` method:\n\n```rust,ignore\nlet wallet_locked = wallet_unlocked.lock();\n```\n\n## Design Guidelines\n\nWhen designing APIs that accept a wallet as an input, we should think carefully\nabout the kind of access that we require. API developers should aim to minimise\ntheir usage of `Wallet<Unlocked<S>>` in order to ensure signers are stored in\nmemory no longer than necessary to reduce the surface area for attacks and\nvulnerabilities in downstream libraries and applications.\n"
  },
  {
    "path": "docs/src/wallets/checking-balances-and-coins.md",
    "content": "# Checking balances and coins\n\n<!-- This section should explain getting the balance of a wallet -->\n<!-- balance:example:start -->\nIn the Fuel network, each UTXO corresponds to a unique _coin_, and said _coin_ has a corresponding _amount_ (the same way a dollar bill has either 10$ or 5$ face value). So, when you want to query the balance for a given asset ID, you want to query the sum of the amount in each unspent coin. This querying is done very easily with a wallet:\n<!-- balance:example:end -->\n\n```rust,ignore\n{{#include ../../../examples/wallets/src/lib.rs:get_asset_balance}}\n```\n\n<!-- This section should explain getting all of the balances of a wallet -->\n<!-- balances:example:start -->\nIf you want to query all the balances (i.e., get the balance for each asset ID in that wallet), you can use the `get_balances` method:\n<!-- balances:example:end -->\n\n```rust,ignore\n{{#include ../../../examples/wallets/src/lib.rs:get_balances}}\n```\n\n<!-- This section should explain the return type for `get_balances` -->\n<!-- balances_return:example:start -->\nThe return type is a `HashMap`, where the key is the _asset ID's_ hex string, and the value is the corresponding balance. For example, we can get the base asset balance with:\n<!-- balances_return:example:end -->\n\n```rust,ignore\n{{#include ../../../examples/wallets/src/lib.rs:get_balance_hashmap}}\n```\n"
  },
  {
    "path": "docs/src/wallets/fake_signer.md",
    "content": "# Fake signer (impersonating another account)\n\nTo facilitate account impersonation, the Rust SDK provides the `FakeSigner`. We can use it to simulate ownership of assets held by an account with a given address. This also implies that we can impersonate contract calls from that address. A wallet with a `FakeSigner` will only succeed in unlocking assets if the network is set up with `utxo_validation = false`.\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:utxo_validation_off}}\n```\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:utxo_validation_off_node_start}}\n```\n\n```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:contract_call_impersonation}}\n```\n"
  },
  {
    "path": "docs/src/wallets/index.md",
    "content": "# Wallets\n\nWallets serve as a centralized interface for all account-related behaviors. They allow you to:\n\n- **Inspect UTXOs:** Check available coins for spending.\n- **Prepare and send transactions:** Build, sign, and submit transfers.\n- **Manage network fees:** Pay for transaction execution and contract deployment.\n\nEvery wallet requires a **provider** to communicate with the network.\n\n---\n\n## Types of Wallets\n\nThere are two primary types of wallets available in the SDK:\n\n### [Locked Wallets](./access.md)\n\n- **Purpose:** Used for read-only operations.\n- **Interface:** Implements the [`ViewOnlyAccount`](../accounts.md) trait.\n- **Use Cases:** Checking balances, viewing UTXOs, and monitoring transactions without the ability to sign or submit transactions.\n\n### [Unlocked Wallets](./access.md)\n\n- **Purpose:** Supports full account functionality.\n- **Interface:** Implements the [`ViewOnlyAccount`](../accounts.md) and [`Account`](../accounts.md) traits.\n- **Additional Requirement:** In addition to a provider, an unlocked wallet must include a **signer**.\n- **Use Cases:** Transferring funds, signing messages, submitting transactions, and performing state-changing operations.\n\n---\n\n## Signer Options\n\nThe SDK offers multiple signing methods to suit different scenarios:\n\n- [**Private Key Signer:**](./private_key_signer.md)  \n  Use when you have direct access to your account’s private key.\n- [**AWS KMS Signer:**](./kms.md)\n  Delegate signing operations to AWS Key Management Service, enhancing key security by offloading cryptographic operations.\n\n- [**Google KMS Signer:**](./kms.md)  \n  Similar to AWS KMS, this option delegates signing to Google’s Key Management Service.\n\n- [**Fake Signer:**](./fake_signer.md)  \n  Generates dummy signatures, which is useful for impersonation while testing. Only possible when using a network that does not enforce signature validation.\n\n---\n"
  },
  {
    "path": "docs/src/wallets/keystore.md",
    "content": "# Encrypting and Storing Keys\n\nThe code below shows how to:\n\n- Encrypt and store your key using a master password.\n- Ensure that the key can be retrieved later with the proper credentials.\n\n```rust,ignore\n{{#include ../../../examples/wallets/src/lib.rs:create_and_store_mnemonic_key}}\n```\n"
  },
  {
    "path": "docs/src/wallets/kms.md",
    "content": "# Using KMS Wallets\n\nKey Management Service (KMS) is a robust and secure solution for managing cryptographic keys for your Fuel wallets. Instead of keeping private keys on your local system, KMS Wallets leverage secure infrastructure to handle both key storage and signing operations.\n\nThe SDK provides signers for AWS and Google KMS.\n\nBelow is an example of how to initialize a wallet with a AWS KMS signer:\n\n```rust,ignore\n{{#include ../../../e2e/tests/aws.rs:use_kms_wallet}}\n```\n"
  },
  {
    "path": "docs/src/wallets/private_key_signer.md",
    "content": "# Using private keys to create wallets\n\n## Directly from a private key\n\nAn example of how to create a wallet that uses a private key signer:\n\n```rust,ignore\n{{#include ../../../examples/wallets/src/lib.rs:create_wallet_from_secret_key}}\n```\n\nThere is also a helper for generating a wallet with a random private key signer:\n\n```rust,ignore\n{{#include ../../../examples/wallets/src/lib.rs:create_random_wallet}}\n```\n\n## From a mnemonic phrase\n\nA mnemonic phrase is a cryptographically generated sequence of words used to create a master seed. This master seed, when combined with a [derivation path](https://thebitcoinmanual.com/articles/btc-derivation-path/), enables the generation of one or more specific private keys. The derivation path acts as a roadmap within the [hierarchical deterministic (HD) wallet structure](https://www.ledger.com/academy/crypto/what-are-hierarchical-deterministic-hd-wallets), determining which branch of the key tree produces the desired private key.\n\n```rust,ignore\n{{#include ../../../examples/wallets/src/lib.rs:create_wallet_from_mnemonic}}\n```\n\n## Security Best Practices\n\n- **Never Share Sensitive Information:**\n  Do not disclose your private key or mnemonic phrase to anyone.\n\n- **Secure Storage:**\n  When storing keys on disk, **always encrypt** them (the SDK provides a [`Keystore`](./keystore.md). This applies to both plain private/secret keys and mnemonic phrases.\n"
  },
  {
    "path": "docs/src/wallets/signing.md",
    "content": "# Signing\n\nAn example of how you might sign a message using any of the SDK signers (or your\nown, custom ones, that implement `Signer`):\n\n```rust,ignore\n{{#include ../../../packages/fuels-accounts/src/signers/private_key.rs:sign_message}}\n```\n\n## Adding `Signers` to a transaction builder\n\nEvery signed resource in the inputs needs to have a witness index that points to a valid witness. Changing the witness index inside an input will change the transaction ID. This means that we need to set all witness indexes before finally signing the transaction. We have to make sure that the witness indexes and the order of the witnesses are correct. To automate this process, the SDK will keep track of the signers in the transaction builder and resolve the final transaction automatically. This is done by storing signers until the final transaction is built.\n\nBelow is a full example of how to create a transaction builder and add signers to it.\n\n> Note: When you add a `Signer` to a transaction builder, the signer is stored inside it and the transaction will not be resolved until you call `build()`!\n\n```rust,ignore\n{{#include ../../../packages/fuels-accounts/src/account.rs:sign_tb}}\n```\n\n## Signing a built transaction\n\nIf you have a built transaction and want to add a signature, you can use the `sign_with` method.\n\n```rust,ignore\n{{#include ../../../e2e/tests/contracts.rs:tx_sign_with}}\n```\n"
  },
  {
    "path": "docs/src/wallets/test-wallets.md",
    "content": "# Setting up test wallets\n\nYou'll often want to create one or more test wallets when testing your contracts. Here's how to do it.\n\n## Setting up multiple test wallets\n\n<!-- This section should explain setting up multiple test wallets -->\n<!-- test_wallets:example:start -->\nIf you need multiple test wallets, they can be set up using the `launch_custom_provider_and_get_wallets` method.\n<!-- test_wallets:example:end -->\n\n```rust,ignore\n{{#include ../../../examples/wallets/src/lib.rs:multiple_wallets_helper}}\n```\n\n<!-- This section should explain how to customize test wallets -->\n<!-- custom_test_wallets:example:start -->\nYou can customize your test wallets via `WalletsConfig`.\n<!-- custom_test_wallets:example:end -->\n\n```rust,ignore\n{{#include ../../../examples/wallets/src/lib.rs:setup_5_wallets}}\n```\n\n<!-- This section should explain that test wallets are deterministic -->\n<!-- deterministic:example:start -->\n>**Note** Wallets generated with `launch_provider_and_get_wallet` or `launch_custom_provider_and_get_wallets`\nwill have deterministic addresses.\n<!-- deterministic:example:end -->\n\n## Setting up a test wallet with multiple random assets\n\nYou can create a test wallet containing multiple assets (including the base asset to pay for gas).\n\n```rust,ignore\n{{#include ../../../examples/wallets/src/lib.rs:multiple_assets_wallet}}\n```\n\n- coins: `Vec<(UtxoId, Coin)>` has `num_assets` * `coins_per_assets` coins (UTXOs)\n- asset_ids: `Vec<AssetId>` contains the `num_assets` randomly generated `AssetId`s (always includes the base asset)\n\n## Setting up a test wallet with multiple custom assets\n\nYou can also create assets with specific `AssetId`s, coin amounts, and number of coins.\n\n```rust,ignore\n{{#include ../../../examples/wallets/src/lib.rs:custom_assets_wallet}}\n```\n\nThis can also be achieved directly with the `WalletsConfig`.\n\n```rust,ignore\n{{#include ../../../examples/wallets/src/lib.rs:custom_assets_wallet_short}}\n```\n\n>**Note** In this case, you need to manually add the base asset and the corresponding number of\n>coins and coin amount\n\n## Setting up assets\n\nThe Fuel blockchain holds many different assets; you can create your asset with its unique `AssetId` or create random assets for testing purposes.\n\nYou can use only one asset to pay for transaction fees and gas: the base asset, whose `AssetId` is `0x000...0`, a 32-byte zeroed value.\n\nFor testing purposes, you can configure coins and amounts for assets. You can use `setup_multiple_assets_coins`:\n\n```rust,ignore\n{{#include ../../../examples/wallets/src/lib.rs:multiple_assets_coins}}\n```\n\n>**Note** If setting up multiple assets, one of these assets will always be the base asset.\n\nIf you want to create coins only with the base asset, then you can use:\n\n```rust,ignore\n{{#include ../../../examples/providers/src/lib.rs:setup_single_asset}}\n```\n\n>**Note** Choosing a large number of coins and assets for `setup_multiple_assets_coins` or `setup_single_asset_coins` can lead to considerable runtime for these methods. This will be improved in the future but for now, we recommend using up to **1_000_000** coins, or **1000** coins and assets simultaneously.\n"
  },
  {
    "path": "docs/theme/highlight.js",
    "content": "/*!\n  Highlight.js v11.3.1 (git: 2a972d8658)\n  (c) 2006-2022 Ivan Sagalaev and other contributors\n  License: BSD-3-Clause\n */\nvar hljs=function(){\"use strict\";var e={exports:{}};function t(e){\nreturn e instanceof Map?e.clear=e.delete=e.set=()=>{\nthrow Error(\"map is read-only\")}:e instanceof Set&&(e.add=e.clear=e.delete=()=>{\nthrow Error(\"set is read-only\")\n}),Object.freeze(e),Object.getOwnPropertyNames(e).forEach((n=>{var s=e[n]\n;\"object\"!=typeof s||Object.isFrozen(s)||t(s)})),e}\ne.exports=t,e.exports.default=t;var n=e.exports;class s{constructor(e){\nvoid 0===e.data&&(e.data={}),this.data=e.data,this.isMatchIgnored=!1}\nignoreMatch(){this.isMatchIgnored=!0}}function i(e){\nreturn e.replace(/&/g,\"&amp;\").replace(/</g,\"&lt;\").replace(/>/g,\"&gt;\").replace(/\"/g,\"&quot;\").replace(/'/g,\"&#x27;\")\n}function a(e,...t){const n=Object.create(null);for(const t in e)n[t]=e[t]\n;return t.forEach((e=>{for(const t in e)n[t]=e[t]})),n}const r=e=>!!e.kind\n;class o{constructor(e,t){\nthis.buffer=\"\",this.classPrefix=t.classPrefix,e.walk(this)}addText(e){\nthis.buffer+=i(e)}openNode(e){if(!r(e))return;let t=e.kind\n;t=e.sublanguage?\"language-\"+t:((e,{prefix:t})=>{if(e.includes(\".\")){\nconst n=e.split(\".\")\n;return[`${t}${n.shift()}`,...n.map(((e,t)=>`${e}${\"_\".repeat(t+1)}`))].join(\" \")\n}return`${t}${e}`})(t,{prefix:this.classPrefix}),this.span(t)}closeNode(e){\nr(e)&&(this.buffer+=\"</span>\")}value(){return this.buffer}span(e){\nthis.buffer+=`<span class=\"${e}\">`}}class l{constructor(){this.rootNode={\nchildren:[]},this.stack=[this.rootNode]}get top(){\nreturn this.stack[this.stack.length-1]}get root(){return this.rootNode}add(e){\nthis.top.children.push(e)}openNode(e){const t={kind:e,children:[]}\n;this.add(t),this.stack.push(t)}closeNode(){\nif(this.stack.length>1)return this.stack.pop()}closeAllNodes(){\nfor(;this.closeNode(););}toJSON(){return JSON.stringify(this.rootNode,null,4)}\nwalk(e){return this.constructor._walk(e,this.rootNode)}static _walk(e,t){\nreturn\"string\"==typeof t?e.addText(t):t.children&&(e.openNode(t),\nt.children.forEach((t=>this._walk(e,t))),e.closeNode(t)),e}static _collapse(e){\n\"string\"!=typeof e&&e.children&&(e.children.every((e=>\"string\"==typeof e))?e.children=[e.children.join(\"\")]:e.children.forEach((e=>{\nl._collapse(e)})))}}class c extends l{constructor(e){super(),this.options=e}\naddKeyword(e,t){\"\"!==e&&(this.openNode(t),this.addText(e),this.closeNode())}\naddText(e){\"\"!==e&&this.add(e)}addSublanguage(e,t){const n=e.root\n;n.kind=t,n.sublanguage=!0,this.add(n)}toHTML(){\nreturn new o(this,this.options).value()}finalize(){return!0}}function d(e){\nreturn e?\"string\"==typeof e?e:e.source:null}function u(e){return b(\"(?=\",e,\")\")}\nfunction g(e){return b(\"(?:\",e,\")*\")}function h(e){return b(\"(?:\",e,\")?\")}\nfunction b(...e){return e.map((e=>d(e))).join(\"\")}function p(...e){const t=(e=>{\nconst t=e[e.length-1]\n;return\"object\"==typeof t&&t.constructor===Object?(e.splice(e.length-1,1),t):{}\n})(e);return\"(\"+(t.capture?\"\":\"?:\")+e.map((e=>d(e))).join(\"|\")+\")\"}\nfunction f(e){return RegExp(e.toString()+\"|\").exec(\"\").length-1}\nconst m=/\\[(?:[^\\\\\\]]|\\\\.)*\\]|\\(\\??|\\\\([1-9][0-9]*)|\\\\./\n;function E(e,{joinWith:t}){let n=0;return e.map((e=>{n+=1;const t=n\n;let s=d(e),i=\"\";for(;s.length>0;){const e=m.exec(s);if(!e){i+=s;break}\ni+=s.substring(0,e.index),\ns=s.substring(e.index+e[0].length),\"\\\\\"===e[0][0]&&e[1]?i+=\"\\\\\"+(Number(e[1])+t):(i+=e[0],\n\"(\"===e[0]&&n++)}return i})).map((e=>`(${e})`)).join(t)}\nconst _=\"[a-zA-Z]\\\\w*\",w=\"[a-zA-Z_]\\\\w*\",y=\"\\\\b\\\\d+(\\\\.\\\\d+)?\",N=\"(-?)(\\\\b0[xX][a-fA-F0-9]+|(\\\\b\\\\d+(\\\\.\\\\d*)?|\\\\.\\\\d+)([eE][-+]?\\\\d+)?)\",x=\"\\\\b(0b[01]+)\",k={\nbegin:\"\\\\\\\\[\\\\s\\\\S]\",relevance:0},v={scope:\"string\",begin:\"'\",end:\"'\",\nillegal:\"\\\\n\",contains:[k]},O={scope:\"string\",begin:'\"',end:'\"',illegal:\"\\\\n\",\ncontains:[k]},S=(e,t,n={})=>{const s=a({scope:\"comment\",begin:e,end:t,\ncontains:[]},n);s.contains.push({scope:\"doctag\",\nbegin:\"[ ]*(?=(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):)\",\nend:/(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):/,excludeBegin:!0,relevance:0})\n;const i=p(\"I\",\"a\",\"is\",\"so\",\"us\",\"to\",\"at\",\"if\",\"in\",\"it\",\"on\",/[A-Za-z]+['](d|ve|re|ll|t|s|n)/,/[A-Za-z]+[-][a-z]+/,/[A-Za-z][a-z]{2,}/)\n;return s.contains.push({begin:b(/[ ]+/,\"(\",i,/[.]?[:]?([.][ ]|[ ])/,\"){3}\")}),s\n},R=S(\"//\",\"$\"),M=S(\"/\\\\*\",\"\\\\*/\"),I=S(\"#\",\"$\");var A=Object.freeze({\n__proto__:null,MATCH_NOTHING_RE:/\\b\\B/,IDENT_RE:_,UNDERSCORE_IDENT_RE:w,\nNUMBER_RE:y,C_NUMBER_RE:N,BINARY_NUMBER_RE:x,\nRE_STARTERS_RE:\"!|!=|!==|%|%=|&|&&|&=|\\\\*|\\\\*=|\\\\+|\\\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\\\?|\\\\[|\\\\{|\\\\(|\\\\^|\\\\^=|\\\\||\\\\|=|\\\\|\\\\||~\",\nSHEBANG:(e={})=>{const t=/^#![ ]*\\//\n;return e.binary&&(e.begin=b(t,/.*\\b/,e.binary,/\\b.*/)),a({scope:\"meta\",begin:t,\nend:/$/,relevance:0,\"on:begin\":(e,t)=>{0!==e.index&&t.ignoreMatch()}},e)},\nBACKSLASH_ESCAPE:k,APOS_STRING_MODE:v,QUOTE_STRING_MODE:O,PHRASAL_WORDS_MODE:{\nbegin:/\\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\\b/\n},COMMENT:S,C_LINE_COMMENT_MODE:R,C_BLOCK_COMMENT_MODE:M,HASH_COMMENT_MODE:I,\nNUMBER_MODE:{scope:\"number\",begin:y,relevance:0},C_NUMBER_MODE:{scope:\"number\",\nbegin:N,relevance:0},BINARY_NUMBER_MODE:{scope:\"number\",begin:x,relevance:0},\nREGEXP_MODE:{begin:/(?=\\/[^/\\n]*\\/)/,contains:[{scope:\"regexp\",begin:/\\//,\nend:/\\/[gimuy]*/,illegal:/\\n/,contains:[k,{begin:/\\[/,end:/\\]/,relevance:0,\ncontains:[k]}]}]},TITLE_MODE:{scope:\"title\",begin:_,relevance:0},\nUNDERSCORE_TITLE_MODE:{scope:\"title\",begin:w,relevance:0},METHOD_GUARD:{\nbegin:\"\\\\.\\\\s*[a-zA-Z_]\\\\w*\",relevance:0},END_SAME_AS_BEGIN:e=>Object.assign(e,{\n\"on:begin\":(e,t)=>{t.data._beginMatch=e[1]},\"on:end\":(e,t)=>{\nt.data._beginMatch!==e[1]&&t.ignoreMatch()}})});function T(e,t){\n\".\"===e.input[e.index-1]&&t.ignoreMatch()}function D(e,t){\nvoid 0!==e.className&&(e.scope=e.className,delete e.className)}function j(e,t){\nt&&e.beginKeywords&&(e.begin=\"\\\\b(\"+e.beginKeywords.split(\" \").join(\"|\")+\")(?!\\\\.)(?=\\\\b|\\\\s)\",\ne.__beforeBegin=T,e.keywords=e.keywords||e.beginKeywords,delete e.beginKeywords,\nvoid 0===e.relevance&&(e.relevance=0))}function C(e,t){\nArray.isArray(e.illegal)&&(e.illegal=p(...e.illegal))}function B(e,t){\nif(e.match){\nif(e.begin||e.end)throw Error(\"begin & end are not supported with match\")\n;e.begin=e.match,delete e.match}}function L(e,t){\nvoid 0===e.relevance&&(e.relevance=1)}const z=(e,t)=>{if(!e.beforeMatch)return\n;if(e.starts)throw Error(\"beforeMatch cannot be used with starts\")\n;const n=Object.assign({},e);Object.keys(e).forEach((t=>{delete e[t]\n})),e.keywords=n.keywords,e.begin=b(n.beforeMatch,u(n.begin)),e.starts={\nrelevance:0,contains:[Object.assign(n,{endsParent:!0})]\n},e.relevance=0,delete n.beforeMatch\n},$=[\"of\",\"and\",\"for\",\"in\",\"not\",\"or\",\"if\",\"then\",\"parent\",\"list\",\"value\"]\n;function U(e,t,n=\"keyword\"){const s=Object.create(null)\n;return\"string\"==typeof e?i(n,e.split(\" \")):Array.isArray(e)?i(n,e):Object.keys(e).forEach((n=>{\nObject.assign(s,U(e[n],t,n))})),s;function i(e,n){\nt&&(n=n.map((e=>e.toLowerCase()))),n.forEach((t=>{const n=t.split(\"|\")\n;s[n[0]]=[e,H(n[0],n[1])]}))}}function H(e,t){\nreturn t?Number(t):(e=>$.includes(e.toLowerCase()))(e)?0:1}const P={},K=e=>{\nconsole.error(e)},G=(e,...t)=>{console.log(\"WARN: \"+e,...t)},F=(e,t)=>{\nP[`${e}/${t}`]||(console.log(`Deprecated as of ${e}. ${t}`),P[`${e}/${t}`]=!0)\n},Z=Error();function W(e,t,{key:n}){let s=0;const i=e[n],a={},r={}\n;for(let e=1;e<=t.length;e++)r[e+s]=i[e],a[e+s]=!0,s+=f(t[e-1])\n;e[n]=r,e[n]._emit=a,e[n]._multi=!0}function X(e){(e=>{\ne.scope&&\"object\"==typeof e.scope&&null!==e.scope&&(e.beginScope=e.scope,\ndelete e.scope)})(e),\"string\"==typeof e.beginScope&&(e.beginScope={\n_wrap:e.beginScope}),\"string\"==typeof e.endScope&&(e.endScope={_wrap:e.endScope\n}),(e=>{if(Array.isArray(e.begin)){\nif(e.skip||e.excludeBegin||e.returnBegin)throw K(\"skip, excludeBegin, returnBegin not compatible with beginScope: {}\"),\nZ\n;if(\"object\"!=typeof e.beginScope||null===e.beginScope)throw K(\"beginScope must be object\"),\nZ;W(e,e.begin,{key:\"beginScope\"}),e.begin=E(e.begin,{joinWith:\"\"})}})(e),(e=>{\nif(Array.isArray(e.end)){\nif(e.skip||e.excludeEnd||e.returnEnd)throw K(\"skip, excludeEnd, returnEnd not compatible with endScope: {}\"),\nZ\n;if(\"object\"!=typeof e.endScope||null===e.endScope)throw K(\"endScope must be object\"),\nZ;W(e,e.end,{key:\"endScope\"}),e.end=E(e.end,{joinWith:\"\"})}})(e)}function q(e){\nfunction t(t,n){\nreturn RegExp(d(t),\"m\"+(e.case_insensitive?\"i\":\"\")+(e.unicodeRegex?\"u\":\"\")+(n?\"g\":\"\"))\n}class n{constructor(){\nthis.matchIndexes={},this.regexes=[],this.matchAt=1,this.position=0}\naddRule(e,t){\nt.position=this.position++,this.matchIndexes[this.matchAt]=t,this.regexes.push([t,e]),\nthis.matchAt+=f(e)+1}compile(){0===this.regexes.length&&(this.exec=()=>null)\n;const e=this.regexes.map((e=>e[1]));this.matcherRe=t(E(e,{joinWith:\"|\"\n}),!0),this.lastIndex=0}exec(e){this.matcherRe.lastIndex=this.lastIndex\n;const t=this.matcherRe.exec(e);if(!t)return null\n;const n=t.findIndex(((e,t)=>t>0&&void 0!==e)),s=this.matchIndexes[n]\n;return t.splice(0,n),Object.assign(t,s)}}class s{constructor(){\nthis.rules=[],this.multiRegexes=[],\nthis.count=0,this.lastIndex=0,this.regexIndex=0}getMatcher(e){\nif(this.multiRegexes[e])return this.multiRegexes[e];const t=new n\n;return this.rules.slice(e).forEach((([e,n])=>t.addRule(e,n))),\nt.compile(),this.multiRegexes[e]=t,t}resumingScanAtSamePosition(){\nreturn 0!==this.regexIndex}considerAll(){this.regexIndex=0}addRule(e,t){\nthis.rules.push([e,t]),\"begin\"===t.type&&this.count++}exec(e){\nconst t=this.getMatcher(this.regexIndex);t.lastIndex=this.lastIndex\n;let n=t.exec(e)\n;if(this.resumingScanAtSamePosition())if(n&&n.index===this.lastIndex);else{\nconst t=this.getMatcher(0);t.lastIndex=this.lastIndex+1,n=t.exec(e)}\nreturn n&&(this.regexIndex+=n.position+1,\nthis.regexIndex===this.count&&this.considerAll()),n}}\nif(e.compilerExtensions||(e.compilerExtensions=[]),\ne.contains&&e.contains.includes(\"self\"))throw Error(\"ERR: contains `self` is not supported at the top-level of a language.  See documentation.\")\n;return e.classNameAliases=a(e.classNameAliases||{}),function n(i,r){const o=i\n;if(i.isCompiled)return o\n;[D,B,X,z].forEach((e=>e(i,r))),e.compilerExtensions.forEach((e=>e(i,r))),\ni.__beforeBegin=null,[j,C,L].forEach((e=>e(i,r))),i.isCompiled=!0;let l=null\n;return\"object\"==typeof i.keywords&&i.keywords.$pattern&&(i.keywords=Object.assign({},i.keywords),\nl=i.keywords.$pattern,\ndelete i.keywords.$pattern),l=l||/\\w+/,i.keywords&&(i.keywords=U(i.keywords,e.case_insensitive)),\no.keywordPatternRe=t(l,!0),\nr&&(i.begin||(i.begin=/\\B|\\b/),o.beginRe=t(o.begin),i.end||i.endsWithParent||(i.end=/\\B|\\b/),\ni.end&&(o.endRe=t(o.end)),\no.terminatorEnd=d(o.end)||\"\",i.endsWithParent&&r.terminatorEnd&&(o.terminatorEnd+=(i.end?\"|\":\"\")+r.terminatorEnd)),\ni.illegal&&(o.illegalRe=t(i.illegal)),\ni.contains||(i.contains=[]),i.contains=[].concat(...i.contains.map((e=>(e=>(e.variants&&!e.cachedVariants&&(e.cachedVariants=e.variants.map((t=>a(e,{\nvariants:null},t)))),e.cachedVariants?e.cachedVariants:V(e)?a(e,{\nstarts:e.starts?a(e.starts):null\n}):Object.isFrozen(e)?a(e):e))(\"self\"===e?i:e)))),i.contains.forEach((e=>{n(e,o)\n})),i.starts&&n(i.starts,r),o.matcher=(e=>{const t=new s\n;return e.contains.forEach((e=>t.addRule(e.begin,{rule:e,type:\"begin\"\n}))),e.terminatorEnd&&t.addRule(e.terminatorEnd,{type:\"end\"\n}),e.illegal&&t.addRule(e.illegal,{type:\"illegal\"}),t})(o),o}(e)}function V(e){\nreturn!!e&&(e.endsWithParent||V(e.starts))}class Q extends Error{\nconstructor(e,t){super(e),this.name=\"HTMLInjectionError\",this.html=t}}\nconst J=i,Y=a,ee=Symbol(\"nomatch\");var te=(e=>{\nconst t=Object.create(null),i=Object.create(null),a=[];let r=!0\n;const o=\"Could not find the language '{}', did you forget to load/include a language module?\",l={\ndisableAutodetect:!0,name:\"Plain text\",contains:[]};let d={\nignoreUnescapedHTML:!1,throwUnescapedHTML:!1,noHighlightRe:/^(no-?highlight)$/i,\nlanguageDetectRe:/\\blang(?:uage)?-([\\w-]+)\\b/i,classPrefix:\"hljs-\",\ncssSelector:\"pre code\",languages:null,__emitter:c};function f(e){\nreturn d.noHighlightRe.test(e)}function m(e,t,n){let s=\"\",i=\"\"\n;\"object\"==typeof t?(s=e,\nn=t.ignoreIllegals,i=t.language):(F(\"10.7.0\",\"highlight(lang, code, ...args) has been deprecated.\"),\nF(\"10.7.0\",\"Please use highlight(code, options) instead.\\nhttps://github.com/highlightjs/highlight.js/issues/2277\"),\ni=e,s=t),void 0===n&&(n=!0);const a={code:s,language:i};O(\"before:highlight\",a)\n;const r=a.result?a.result:E(a.language,a.code,n)\n;return r.code=a.code,O(\"after:highlight\",r),r}function E(e,n,i,a){\nconst l=Object.create(null);function c(){if(!v.keywords)return void S.addText(R)\n;let e=0;v.keywordPatternRe.lastIndex=0;let t=v.keywordPatternRe.exec(R),n=\"\"\n;for(;t;){n+=R.substring(e,t.index)\n;const i=y.case_insensitive?t[0].toLowerCase():t[0],a=(s=i,v.keywords[s]);if(a){\nconst[e,s]=a\n;if(S.addText(n),n=\"\",l[i]=(l[i]||0)+1,l[i]<=7&&(M+=s),e.startsWith(\"_\"))n+=t[0];else{\nconst n=y.classNameAliases[e]||e;S.addKeyword(t[0],n)}}else n+=t[0]\n;e=v.keywordPatternRe.lastIndex,t=v.keywordPatternRe.exec(R)}var s\n;n+=R.substr(e),S.addText(n)}function u(){null!=v.subLanguage?(()=>{\nif(\"\"===R)return;let e=null;if(\"string\"==typeof v.subLanguage){\nif(!t[v.subLanguage])return void S.addText(R)\n;e=E(v.subLanguage,R,!0,O[v.subLanguage]),O[v.subLanguage]=e._top\n}else e=_(R,v.subLanguage.length?v.subLanguage:null)\n;v.relevance>0&&(M+=e.relevance),S.addSublanguage(e._emitter,e.language)\n})():c(),R=\"\"}function g(e,t){let n=1;for(;void 0!==t[n];){if(!e._emit[n]){n++\n;continue}const s=y.classNameAliases[e[n]]||e[n],i=t[n]\n;s?S.addKeyword(i,s):(R=i,c(),R=\"\"),n++}}function h(e,t){\nreturn e.scope&&\"string\"==typeof e.scope&&S.openNode(y.classNameAliases[e.scope]||e.scope),\ne.beginScope&&(e.beginScope._wrap?(S.addKeyword(R,y.classNameAliases[e.beginScope._wrap]||e.beginScope._wrap),\nR=\"\"):e.beginScope._multi&&(g(e.beginScope,t),R=\"\")),v=Object.create(e,{parent:{\nvalue:v}}),v}function b(e,t,n){let i=((e,t)=>{const n=e&&e.exec(t)\n;return n&&0===n.index})(e.endRe,n);if(i){if(e[\"on:end\"]){const n=new s(e)\n;e[\"on:end\"](t,n),n.isMatchIgnored&&(i=!1)}if(i){\nfor(;e.endsParent&&e.parent;)e=e.parent;return e}}\nif(e.endsWithParent)return b(e.parent,t,n)}function p(e){\nreturn 0===v.matcher.regexIndex?(R+=e[0],1):(T=!0,0)}function f(e){\nconst t=e[0],s=n.substr(e.index),i=b(v,e,s);if(!i)return ee;const a=v\n;v.endScope&&v.endScope._wrap?(u(),\nS.addKeyword(t,v.endScope._wrap)):v.endScope&&v.endScope._multi?(u(),\ng(v.endScope,e)):a.skip?R+=t:(a.returnEnd||a.excludeEnd||(R+=t),\nu(),a.excludeEnd&&(R=t));do{\nv.scope&&S.closeNode(),v.skip||v.subLanguage||(M+=v.relevance),v=v.parent\n}while(v!==i.parent);return i.starts&&h(i.starts,e),a.returnEnd?0:t.length}\nlet m={};function w(t,a){const o=a&&a[0];if(R+=t,null==o)return u(),0\n;if(\"begin\"===m.type&&\"end\"===a.type&&m.index===a.index&&\"\"===o){\nif(R+=n.slice(a.index,a.index+1),!r){const t=Error(`0 width match regex (${e})`)\n;throw t.languageName=e,t.badRule=m.rule,t}return 1}\nif(m=a,\"begin\"===a.type)return(e=>{\nconst t=e[0],n=e.rule,i=new s(n),a=[n.__beforeBegin,n[\"on:begin\"]]\n;for(const n of a)if(n&&(n(e,i),i.isMatchIgnored))return p(t)\n;return n.skip?R+=t:(n.excludeBegin&&(R+=t),\nu(),n.returnBegin||n.excludeBegin||(R=t)),h(n,e),n.returnBegin?0:t.length})(a)\n;if(\"illegal\"===a.type&&!i){\nconst e=Error('Illegal lexeme \"'+o+'\" for mode \"'+(v.scope||\"<unnamed>\")+'\"')\n;throw e.mode=v,e}if(\"end\"===a.type){const e=f(a);if(e!==ee)return e}\nif(\"illegal\"===a.type&&\"\"===o)return 1\n;if(A>1e5&&A>3*a.index)throw Error(\"potential infinite loop, way more iterations than matches\")\n;return R+=o,o.length}const y=x(e)\n;if(!y)throw K(o.replace(\"{}\",e)),Error('Unknown language: \"'+e+'\"')\n;const N=q(y);let k=\"\",v=a||N;const O={},S=new d.__emitter(d);(()=>{const e=[]\n;for(let t=v;t!==y;t=t.parent)t.scope&&e.unshift(t.scope)\n;e.forEach((e=>S.openNode(e)))})();let R=\"\",M=0,I=0,A=0,T=!1;try{\nfor(v.matcher.considerAll();;){\nA++,T?T=!1:v.matcher.considerAll(),v.matcher.lastIndex=I\n;const e=v.matcher.exec(n);if(!e)break;const t=w(n.substring(I,e.index),e)\n;I=e.index+t}return w(n.substr(I)),S.closeAllNodes(),S.finalize(),k=S.toHTML(),{\nlanguage:e,value:k,relevance:M,illegal:!1,_emitter:S,_top:v}}catch(t){\nif(t.message&&t.message.includes(\"Illegal\"))return{language:e,value:J(n),\nillegal:!0,relevance:0,_illegalBy:{message:t.message,index:I,\ncontext:n.slice(I-100,I+100),mode:t.mode,resultSoFar:k},_emitter:S};if(r)return{\nlanguage:e,value:J(n),illegal:!1,relevance:0,errorRaised:t,_emitter:S,_top:v}\n;throw t}}function _(e,n){n=n||d.languages||Object.keys(t);const s=(e=>{\nconst t={value:J(e),illegal:!1,relevance:0,_top:l,_emitter:new d.__emitter(d)}\n;return t._emitter.addText(e),t})(e),i=n.filter(x).filter(v).map((t=>E(t,e,!1)))\n;i.unshift(s);const a=i.sort(((e,t)=>{\nif(e.relevance!==t.relevance)return t.relevance-e.relevance\n;if(e.language&&t.language){if(x(e.language).supersetOf===t.language)return 1\n;if(x(t.language).supersetOf===e.language)return-1}return 0})),[r,o]=a,c=r\n;return c.secondBest=o,c}function w(e){let t=null;const n=(e=>{\nlet t=e.className+\" \";t+=e.parentNode?e.parentNode.className:\"\"\n;const n=d.languageDetectRe.exec(t);if(n){const t=x(n[1])\n;return t||(G(o.replace(\"{}\",n[1])),\nG(\"Falling back to no-highlight mode for this block.\",e)),t?n[1]:\"no-highlight\"}\nreturn t.split(/\\s+/).find((e=>f(e)||x(e)))})(e);if(f(n))return\n;if(O(\"before:highlightElement\",{el:e,language:n\n}),e.children.length>0&&(d.ignoreUnescapedHTML||(console.warn(\"One of your code blocks includes unescaped HTML. This is a potentially serious security risk.\"),\nconsole.warn(\"https://github.com/highlightjs/highlight.js/issues/2886\"),\nconsole.warn(e)),\nd.throwUnescapedHTML))throw new Q(\"One of your code blocks includes unescaped HTML.\",e.innerHTML)\n;t=e;const s=t.textContent,a=n?m(s,{language:n,ignoreIllegals:!0}):_(s)\n;e.innerHTML=a.value,((e,t,n)=>{const s=t&&i[t]||n\n;e.classList.add(\"hljs\"),e.classList.add(\"language-\"+s)\n})(e,n,a.language),e.result={language:a.language,re:a.relevance,\nrelevance:a.relevance},a.secondBest&&(e.secondBest={\nlanguage:a.secondBest.language,relevance:a.secondBest.relevance\n}),O(\"after:highlightElement\",{el:e,result:a,text:s})}let y=!1;function N(){\n\"loading\"!==document.readyState?document.querySelectorAll(d.cssSelector).forEach(w):y=!0\n}function x(e){return e=(e||\"\").toLowerCase(),t[e]||t[i[e]]}\nfunction k(e,{languageName:t}){\"string\"==typeof e&&(e=[e]),e.forEach((e=>{\ni[e.toLowerCase()]=t}))}function v(e){const t=x(e)\n;return t&&!t.disableAutodetect}function O(e,t){const n=e;a.forEach((e=>{\ne[n]&&e[n](t)}))}\n\"undefined\"!=typeof window&&window.addEventListener&&window.addEventListener(\"DOMContentLoaded\",(()=>{\ny&&N()}),!1),Object.assign(e,{highlight:m,highlightAuto:_,highlightAll:N,\nhighlightElement:w,\nhighlightBlock:e=>(F(\"10.7.0\",\"highlightBlock will be removed entirely in v12.0\"),\nF(\"10.7.0\",\"Please use highlightElement now.\"),w(e)),configure:e=>{d=Y(d,e)},\ninitHighlighting:()=>{\nN(),F(\"10.6.0\",\"initHighlighting() deprecated.  Use highlightAll() now.\")},\ninitHighlightingOnLoad:()=>{\nN(),F(\"10.6.0\",\"initHighlightingOnLoad() deprecated.  Use highlightAll() now.\")\n},registerLanguage:(n,s)=>{let i=null;try{i=s(e)}catch(e){\nif(K(\"Language definition for '{}' could not be registered.\".replace(\"{}\",n)),\n!r)throw e;K(e),i=l}\ni.name||(i.name=n),t[n]=i,i.rawDefinition=s.bind(null,e),i.aliases&&k(i.aliases,{\nlanguageName:n})},unregisterLanguage:e=>{delete t[e]\n;for(const t of Object.keys(i))i[t]===e&&delete i[t]},\nlistLanguages:()=>Object.keys(t),getLanguage:x,registerAliases:k,\nautoDetection:v,inherit:Y,addPlugin:e=>{(e=>{\ne[\"before:highlightBlock\"]&&!e[\"before:highlightElement\"]&&(e[\"before:highlightElement\"]=t=>{\ne[\"before:highlightBlock\"](Object.assign({block:t.el},t))\n}),e[\"after:highlightBlock\"]&&!e[\"after:highlightElement\"]&&(e[\"after:highlightElement\"]=t=>{\ne[\"after:highlightBlock\"](Object.assign({block:t.el},t))})})(e),a.push(e)}\n}),e.debugMode=()=>{r=!1},e.safeMode=()=>{r=!0\n},e.versionString=\"11.3.1\",e.regex={concat:b,lookahead:u,either:p,optional:h,\nanyNumberOfTimes:g};for(const e in A)\"object\"==typeof A[e]&&n(A[e])\n;return Object.assign(e,A),e})({}),ne=Object.freeze({__proto__:null,\ngrmr_sway:e=>{const t={className:\"title.function.invoke\",relevance:0,\nbegin:b(/\\b/,/(?!let\\b)/,e.IDENT_RE,u(/\\s*\\(/))},n=\"([u](8|16|32|64))?\";return{\nname:\"Sway\",aliases:[\"sw\"],keywords:{$pattern:e.IDENT_RE+\"!?\",\nkeyword:[\"abi\",\"as\",\"asm\",\"const\",\"contract\",\"deref\",\"enum\",\"fn\",\"if\",\"impl\",\"let\",\"library\",\"match\",\"mut\",\"else\",\"predicate\",\"ref\",\"return\",\"script\",\"Self\",\"self\",\"str\",\"struct\",\"trait\",\"use\",\"where\",\"while\"],\nliteral:[\"true\",\"false\"],\nbuilt_in:[\"bool\",\"char\",\"u8\",\"u16\",\"u32\",\"u64\",\"b256\",\"str\",\"Self\"]},\nillegal:\"</\",contains:[e.C_LINE_COMMENT_MODE,e.COMMENT(\"/\\\\*\",\"\\\\*/\",{\ncontains:[\"self\"]}),e.inherit(e.QUOTE_STRING_MODE,{begin:/b?\"/,illegal:null}),{\nclassName:\"string\",variants:[{begin:/b?r(#*)\"(.|\\n)*?\"\\1(?!#)/},{\nbegin:/b?'\\\\?(x\\w{2}|u\\w{4}|U\\w{8}|.)'/}]},{className:\"symbol\",\nbegin:/'[a-zA-Z_][a-zA-Z0-9_]*/},{className:\"number\",variants:[{\nbegin:\"\\\\b0b([01_]+)\"+n},{begin:\"\\\\b0o([0-7_]+)\"+n},{\nbegin:\"\\\\b0x([A-Fa-f0-9_]+)\"+n},{\nbegin:\"\\\\b(\\\\d[\\\\d_]*(\\\\.[0-9_]+)?([eE][+-]?[0-9_]+)?)\"+n}],relevance:0},{\nbegin:[/fn/,/\\s+/,e.UNDERSCORE_IDENT_RE],className:{1:\"keyword\",\n3:\"title.function\"}},{\nbegin:[/(let|const)/,/\\s+/,/(?:mut\\s+)?/,e.UNDERSCORE_IDENT_RE],className:{\n1:\"keyword\",3:\"keyword\",4:\"variable\"}},{\nbegin:[/type/,/\\s+/,e.UNDERSCORE_IDENT_RE],className:{1:\"keyword\",\n3:\"title.class\"}},{\nbegin:[/(?:trait|enum|struct|impl|for|library|abi)/,/\\s+/,e.UNDERSCORE_IDENT_RE],\nclassName:{1:\"keyword\",3:\"title.class\"}},{begin:e.IDENT_RE+\"::\",keywords:{\nkeyword:\"Self\",built_in:[]}},{className:\"punctuation\",begin:\"->\"},t]}},\ngrmr_rust:e=>{const t=e.regex,n={className:\"title.function.invoke\",relevance:0,\nbegin:t.concat(/\\b/,/(?!let\\b)/,e.IDENT_RE,t.lookahead(/\\s*\\(/))\n},s=\"([ui](8|16|32|64|128|size)|f(32|64))?\",i=[\"drop \",\"Copy\",\"Send\",\"Sized\",\"Sync\",\"Drop\",\"Fn\",\"FnMut\",\"FnOnce\",\"ToOwned\",\"Clone\",\"Debug\",\"PartialEq\",\"PartialOrd\",\"Eq\",\"Ord\",\"AsRef\",\"AsMut\",\"Into\",\"From\",\"Default\",\"Iterator\",\"Extend\",\"IntoIterator\",\"DoubleEndedIterator\",\"ExactSizeIterator\",\"SliceConcatExt\",\"ToString\",\"assert!\",\"assert_eq!\",\"bitflags!\",\"bytes!\",\"cfg!\",\"col!\",\"concat!\",\"concat_idents!\",\"debug_assert!\",\"debug_assert_eq!\",\"env!\",\"panic!\",\"file!\",\"format!\",\"format_args!\",\"include_bin!\",\"include_str!\",\"line!\",\"local_data_key!\",\"module_path!\",\"option_env!\",\"print!\",\"println!\",\"select!\",\"stringify!\",\"try!\",\"unimplemented!\",\"unreachable!\",\"vec!\",\"write!\",\"writeln!\",\"macro_rules!\",\"assert_ne!\",\"debug_assert_ne!\"]\n;return{name:\"Rust\",aliases:[\"rs\"],keywords:{$pattern:e.IDENT_RE+\"!?\",\ntype:[\"i8\",\"i16\",\"i32\",\"i64\",\"i128\",\"isize\",\"u8\",\"u16\",\"u32\",\"u64\",\"u128\",\"usize\",\"f32\",\"f64\",\"str\",\"char\",\"bool\",\"Box\",\"Option\",\"Result\",\"String\",\"Vec\"],\nkeyword:[\"abstract\",\"as\",\"async\",\"await\",\"become\",\"box\",\"break\",\"const\",\"continue\",\"crate\",\"do\",\"dyn\",\"else\",\"enum\",\"extern\",\"false\",\"final\",\"fn\",\"for\",\"if\",\"impl\",\"in\",\"let\",\"loop\",\"macro\",\"match\",\"mod\",\"move\",\"mut\",\"override\",\"priv\",\"pub\",\"ref\",\"return\",\"self\",\"Self\",\"static\",\"struct\",\"super\",\"trait\",\"true\",\"try\",\"type\",\"typeof\",\"unsafe\",\"unsized\",\"use\",\"virtual\",\"where\",\"while\",\"yield\"],\nliteral:[\"true\",\"false\",\"Some\",\"None\",\"Ok\",\"Err\"],built_in:i},illegal:\"</\",\ncontains:[e.C_LINE_COMMENT_MODE,e.COMMENT(\"/\\\\*\",\"\\\\*/\",{contains:[\"self\"]\n}),e.inherit(e.QUOTE_STRING_MODE,{begin:/b?\"/,illegal:null}),{\nclassName:\"string\",variants:[{begin:/b?r(#*)\"(.|\\n)*?\"\\1(?!#)/},{\nbegin:/b?'\\\\?(x\\w{2}|u\\w{4}|U\\w{8}|.)'/}]},{className:\"symbol\",\nbegin:/'[a-zA-Z_][a-zA-Z0-9_]*/},{className:\"number\",variants:[{\nbegin:\"\\\\b0b([01_]+)\"+s},{begin:\"\\\\b0o([0-7_]+)\"+s},{\nbegin:\"\\\\b0x([A-Fa-f0-9_]+)\"+s},{\nbegin:\"\\\\b(\\\\d[\\\\d_]*(\\\\.[0-9_]+)?([eE][+-]?[0-9_]+)?)\"+s}],relevance:0},{\nbegin:[/fn/,/\\s+/,e.UNDERSCORE_IDENT_RE],className:{1:\"keyword\",\n3:\"title.function\"}},{className:\"meta\",begin:\"#!?\\\\[\",end:\"\\\\]\",contains:[{\nclassName:\"string\",begin:/\"/,end:/\"/}]},{\nbegin:[/let/,/\\s+/,/(?:mut\\s+)?/,e.UNDERSCORE_IDENT_RE],className:{1:\"keyword\",\n3:\"keyword\",4:\"variable\"}},{\nbegin:[/for/,/\\s+/,e.UNDERSCORE_IDENT_RE,/\\s+/,/in/],className:{1:\"keyword\",\n3:\"variable\",5:\"keyword\"}},{begin:[/type/,/\\s+/,e.UNDERSCORE_IDENT_RE],\nclassName:{1:\"keyword\",3:\"title.class\"}},{\nbegin:[/(?:trait|enum|struct|union|impl|for)/,/\\s+/,e.UNDERSCORE_IDENT_RE],\nclassName:{1:\"keyword\",3:\"title.class\"}},{begin:e.IDENT_RE+\"::\",keywords:{\nkeyword:\"Self\",built_in:i}},{className:\"punctuation\",begin:\"->\"},n]}},\ngrmr_ini:e=>{const t=e.regex,n={className:\"number\",relevance:0,variants:[{\nbegin:/([+-]+)?[\\d]+_[\\d_]+/},{begin:e.NUMBER_RE}]},s=e.COMMENT();s.variants=[{\nbegin:/;/,end:/$/},{begin:/#/,end:/$/}];const i={className:\"variable\",\nvariants:[{begin:/\\$[\\w\\d\"][\\w\\d_]*/},{begin:/\\$\\{(.*?)\\}/}]},a={\nclassName:\"literal\",begin:/\\bon|off|true|false|yes|no\\b/},r={className:\"string\",\ncontains:[e.BACKSLASH_ESCAPE],variants:[{begin:\"'''\",end:\"'''\",relevance:10},{\nbegin:'\"\"\"',end:'\"\"\"',relevance:10},{begin:'\"',end:'\"'},{begin:\"'\",end:\"'\"}]\n},o={begin:/\\[/,end:/\\]/,contains:[s,a,i,r,n,\"self\"],relevance:0\n},l=t.either(/[A-Za-z0-9_-]+/,/\"(\\\\\"|[^\"])*\"/,/'[^']*'/);return{\nname:\"TOML, also INI\",aliases:[\"toml\"],case_insensitive:!0,illegal:/\\S/,\ncontains:[s,{className:\"section\",begin:/\\[+/,end:/\\]+/},{\nbegin:t.concat(l,\"(\\\\s*\\\\.\\\\s*\",l,\")*\",t.lookahead(/\\s*=\\s*[^#\\s]/)),\nclassName:\"attr\",starts:{end:/$/,contains:[s,o,a,i,r,n]}}]}},grmr_bash:e=>{\nconst t=e.regex,n={},s={begin:/\\$\\{/,end:/\\}/,contains:[\"self\",{begin:/:-/,\ncontains:[n]}]};Object.assign(n,{className:\"variable\",variants:[{\nbegin:t.concat(/\\$[\\w\\d#@][\\w\\d_]*/,\"(?![\\\\w\\\\d])(?![$])\")},s]});const i={\nclassName:\"subst\",begin:/\\$\\(/,end:/\\)/,contains:[e.BACKSLASH_ESCAPE]},a={\nbegin:/<<-?\\s*(?=\\w+)/,starts:{contains:[e.END_SAME_AS_BEGIN({begin:/(\\w+)/,\nend:/(\\w+)/,className:\"string\"})]}},r={className:\"string\",begin:/\"/,end:/\"/,\ncontains:[e.BACKSLASH_ESCAPE,n,i]};i.contains.push(r);const o={begin:/\\$\\(\\(/,\nend:/\\)\\)/,contains:[{begin:/\\d+#[0-9a-f]+/,className:\"number\"},e.NUMBER_MODE,n]\n},l=e.SHEBANG({binary:\"(fish|bash|zsh|sh|csh|ksh|tcsh|dash|scsh)\",relevance:10\n}),c={className:\"function\",begin:/\\w[\\w\\d_]*\\s*\\(\\s*\\)\\s*\\{/,returnBegin:!0,\ncontains:[e.inherit(e.TITLE_MODE,{begin:/\\w[\\w\\d_]*/})],relevance:0};return{\nname:\"Bash\",aliases:[\"sh\"],keywords:{$pattern:/\\b[a-z._-]+\\b/,\nkeyword:[\"if\",\"then\",\"else\",\"elif\",\"fi\",\"for\",\"while\",\"in\",\"do\",\"done\",\"case\",\"esac\",\"function\"],\nliteral:[\"true\",\"false\"],\nbuilt_in:[\"break\",\"cd\",\"continue\",\"eval\",\"exec\",\"exit\",\"export\",\"getopts\",\"hash\",\"pwd\",\"readonly\",\"return\",\"shift\",\"test\",\"times\",\"trap\",\"umask\",\"unset\",\"alias\",\"bind\",\"builtin\",\"caller\",\"command\",\"declare\",\"echo\",\"enable\",\"help\",\"let\",\"local\",\"logout\",\"mapfile\",\"printf\",\"read\",\"readarray\",\"source\",\"type\",\"typeset\",\"ulimit\",\"unalias\",\"set\",\"shopt\",\"autoload\",\"bg\",\"bindkey\",\"bye\",\"cap\",\"chdir\",\"clone\",\"comparguments\",\"compcall\",\"compctl\",\"compdescribe\",\"compfiles\",\"compgroups\",\"compquote\",\"comptags\",\"comptry\",\"compvalues\",\"dirs\",\"disable\",\"disown\",\"echotc\",\"echoti\",\"emulate\",\"fc\",\"fg\",\"float\",\"functions\",\"getcap\",\"getln\",\"history\",\"integer\",\"jobs\",\"kill\",\"limit\",\"log\",\"noglob\",\"popd\",\"print\",\"pushd\",\"pushln\",\"rehash\",\"sched\",\"setcap\",\"setopt\",\"stat\",\"suspend\",\"ttyctl\",\"unfunction\",\"unhash\",\"unlimit\",\"unsetopt\",\"vared\",\"wait\",\"whence\",\"where\",\"which\",\"zcompile\",\"zformat\",\"zftp\",\"zle\",\"zmodload\",\"zparseopts\",\"zprof\",\"zpty\",\"zregexparse\",\"zsocket\",\"zstyle\",\"ztcp\",\"chcon\",\"chgrp\",\"chown\",\"chmod\",\"cp\",\"dd\",\"df\",\"dir\",\"dircolors\",\"ln\",\"ls\",\"mkdir\",\"mkfifo\",\"mknod\",\"mktemp\",\"mv\",\"realpath\",\"rm\",\"rmdir\",\"shred\",\"sync\",\"touch\",\"truncate\",\"vdir\",\"b2sum\",\"base32\",\"base64\",\"cat\",\"cksum\",\"comm\",\"csplit\",\"cut\",\"expand\",\"fmt\",\"fold\",\"head\",\"join\",\"md5sum\",\"nl\",\"numfmt\",\"od\",\"paste\",\"ptx\",\"pr\",\"sha1sum\",\"sha224sum\",\"sha256sum\",\"sha384sum\",\"sha512sum\",\"shuf\",\"sort\",\"split\",\"sum\",\"tac\",\"tail\",\"tr\",\"tsort\",\"unexpand\",\"uniq\",\"wc\",\"arch\",\"basename\",\"chroot\",\"date\",\"dirname\",\"du\",\"echo\",\"env\",\"expr\",\"factor\",\"groups\",\"hostid\",\"id\",\"link\",\"logname\",\"nice\",\"nohup\",\"nproc\",\"pathchk\",\"pinky\",\"printenv\",\"printf\",\"pwd\",\"readlink\",\"runcon\",\"seq\",\"sleep\",\"stat\",\"stdbuf\",\"stty\",\"tee\",\"test\",\"timeout\",\"tty\",\"uname\",\"unlink\",\"uptime\",\"users\",\"who\",\"whoami\",\"yes\"]\n},contains:[l,e.SHEBANG(),c,o,e.HASH_COMMENT_MODE,a,{match:/(\\/[a-z._-]+)+/},r,{\nclassName:\"\",begin:/\\\\\"/},{className:\"string\",begin:/'/,end:/'/},n]}},\ngrmr_shell:e=>({name:\"Shell Session\",aliases:[\"console\",\"shellsession\"],\ncontains:[{className:\"meta\",begin:/^\\s{0,3}[/~\\w\\d[\\]()@-]*[>%$#][ ]?/,starts:{\nend:/[^\\\\](?=\\s*$)/,subLanguage:\"bash\"}}]}),grmr_json:e=>({name:\"JSON\",\ncontains:[{className:\"attr\",begin:/\"(\\\\.|[^\\\\\"\\r\\n])*\"(?=\\s*:)/,relevance:1.01\n},{match:/[{}[\\],:]/,className:\"punctuation\",relevance:0},e.QUOTE_STRING_MODE,{\nbeginKeywords:\"true false null\"\n},e.C_NUMBER_MODE,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE],illegal:\"\\\\S\"})\n});const se=te;for(const e of Object.keys(ne)){\nconst t=e.replace(\"grmr_\",\"\").replace(\"_\",\"-\");se.registerLanguage(t,ne[e])}\nreturn se}()\n;\"object\"==typeof exports&&\"undefined\"!=typeof module&&(module.exports=hljs);"
  },
  {
    "path": "e2e/Cargo.toml",
    "content": "[package]\nname = \"e2e\"\nauthors = { workspace = true }\nedition = { workspace = true }\nhomepage = { workspace = true }\nreadme = { workspace = true }\nlicense = { workspace = true }\nrepository = { workspace = true }\nrust-version = { workspace = true }\nversion = { workspace = true }\npublish = false\n\nbuild = \"build.rs\"\n\n[dev-dependencies]\n# used in test assertions\nchrono = { workspace = true }\nrand = { workspace = true }\nfuel-asm = { workspace = true }\n# TODO: [issue](https://github.com/FuelLabs/fuels-rs/issues/1375) needs to be removed, `ScriptTransaction` and `CreateTransaction` in `fuels` use `fuel_tx::Input` but don't reexport or convert it into a `fuels` owned type\nfuel-tx = { workspace = true }\n# used in test assertions\ntai64 = { workspace = true }\ntempfile = { workspace = true }\n\n[build-dependencies]\nanyhow = { workspace = true, features = [\"std\"] }\nflate2 = { workspace = true, features = [\"zlib\"] }\nfuels-accounts = { workspace = true, features = [\"std\"] }\nreqwest = { workspace = true, features = [\"blocking\", \"default-tls\"] }\nsemver = { workspace = true }\ntar = { workspace = true }\n\n[dependencies]\nanyhow = { workspace = true }\nfuels = { workspace = true, features = [\n  \"accounts-signer-aws-kms\",\n  \"test-helpers\",\n] }\nfutures = { workspace = true }\ntestcontainers = { workspace = true }\ntokio = { workspace = true, features = [\"test-util\"] }\n\n[features]\ndefault = [\"fuels/default\", \"coin-cache\"]\nfuel-core-lib = [\"fuels/fuel-core-lib\"]\nrocksdb = [\"fuels/rocksdb\"]\ncoin-cache = [\"fuels/coin-cache\"]\n"
  },
  {
    "path": "e2e/Forc.toml",
    "content": "[workspace]\nmembers = [\n  'sway/bindings/sharing_types/contract_a',\n  'sway/bindings/sharing_types/contract_b',\n  'sway/bindings/sharing_types/shared_lib',\n  'sway/bindings/simple_contract',\n  'sway/bindings/type_paths',\n  'sway/contracts/asserts',\n  'sway/contracts/auth_testing_abi',\n  'sway/contracts/auth_testing_contract',\n  'sway/contracts/block_timestamp',\n  'sway/contracts/configurables',\n  'sway/contracts/contract_test',\n  'sway/contracts/huge_contract',\n  'sway/contracts/large_return_data',\n  'sway/contracts/lib_contract',\n  'sway/contracts/lib_contract_abi',\n  'sway/contracts/lib_contract_caller',\n  'sway/contracts/library_test',\n  'sway/contracts/liquidity_pool',\n  'sway/contracts/low_level_caller',\n  'sway/contracts/msg_methods',\n  'sway/contracts/multiple_read_calls',\n  'sway/contracts/needs_custom_decoder',\n  'sway/contracts/payable_annotation',\n  'sway/contracts/proxy',\n  'sway/contracts/revert_transaction_error',\n  'sway/contracts/storage',\n  'sway/contracts/token_ops',\n  'sway/contracts/transaction_block_height',\n  'sway/contracts/tx_input_output',\n  'sway/contracts/var_outputs',\n  'sway/logs/contract_logs',\n  'sway/logs/contract_logs_abi',\n  'sway/logs/contract_revert_logs',\n  'sway/logs/contract_with_contract_logs',\n  'sway/logs/script_heap_logs',\n  'sway/logs/script_logs',\n  'sway/logs/script_revert_logs',\n  'sway/logs/script_with_contract_logs',\n  'sway/predicates/basic_predicate',\n  'sway/predicates/predicate_blobs',\n  'sway/predicates/predicate_configurables',\n  'sway/predicates/predicate_witnesses',\n  'sway/predicates/signatures',\n  'sway/predicates/swap',\n  'sway/predicates/predicate_tx_input_output',\n  'sway/scripts/arguments',\n  'sway/scripts/basic_script',\n  'sway/scripts/empty',\n  'sway/scripts/require_from_contract',\n  'sway/scripts/reverting',\n  'sway/scripts/script_array',\n  'sway/scripts/script_asserts',\n  'sway/scripts/script_blobs',\n  'sway/scripts/script_configurables',\n  'sway/scripts/script_enum',\n  'sway/scripts/script_needs_custom_decoder',\n  'sway/scripts/script_proxy',\n  'sway/scripts/script_struct',\n  'sway/scripts/script_tx_input_output',\n  'sway/scripts/transfer_script',\n  'sway/types/contracts/b256',\n  'sway/types/contracts/b512',\n  'sway/types/contracts/bytes',\n  'sway/types/contracts/call_empty_return',\n  'sway/types/contracts/complex_types_contract',\n  'sway/types/contracts/empty_arguments',\n  'sway/types/contracts/enum_as_input',\n  'sway/types/contracts/enum_encoding',\n  'sway/types/contracts/enum_inside_struct',\n  'sway/types/contracts/evm_address',\n  'sway/types/contracts/generics',\n  'sway/types/contracts/heap_type_in_enums',\n  'sway/types/contracts/heap_types',\n  'sway/types/contracts/identity',\n  'sway/types/contracts/native_types',\n  'sway/types/contracts/nested_structs',\n  'sway/types/contracts/options',\n  'sway/types/contracts/raw_slice',\n  'sway/types/contracts/results',\n  'sway/types/contracts/std_lib_string',\n  'sway/types/contracts/str_in_array',\n  'sway/types/contracts/string_slice',\n  'sway/types/contracts/tuples',\n  'sway/types/contracts/two_structs',\n  'sway/types/contracts/type_inside_enum',\n  'sway/types/contracts/u128',\n  'sway/types/contracts/u256',\n  'sway/types/contracts/vector_output',\n  'sway/types/contracts/vectors',\n  'sway/types/predicates/address',\n  'sway/types/predicates/enums',\n  'sway/types/predicates/predicate_b256',\n  'sway/types/predicates/predicate_bytes',\n  'sway/types/predicates/predicate_bytes_hash',\n  'sway/types/predicates/predicate_generics',\n  'sway/types/predicates/predicate_raw_slice',\n  'sway/types/predicates/predicate_std_lib_string',\n  'sway/types/predicates/predicate_string_slice',\n  'sway/types/predicates/predicate_tuples',\n  'sway/types/predicates/predicate_u128',\n  'sway/types/predicates/predicate_u256',\n  'sway/types/predicates/predicate_vector',\n  'sway/types/predicates/predicate_vectors',\n  'sway/types/predicates/structs',\n  'sway/types/predicates/u64',\n  'sway/types/scripts/options_results',\n  'sway/types/scripts/script_b256',\n  'sway/types/scripts/script_bytes',\n  'sway/types/scripts/script_generics',\n  'sway/types/scripts/script_heap_types',\n  'sway/types/scripts/script_raw_slice',\n  'sway/types/scripts/script_std_lib_string',\n  'sway/types/scripts/script_string_slice',\n  'sway/types/scripts/script_tuples',\n  'sway/types/scripts/script_u128',\n  'sway/types/scripts/script_u256',\n  'sway/types/scripts/script_vectors',\n]\n\n[patch.'https://github.com/fuellabs/sway']\nstd = { git = \"https://github.com/fuellabs/sway\" }\n"
  },
  {
    "path": "e2e/build.rs",
    "content": "use std::{\n    io::Cursor,\n    path::{Path, PathBuf},\n};\n\nuse flate2::read::GzDecoder;\nuse fuels_accounts::provider::SUPPORTED_FUEL_CORE_VERSION;\nuse tar::Archive;\n\nstruct Downloader {\n    dir: PathBuf,\n}\n\nimpl Downloader {\n    const EXECUTOR_FILE_NAME: &'static str = \"fuel-core-wasm-executor.wasm\";\n\n    pub fn new() -> Self {\n        let env = std::env::var(\"OUT_DIR\").unwrap();\n        let out_dir = Path::new(&env);\n        Self {\n            dir: out_dir.to_path_buf(),\n        }\n    }\n\n    pub fn should_download(&self) -> anyhow::Result<bool> {\n        if !self.executor_path().exists() {\n            return Ok(true);\n        }\n\n        if !self.version_path().exists() {\n            return Ok(true);\n        }\n\n        let saved_version = semver::Version::parse(&std::fs::read_to_string(self.version_path())?)?;\n        if saved_version != SUPPORTED_FUEL_CORE_VERSION {\n            return Ok(true);\n        }\n\n        Ok(false)\n    }\n\n    pub fn download(&self) -> anyhow::Result<()> {\n        std::fs::create_dir_all(&self.dir)?;\n\n        const LINK_TEMPLATE: &str = \"https://github.com/FuelLabs/fuel-core/releases/download/vVERSION/fuel-core-VERSION-x86_64-unknown-linux-gnu.tar.gz\";\n        let link = LINK_TEMPLATE.replace(\"VERSION\", &SUPPORTED_FUEL_CORE_VERSION.to_string());\n\n        let response = reqwest::blocking::Client::builder()\n            .timeout(std::time::Duration::from_secs(60))\n            .build()?\n            .get(link)\n            .send()?;\n\n        if !response.status().is_success() {\n            anyhow::bail!(\"Failed to download wasm executor: {}\", response.status());\n        }\n\n        let mut content = Cursor::new(response.bytes()?);\n\n        let mut archive = Archive::new(GzDecoder::new(&mut content));\n\n        let mut extracted = false;\n        let executor_in_tar = Path::new(&format!(\n            \"fuel-core-{SUPPORTED_FUEL_CORE_VERSION}-x86_64-unknown-linux-gnu\"\n        ))\n        .join(Self::EXECUTOR_FILE_NAME);\n\n        for entry in archive.entries()? {\n            let mut entry = entry?;\n\n            if entry.path()? == executor_in_tar {\n                entry.unpack(self.executor_path())?;\n                std::fs::write(\n                    self.version_path(),\n                    format!(\"{SUPPORTED_FUEL_CORE_VERSION}\"),\n                )?;\n\n                extracted = true;\n                break;\n            }\n        }\n        if !extracted {\n            anyhow::bail!(\"Failed to extract wasm executor from the archive\");\n        }\n\n        Ok(())\n    }\n\n    fn make_cargo_watch_downloaded_files(&self) {\n        let executor_path = self.executor_path();\n        println!(\"cargo:rerun-if-changed={}\", executor_path.display());\n\n        let version_path = self.version_path();\n        println!(\"cargo:rerun-if-changed={}\", version_path.display());\n    }\n\n    fn executor_path(&self) -> PathBuf {\n        self.dir.join(Self::EXECUTOR_FILE_NAME)\n    }\n\n    fn version_path(&self) -> PathBuf {\n        self.dir.join(\"version.rs\")\n    }\n}\n\nfn main() {\n    println!(\"cargo:rerun-if-changed=build.rs\");\n\n    let downloader = Downloader::new();\n    downloader.make_cargo_watch_downloaded_files();\n\n    if downloader.should_download().unwrap() {\n        downloader.download().unwrap();\n    }\n}\n"
  },
  {
    "path": "e2e/src/aws_kms.rs",
    "content": "use fuels::{\n    accounts::signers::kms::aws::{\n        AwsKmsSigner,\n        aws_config::{BehaviorVersion, Region, defaults},\n        aws_sdk_kms::{\n            Client,\n            config::Credentials,\n            types::{KeySpec, KeyUsageType},\n        },\n    },\n    prelude::Error,\n    types::errors::{Context, Result},\n};\nuse testcontainers::{core::ContainerPort, runners::AsyncRunner};\nuse tokio::io::AsyncBufReadExt;\n\n#[derive(Default)]\npub struct AwsKms {\n    show_logs: bool,\n}\n\nstruct AwsKmsImage;\n\nimpl testcontainers::Image for AwsKmsImage {\n    fn name(&self) -> &str {\n        \"localstack/localstack\"\n    }\n\n    fn tag(&self) -> &str {\n        \"latest\"\n    }\n\n    fn ready_conditions(&self) -> Vec<testcontainers::core::WaitFor> {\n        vec![testcontainers::core::WaitFor::message_on_stdout(\"Ready.\")]\n    }\n\n    fn expose_ports(&self) -> &[ContainerPort] {\n        &[ContainerPort::Tcp(4566)]\n    }\n}\n\nimpl AwsKms {\n    pub fn with_show_logs(mut self, show_logs: bool) -> Self {\n        self.show_logs = show_logs;\n        self\n    }\n\n    pub async fn start(self) -> Result<AwsKmsProcess> {\n        let container = AwsKmsImage\n            .start()\n            .await\n            .map_err(|e| Error::Other(e.to_string()))\n            .with_context(|| \"Failed to start KMS container\")?;\n\n        if self.show_logs {\n            spawn_log_printer(&container);\n        }\n\n        let port = container\n            .get_host_port_ipv4(4566)\n            .await\n            .map_err(|e| Error::Other(e.to_string()))?;\n        let url = format!(\"http://localhost:{}\", port);\n\n        let credentials = Credentials::new(\"test\", \"test\", None, None, \"Static Test Credentials\");\n        let region = Region::new(\"us-east-1\");\n\n        let config = defaults(BehaviorVersion::latest())\n            .credentials_provider(credentials)\n            .endpoint_url(url.clone())\n            .region(region)\n            .load()\n            .await;\n\n        let client = Client::new(&config);\n\n        Ok(AwsKmsProcess {\n            _container: container,\n            client,\n            url,\n        })\n    }\n}\n\nfn spawn_log_printer(container: &testcontainers::ContainerAsync<AwsKmsImage>) {\n    let stderr = container.stderr(true);\n    let stdout = container.stdout(true);\n    tokio::spawn(async move {\n        let mut stderr_lines = stderr.lines();\n        let mut stdout_lines = stdout.lines();\n\n        let mut other_stream_closed = false;\n        loop {\n            tokio::select! {\n                stderr_result = stderr_lines.next_line() => {\n                    match stderr_result {\n                        Ok(Some(line)) => eprintln!(\"KMS (stderr): {}\", line),\n                        Ok(None) if other_stream_closed => break,\n                        Ok(None) => other_stream_closed = true,\n                        Err(e) => {\n                            eprintln!(\"KMS: Error reading from stderr: {:?}\", e);\n                            break;\n                        }\n                    }\n                }\n                stdout_result = stdout_lines.next_line() => {\n                    match stdout_result {\n                        Ok(Some(line)) => eprintln!(\"KMS (stdout): {}\", line),\n                        Ok(None) if other_stream_closed => break,\n                        Ok(None) => other_stream_closed = true,\n                        Err(e) => {\n                            eprintln!(\"KMS: Error reading from stdout: {:?}\", e);\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n\n        Ok::<(), std::io::Error>(())\n    });\n}\n\npub struct AwsKmsProcess {\n    _container: testcontainers::ContainerAsync<AwsKmsImage>,\n    client: Client,\n    url: String,\n}\n\nimpl AwsKmsProcess {\n    pub async fn create_signer(&self) -> anyhow::Result<AwsKmsSigner> {\n        let response = self\n            .client\n            .create_key()\n            .key_usage(KeyUsageType::SignVerify)\n            .key_spec(KeySpec::EccSecgP256K1)\n            .send()\n            .await?;\n\n        let id = response\n            .key_metadata\n            .and_then(|metadata| metadata.arn)\n            .ok_or_else(|| anyhow::anyhow!(\"key arn missing from response\"))?;\n\n        let kms_signer = AwsKmsSigner::new(id.clone(), &self.client).await?;\n\n        Ok(kms_signer)\n    }\n\n    pub fn client(&self) -> &Client {\n        &self.client\n    }\n\n    pub fn url(&self) -> &str {\n        &self.url\n    }\n}\n"
  },
  {
    "path": "e2e/src/e2e_helpers.rs",
    "content": "use fuels::types::errors::Result;\n\nuse crate::aws_kms::{AwsKms, AwsKmsProcess};\n\npub async fn start_aws_kms(logs: bool) -> Result<AwsKmsProcess> {\n    AwsKms::default().with_show_logs(logs).start().await\n}\n"
  },
  {
    "path": "e2e/src/lib.rs",
    "content": "mod aws_kms;\npub mod e2e_helpers;\n"
  },
  {
    "path": "e2e/sway/abi/simple_contract/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"simple_contract\"\n"
  },
  {
    "path": "e2e/sway/abi/simple_contract/src/main.sw",
    "content": "contract;\n\nabi SimpleContract {\n    fn takes_u32_returns_bool(arg: u32) -> bool;\n}\n\nimpl SimpleContract for Contract {\n    fn takes_u32_returns_bool(_arg: u32) -> bool {\n        true\n    }\n}\n"
  },
  {
    "path": "e2e/sway/abi/wasm_contract/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"wasm_contract\"\n"
  },
  {
    "path": "e2e/sway/abi/wasm_contract/src/main.sw",
    "content": "contract;\n\nenum SomeEnum<T> {\n    V1: (),\n    V2: T,\n}\n\n#[allow(dead_code)]\nstruct SomeStruct {\n    a: u32,\n    b: bool,\n}\n\nabi TestContract {\n    fn test_function(arg: SomeEnum<SomeStruct>);\n}\n\nimpl TestContract for Contract {\n    fn test_function(_arg: SomeEnum<SomeStruct>) {}\n}\n"
  },
  {
    "path": "e2e/sway/abi/wasm_predicate/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"wasm_predicate\"\n"
  },
  {
    "path": "e2e/sway/abi/wasm_predicate/src/main.sw",
    "content": "predicate;\n\nconfigurable {\n    U64: u64 = 128,\n}\n\nfn main(val: u64) -> bool {\n    val == U64\n}\n"
  },
  {
    "path": "e2e/sway/bindings/sharing_types/contract_a/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"contract_a\"\n\n[dependencies]\nshared_lib = { path = \"../shared_lib\" }\n"
  },
  {
    "path": "e2e/sway/bindings/sharing_types/contract_a/src/main.sw",
    "content": "contract;\nuse shared_lib::*;\n\nstruct UniqueStructToContractA<T> {\n    a: T,\n}\n\nstruct StructSameNameButDifferentInternals {\n    a: u32,\n}\n\n#[allow(dead_code)]\nenum EnumSameNameButDifferentInternals {\n    a: u32,\n}\n\nabi MyContract {\n    fn uses_shared_type(\n        arg1: SharedStruct2<u32>,\n        arg2: SharedEnum<u64>,\n    ) -> (SharedStruct2<u32>, SharedEnum<u64>);\n    fn uses_types_that_share_only_names(\n        arg1: StructSameNameButDifferentInternals,\n        arg2: EnumSameNameButDifferentInternals,\n    ) -> (StructSameNameButDifferentInternals, EnumSameNameButDifferentInternals);\n    fn uses_shared_type_inside_owned_one(\n        arg1: UniqueStructToContractA<SharedStruct2<u8>>,\n    ) -> UniqueStructToContractA<SharedStruct2<u8>>;\n}\n\nimpl MyContract for Contract {\n    fn uses_shared_type(\n        arg1: SharedStruct2<u32>,\n        arg2: SharedEnum<u64>,\n    ) -> (SharedStruct2<u32>, SharedEnum<u64>) {\n        (arg1, arg2)\n    }\n    fn uses_types_that_share_only_names(\n        arg1: StructSameNameButDifferentInternals,\n        arg2: EnumSameNameButDifferentInternals,\n    ) -> (StructSameNameButDifferentInternals, EnumSameNameButDifferentInternals) {\n        (arg1, arg2)\n    }\n    fn uses_shared_type_inside_owned_one(\n        arg1: UniqueStructToContractA<SharedStruct2<u8>>,\n    ) -> UniqueStructToContractA<SharedStruct2<u8>> {\n        arg1\n    }\n}\n"
  },
  {
    "path": "e2e/sway/bindings/sharing_types/contract_b/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"contract_b\"\n\n[dependencies]\nshared_lib = { path = \"../shared_lib\" }\n"
  },
  {
    "path": "e2e/sway/bindings/sharing_types/contract_b/src/main.sw",
    "content": "contract;\nuse shared_lib::*;\n\nstruct UniqueStructToContractB<T> {\n    a: T,\n}\n\nstruct StructSameNameButDifferentInternals {\n    a: [u64; 1],\n}\n\n#[allow(dead_code)]\nenum EnumSameNameButDifferentInternals {\n    a: [u64; 1],\n}\n\nabi MyContract {\n    fn uses_shared_type(\n        arg1: SharedStruct2<u32>,\n        arg2: SharedEnum<u64>,\n    ) -> (SharedStruct2<u32>, SharedEnum<u64>);\n    fn uses_types_that_share_only_names(\n        arg1: StructSameNameButDifferentInternals,\n        arg2: EnumSameNameButDifferentInternals,\n    ) -> (StructSameNameButDifferentInternals, EnumSameNameButDifferentInternals);\n    fn uses_shared_type_inside_owned_one(\n        arg1: UniqueStructToContractB<SharedStruct2<u8>>,\n    ) -> UniqueStructToContractB<SharedStruct2<u8>>;\n}\n\nimpl MyContract for Contract {\n    fn uses_shared_type(\n        arg1: SharedStruct2<u32>,\n        arg2: SharedEnum<u64>,\n    ) -> (SharedStruct2<u32>, SharedEnum<u64>) {\n        (arg1, arg2)\n    }\n    fn uses_types_that_share_only_names(\n        arg1: StructSameNameButDifferentInternals,\n        arg2: EnumSameNameButDifferentInternals,\n    ) -> (StructSameNameButDifferentInternals, EnumSameNameButDifferentInternals) {\n        (arg1, arg2)\n    }\n    fn uses_shared_type_inside_owned_one(\n        arg1: UniqueStructToContractB<SharedStruct2<u8>>,\n    ) -> UniqueStructToContractB<SharedStruct2<u8>> {\n        arg1\n    }\n}\n"
  },
  {
    "path": "e2e/sway/bindings/sharing_types/shared_lib/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"lib.sw\"\nlicense = \"Apache-2.0\"\nname = \"shared_lib\"\n"
  },
  {
    "path": "e2e/sway/bindings/sharing_types/shared_lib/src/lib.sw",
    "content": "library;\n\npub struct SharedStruct1<T> {\n    a: T,\n}\n\npub struct SharedStruct2<K> {\n    a: u32,\n    b: SharedStruct1<K>,\n}\n\n#[allow(dead_code)]\npub enum SharedEnum<L> {\n    a: u64,\n    b: SharedStruct2<L>,\n}\n"
  },
  {
    "path": "e2e/sway/bindings/simple_contract/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"simple_contract\"\n"
  },
  {
    "path": "e2e/sway/bindings/simple_contract/src/main.sw",
    "content": "contract;\n\nabi MyContract {\n    fn takes_int_returns_bool(arg: u32) -> bool;\n}\n\nimpl MyContract for Contract {\n    fn takes_int_returns_bool(arg: u32) -> bool {\n        arg == 32u32\n    }\n}\n"
  },
  {
    "path": "e2e/sway/bindings/type_paths/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"type_paths\"\n"
  },
  {
    "path": "e2e/sway/bindings/type_paths/src/another_lib.sw",
    "content": "library;\n\npub struct VeryCommonNameStruct {\n    pub field_a: u32,\n}\n"
  },
  {
    "path": "e2e/sway/bindings/type_paths/src/contract_a_types.sw",
    "content": "library;\n\npub struct VeryCommonNameStruct {\n    another_field: u32,\n}\n\npub struct AWrapper {\n    field: VeryCommonNameStruct,\n}\n"
  },
  {
    "path": "e2e/sway/bindings/type_paths/src/main.sw",
    "content": "contract;\n\nmod contract_a_types;\nmod another_lib;\n\nuse contract_a_types::AWrapper;\nuse another_lib::VeryCommonNameStruct;\n\nabi MyContract {\n    fn test_function(arg: AWrapper) -> VeryCommonNameStruct;\n}\n\nimpl MyContract for Contract {\n    fn test_function(_arg: AWrapper) -> VeryCommonNameStruct {\n        VeryCommonNameStruct { field_a: 10u32 }\n    }\n}\n"
  },
  {
    "path": "e2e/sway/contracts/asserts/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"asserts\"\n"
  },
  {
    "path": "e2e/sway/contracts/asserts/src/main.sw",
    "content": "contract;\n\nstruct TestStruct {\n    field_1: bool,\n    field_2: u64,\n}\n\n#[allow(dead_code)]\nenum TestEnum {\n    VariantOne: (),\n    VariantTwo: (),\n}\n\nimpl PartialEq for TestStruct {\n    fn eq(self, other: Self) -> bool {\n        self.field_1 == other.field_1 && self.field_2 == other.field_2\n    }\n}\nimpl Eq for TestStruct {}\n\nimpl PartialEq for TestEnum {\n    fn eq(self, other: Self) -> bool {\n        match (self, other) {\n            (TestEnum::VariantOne, TestEnum::VariantOne) => true,\n            (TestEnum::VariantTwo, TestEnum::VariantTwo) => true,\n            _ => false,\n        }\n    }\n}\nimpl Eq for TestEnum {}\n\nabi TestContract {\n    fn assert_primitive(a: u64, b: u64);\n\n    fn assert_eq_primitive(a: u64, b: u64);\n    fn assert_eq_struct(test_struct: TestStruct, test_struct2: TestStruct);\n    fn assert_eq_enum(test_enum: TestEnum, test_enum2: TestEnum);\n\n    fn assert_ne_primitive(a: u64, b: u64);\n    fn assert_ne_struct(test_struct: TestStruct, test_struct2: TestStruct);\n    fn assert_ne_enum(test_enum: TestEnum, test_enum2: TestEnum);\n}\n\nimpl TestContract for Contract {\n    fn assert_primitive(a: u64, b: u64) {\n        assert(a == b);\n    }\n\n    fn assert_eq_primitive(a: u64, b: u64) {\n        assert_eq(a, b);\n    }\n    fn assert_eq_struct(test_struct: TestStruct, test_struct2: TestStruct) {\n        assert_eq(test_struct, test_struct2);\n    }\n    fn assert_eq_enum(test_enum: TestEnum, test_enum2: TestEnum) {\n        assert_eq(test_enum, test_enum2);\n    }\n\n    fn assert_ne_primitive(a: u64, b: u64) {\n        assert_ne(a, b);\n    }\n    fn assert_ne_struct(test_struct: TestStruct, test_struct2: TestStruct) {\n        assert_ne(test_struct, test_struct2);\n    }\n    fn assert_ne_enum(test_enum: TestEnum, test_enum2: TestEnum) {\n        assert_ne(test_enum, test_enum2);\n    }\n}\n"
  },
  {
    "path": "e2e/sway/contracts/auth_testing_abi/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"auth_testing_abi\"\n"
  },
  {
    "path": "e2e/sway/contracts/auth_testing_abi/src/main.sw",
    "content": "library;\n\nabi AuthTesting {\n    fn is_caller_external() -> bool;\n    fn check_msg_sender(expected_id: Address) -> bool;\n}\n"
  },
  {
    "path": "e2e/sway/contracts/auth_testing_contract/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"auth_testing_contract\"\n\n[dependencies]\nauth_testing_abi = { path = \"../auth_testing_abi\" }\n"
  },
  {
    "path": "e2e/sway/contracts/auth_testing_contract/src/main.sw",
    "content": "contract;\n\nuse std::auth::{AuthError, caller_is_external, msg_sender};\nuse auth_testing_abi::*;\n\nimpl AuthTesting for Contract {\n    fn is_caller_external() -> bool {\n        caller_is_external()\n    }\n\n    fn check_msg_sender(expected_id: Address) -> bool {\n        let result: Result<Identity, AuthError> = msg_sender();\n        let mut ret = false;\n        if result.is_err() {\n            ret = false;\n        } else {\n            let unwrapped = result.unwrap();\n            if let Identity::Address(v) = unwrapped {\n                assert(v == expected_id);\n                ret = true;\n            } else {\n                ret = false;\n            }\n        };\n\n        ret\n    }\n}\n"
  },
  {
    "path": "e2e/sway/contracts/block_timestamp/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"block_timestamp\"\n"
  },
  {
    "path": "e2e/sway/contracts/block_timestamp/src/main.sw",
    "content": "contract;\n\nuse std::block::timestamp;\n\nabi MyContract {\n    fn return_timestamp() -> u64;\n}\n\nimpl MyContract for Contract {\n    fn return_timestamp() -> u64 {\n        timestamp()\n    }\n}\n"
  },
  {
    "path": "e2e/sway/contracts/configurables/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"configurables\"\n"
  },
  {
    "path": "e2e/sway/contracts/configurables/src/main.sw",
    "content": "contract;\n\n#[allow(dead_code)]\nenum EnumWithGeneric<D> {\n    VariantOne: D,\n    VariantTwo: (),\n}\n\nstruct StructWithGeneric<D> {\n    field_1: D,\n    field_2: u64,\n}\n\nconfigurable {\n    BOOL: bool = true,\n    U8: u8 = 8,\n    U16: u16 = 16,\n    U32: u32 = 32,\n    U64: u64 = 63,\n    U256: u256 = 0x0000000000000000000000000000000000000000000000000000000000000008u256,\n    B256: b256 = 0x0101010101010101010101010101010101010101010101010101010101010101,\n    STR_4: str[4] = __to_str_array(\"fuel\"),\n    TUPLE: (u8, bool) = (8, true),\n    ARRAY: [u32; 3] = [253, 254, 255],\n    STRUCT: StructWithGeneric<u8> = StructWithGeneric {\n        field_1: 8,\n        field_2: 16,\n    },\n    ENUM: EnumWithGeneric<bool> = EnumWithGeneric::VariantOne(true),\n}\n//U128: u128 = 128, //TODO: add once https://github.com/FuelLabs/sway/issues/5356 is done\n\nabi TestContract {\n    fn return_configurables() -> (bool, u8, u16, u32, u64, u256, b256, str[4], (u8, bool), [u32; 3], StructWithGeneric<u8>, EnumWithGeneric<bool>);\n}\n\nimpl TestContract for Contract {\n    fn return_configurables() -> (bool, u8, u16, u32, u64, u256, b256, str[4], (u8, bool), [u32; 3], StructWithGeneric<u8>, EnumWithGeneric<bool>) {\n        (BOOL, U8, U16, U32, U64, U256, B256, STR_4, TUPLE, ARRAY, STRUCT, ENUM)\n    }\n}\n"
  },
  {
    "path": "e2e/sway/contracts/contract_test/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"contract_test\"\n\n[dependencies]\nincrement_abi = { path = \"../library_test\", package = \"library_test\" }\n"
  },
  {
    "path": "e2e/sway/contracts/contract_test/src/main.sw",
    "content": "contract;\n\nuse std::storage::storage_api::{read, write};\nuse std::context::msg_amount;\n\nstruct MyType {\n    x: u64,\n    y: u64,\n}\n\n#[allow(dead_code)]\nstruct Person {\n    name: str[4],\n}\n\n#[allow(dead_code)]\nenum State {\n    A: (),\n    B: (),\n    C: (),\n}\n\nabi TestContract {\n    #[storage(write)]\n    fn initialize_counter(value: u64) -> u64;\n    #[storage(read, write)]\n    fn increment_counter(amount: u64) -> u64;\n    #[storage(read)]\n    fn read_counter() -> u64;\n    // ANCHOR: low_level_call\n    #[storage(write)]\n    fn set_value_multiple_complex(a: MyStruct, b: str[4]);\n    // ANCHOR_END: low_level_call\n    #[storage(read)]\n    fn get_str_value() -> str[4];\n    #[storage(read)]\n    fn get_bool_value() -> bool;\n    fn get(x: u64, y: u64) -> u64;\n    fn get_alt(x: MyType) -> MyType;\n    fn get_single(x: u64) -> u64;\n    fn array_of_structs(p: [Person; 2]) -> [Person; 2];\n    fn array_of_enums(p: [State; 2]) -> [State; 2];\n    fn get_array(p: [u64; 2]) -> [u64; 2];\n    #[payable]\n    fn get_msg_amount() -> u64;\n    fn new() -> u64;\n}\n\nstorage {\n    counter: u64 = 0,\n    value_str: str[4] = __to_str_array(\"none\"),\n    value_bool: bool = false,\n}\n\npub struct MyStruct {\n    a: bool,\n    b: [u64; 3],\n}\n\nimpl TestContract for Contract {\n    // ANCHOR: msg_amount\n    #[payable]\n    fn get_msg_amount() -> u64 {\n        msg_amount()\n    }\n    // ANCHOR_END: msg_amount\n    #[storage(write)]\n    fn initialize_counter(value: u64) -> u64 {\n        storage.counter.write(value);\n\n        value\n    }\n\n    /// This method will read the counter from storage, increment it\n    /// and write the incremented value to storage\n    #[storage(read, write)]\n    fn increment_counter(amount: u64) -> u64 {\n        let incremented = storage.counter.read() + amount;\n        storage.counter.write(incremented);\n\n        incremented\n    }\n\n    #[storage(read)]\n    fn read_counter() -> u64 {\n        storage.counter.read()\n    }\n\n    #[storage(write)]\n    fn set_value_multiple_complex(a: MyStruct, b: str[4]) {\n        storage.counter.write(a.b[1]);\n        storage.value_str.write(b);\n        storage.value_bool.write(a.a);\n    }\n\n    #[storage(read)]\n    fn get_str_value() -> str[4] {\n        storage.value_str.read()\n    }\n\n    #[storage(read)]\n    fn get_bool_value() -> bool {\n        storage.value_bool.read()\n    }\n\n    fn get(x: u64, y: u64) -> u64 {\n        x + y\n    }\n\n    fn get_alt(t: MyType) -> MyType {\n        t\n    }\n\n    fn get_single(x: u64) -> u64 {\n        x\n    }\n\n    fn array_of_structs(p: [Person; 2]) -> [Person; 2] {\n        p\n    }\n\n    fn array_of_enums(p: [State; 2]) -> [State; 2] {\n        p\n    }\n\n    fn get_array(p: [u64; 2]) -> [u64; 2] {\n        p\n    }\n\n    fn new() -> u64 {\n        12345u64\n    }\n}\n"
  },
  {
    "path": "e2e/sway/contracts/huge_contract/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"huge_contract\"\n\n[dependencies]\n"
  },
  {
    "path": "e2e/sway/contracts/huge_contract/src/main.sw",
    "content": "contract;\n\nabi MyContract {\n    fn something() -> u64;\n    #[storage(write)]\n    fn write_some_u64(some: u64);\n    #[storage(read)]\n    fn read_some_u64() -> u64;\n}\n\nstorage {\n    some_u64: u64 = 42,\n}\n\nimpl MyContract for Contract {\n    fn something() -> u64 {\n        asm() {\n            blob i450000;\n        }\n        1001\n    }\n\n    #[storage(write)]\n    fn write_some_u64(some: u64) {\n        storage.some_u64.write(some);\n    }\n\n    #[storage(read)]\n    fn read_some_u64() -> u64 {\n        storage.some_u64.read()\n    }\n}\n"
  },
  {
    "path": "e2e/sway/contracts/large_return_data/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"large_return_data\"\n"
  },
  {
    "path": "e2e/sway/contracts/large_return_data/src/main.sw",
    "content": "contract;\n\npub struct SmallStruct {\n    foo: u32,\n}\n\npub struct LargeStruct {\n    foo: u8,\n    bar: u8,\n}\n\nabi TestContract {\n    fn get_id() -> b256;\n    fn get_small_string() -> str[8];\n    fn get_large_string() -> str[9];\n    fn get_large_struct() -> LargeStruct;\n    fn get_small_struct() -> SmallStruct;\n    fn get_large_array() -> [u32; 2];\n    fn get_contract_id() -> ContractId;\n}\n\nimpl TestContract for Contract {\n    fn get_id() -> b256 {\n        0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\n    }\n\n    fn get_small_string() -> str[8] {\n        let my_string: str[8] = __to_str_array(\"gggggggg\");\n        my_string\n    }\n\n    fn get_large_string() -> str[9] {\n        let my_string: str[9] = __to_str_array(\"ggggggggg\");\n        my_string\n    }\n\n    fn get_small_struct() -> SmallStruct {\n        SmallStruct { foo: 100u32 }\n    }\n\n    fn get_large_struct() -> LargeStruct {\n        LargeStruct {\n            foo: 12u8,\n            bar: 42u8,\n        }\n    }\n\n    fn get_large_array() -> [u32; 2] {\n        let x: [u32; 2] = [1u32, 2u32];\n        x\n    }\n\n    fn get_contract_id() -> ContractId {\n        let id = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n        ContractId::from(id)\n    }\n}\n"
  },
  {
    "path": "e2e/sway/contracts/lib_contract/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"lib_contract\"\n\n[dependencies]\nlib_contract_abi = { path = \"../lib_contract_abi/\", package = \"lib_contract_abi\" }\n"
  },
  {
    "path": "e2e/sway/contracts/lib_contract/src/main.sw",
    "content": "contract;\n\nuse lib_contract_abi::LibContract;\n\nimpl LibContract for Contract {\n    fn increment(value: u64) -> u64 {\n        value + 1\n    }\n\n    fn require() -> () {\n        require(false, __to_str_array(\"require from contract\"));\n    }\n}\n"
  },
  {
    "path": "e2e/sway/contracts/lib_contract_abi/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"lib_contract_abi\"\n"
  },
  {
    "path": "e2e/sway/contracts/lib_contract_abi/src/main.sw",
    "content": "library;\n\nabi LibContract {\n    fn increment(value: u64) -> u64;\n    fn require();\n}\n"
  },
  {
    "path": "e2e/sway/contracts/lib_contract_caller/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"lib_contract_caller\"\n\n[dependencies]\nlib_contract = { path = \"../lib_contract_abi/\", package = \"lib_contract_abi\" }\n"
  },
  {
    "path": "e2e/sway/contracts/lib_contract_caller/src/main.sw",
    "content": "contract;\n\nuse lib_contract::LibContract;\nuse std::asset::mint_to;\n\nabi ContractCaller {\n    fn increment_from_contract(contract_id: ContractId, value: u64) -> u64;\n    fn increment_from_contracts(\n        contract_id: ContractId,\n        contract_id2: ContractId,\n        value: u64,\n    ) -> u64;\n    fn mint_then_increment_from_contract(contract_id: ContractId, amount: u64, address: Identity);\n    fn require_from_contract(contract_id: ContractId);\n    fn re_entrant(contract_id: ContractId, re_enter: bool) -> u64;\n}\n\nimpl ContractCaller for Contract {\n    fn increment_from_contract(contract_id: ContractId, value: u64) -> u64 {\n        let contract_instance = abi(LibContract, contract_id.into());\n\n        contract_instance.increment(value)\n    }\n\n    fn increment_from_contracts(\n        contract_id: ContractId,\n        contract_id2: ContractId,\n        value: u64,\n    ) -> u64 {\n        let contract_instance = abi(LibContract, contract_id.into());\n        let contract_instance2 = abi(LibContract, contract_id2.into());\n\n        contract_instance.increment(value) + contract_instance2.increment(value)\n    }\n\n    fn mint_then_increment_from_contract(contract_id: ContractId, amount: u64, address: Identity) {\n        mint_to(address, b256::zero(), amount);\n\n        let contract_instance = abi(LibContract, contract_id.into());\n        let _ = contract_instance.increment(42);\n    }\n\n    fn require_from_contract(contract_id: ContractId) {\n        let contract_instance = abi(LibContract, contract_id.into());\n\n        contract_instance.require();\n    }\n\n    fn re_entrant(contract_id: ContractId, re_enter: bool) -> u64 {\n        if !re_enter {\n            return 101;\n        }\n\n        let contract_instance = abi(ContractCaller, contract_id.into());\n        let _ = contract_instance.re_entrant(contract_id, false);\n\n        42\n    }\n}\n"
  },
  {
    "path": "e2e/sway/contracts/library_test/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"library_test\"\n"
  },
  {
    "path": "e2e/sway/contracts/library_test/src/main.sw",
    "content": "library;\n\nabi Incrementor {\n    fn initialize(gas: u64, amt: u64, coin: b256, initial_value: u64) -> u64;\n    fn increment(gas: u64, amt: u64, coin: b256, initial_value: u64) -> u64;\n}\n"
  },
  {
    "path": "e2e/sway/contracts/liquidity_pool/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"liquidity_pool\"\n"
  },
  {
    "path": "e2e/sway/contracts/liquidity_pool/src/main.sw",
    "content": "contract;\n\nuse std::{asset::{mint_to, transfer}, call_frames::msg_asset_id, context::msg_amount};\nabi LiquidityPool {\n    #[payable]\n    fn deposit(recipient: Identity);\n    #[payable]\n    fn withdraw(recipient: Identity);\n}\nconst BASE_TOKEN: AssetId = AssetId::from(0x9ae5b658754e096e4d681c548daf46354495a437cc61492599e33fc64dcdc30c);\nimpl LiquidityPool for Contract {\n    #[payable]\n    fn deposit(recipient: Identity) {\n        assert(BASE_TOKEN == msg_asset_id());\n        assert(0 < msg_amount());\n        // Mint two times the amount.\n        let amount_to_mint = msg_amount() * 2;\n        // Mint some LP token based upon the amount of the base token.\n        mint_to(recipient, b256::zero(), amount_to_mint);\n    }\n    #[payable]\n    fn withdraw(recipient: Identity) {\n        assert(0 < msg_amount());\n        // Amount to withdraw.\n        let amount_to_transfer = msg_amount() / 2;\n        // Transfer base token to recipient.\n        transfer(recipient, BASE_TOKEN, amount_to_transfer);\n    }\n}\n"
  },
  {
    "path": "e2e/sway/contracts/low_level_caller/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"low_level_caller\"\n"
  },
  {
    "path": "e2e/sway/contracts/low_level_caller/src/main.sw",
    "content": "contract;\n\nuse std::{\n    bytes::Bytes,\n    constants::ZERO_B256,\n    low_level_call::{\n        call_with_function_selector,\n        CallParams,\n    },\n};\n\nabi MyCallerContract {\n    fn call_low_level_call(\n        target: ContractId,\n        function_selector: Bytes,\n        calldata: Bytes,\n    );\n}\n\nimpl MyCallerContract for Contract {\n    // ANCHOR: low_level_call_contract\n    fn call_low_level_call(\n        target: ContractId,\n        function_selector: Bytes,\n        calldata: Bytes,\n    ) {\n        let call_params = CallParams {\n            coins: 0,\n            asset_id: AssetId::from(ZERO_B256),\n            gas: 10_000,\n        };\n\n        call_with_function_selector(target, function_selector, calldata, call_params);\n    }\n    // ANCHOR_END: low_level_call_contract\n}\n"
  },
  {
    "path": "e2e/sway/contracts/msg_methods/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"msg_methods\"\n"
  },
  {
    "path": "e2e/sway/contracts/msg_methods/src/main.sw",
    "content": "contract;\n\nuse std::auth::msg_sender;\n\nabi FuelTest {\n    #[payable]\n    fn message_sender() -> Identity;\n}\n\nimpl FuelTest for Contract {\n    #[payable]\n    fn message_sender() -> Identity {\n        msg_sender().unwrap()\n    }\n}\n"
  },
  {
    "path": "e2e/sway/contracts/multiple_read_calls/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"multiple_read_calls\"\n"
  },
  {
    "path": "e2e/sway/contracts/multiple_read_calls/src/main.sw",
    "content": "contract;\n\nuse std::storage::storage_api::{read, write};\n\nabi MyContract {\n    #[storage(write)]\n    fn store(input: u64);\n    #[storage(read)]\n    fn read() -> u64;\n}\n\nconst COUNTER_KEY = 0x0000000000000000000000000000000000000000000000000000000000000000;\n\nimpl MyContract for Contract {\n    #[storage(write)]\n    fn store(input: u64) {\n        write(COUNTER_KEY, 0, input);\n    }\n\n    #[storage(read)]\n    fn read() -> u64 {\n        read::<u64>(COUNTER_KEY, 0).unwrap_or(0)\n    }\n}\n"
  },
  {
    "path": "e2e/sway/contracts/needs_custom_decoder/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"needs_custom_decoder\"\n\n[dependencies]\n"
  },
  {
    "path": "e2e/sway/contracts/needs_custom_decoder/src/main.sw",
    "content": "contract;\n\nimpl AbiEncode for [u8; 1000] {\n    fn abi_encode(self, buffer: Buffer) -> Buffer {\n        let mut buffer = buffer;\n        let mut i = 0;\n        while i < 1000 {\n            buffer = self[i].abi_encode(buffer);\n            i += 1;\n        };\n\n        buffer\n    }\n}\n\nabi MyContract {\n    fn i_return_a_1k_el_array() -> [u8; 1000];\n    fn i_log_a_1k_el_array();\n}\n\nimpl MyContract for Contract {\n    fn i_log_a_1k_el_array() {\n        let arr: [u8; 1000] = [0; 1000];\n        log(arr);\n    }\n\n    fn i_return_a_1k_el_array() -> [u8; 1000] {\n        [0; 1000]\n    }\n}\n"
  },
  {
    "path": "e2e/sway/contracts/payable_annotation/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"payable_annotation\"\n"
  },
  {
    "path": "e2e/sway/contracts/payable_annotation/src/main.sw",
    "content": "contract;\n\nabi TestContract {\n    #[payable]\n    fn payable() -> u64;\n    fn non_payable() -> u64;\n}\n\nimpl TestContract for Contract {\n    #[payable]\n    fn payable() -> u64 {\n        42\n    }\n\n    fn non_payable() -> u64 {\n        42\n    }\n}\n"
  },
  {
    "path": "e2e/sway/contracts/proxy/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"proxy\"\n\n[dependencies]\n"
  },
  {
    "path": "e2e/sway/contracts/proxy/src/main.sw",
    "content": "contract;\n\nuse std::execution::run_external;\n\nabi Proxy {\n    #[storage(write)]\n    fn set_target_contract(id: ContractId);\n\n    // methods of the `huge_contract` in our e2e sway contracts\n    #[storage(read)]\n    fn something() -> u64;\n\n    #[storage(read)]\n    fn write_some_u64(some: u64);\n\n    #[storage(read)]\n    fn read_some_u64() -> u64;\n}\n\nstorage {\n    target_contract: Option<ContractId> = None,\n}\n\nimpl Proxy for Contract {\n    #[storage(write)]\n    fn set_target_contract(id: ContractId) {\n        storage.target_contract.write(Some(id));\n    }\n\n    #[storage(read)]\n    fn something() -> u64 {\n        let target = storage.target_contract.read().unwrap();\n        run_external(target)\n    }\n\n    #[storage(read)]\n    fn write_some_u64(_some: u64) {\n        let target = storage.target_contract.read().unwrap();\n        run_external(target)\n    }\n\n    #[storage(read)]\n    fn read_some_u64() -> u64 {\n        let target = storage.target_contract.read().unwrap();\n        run_external(target)\n    }\n}\n"
  },
  {
    "path": "e2e/sway/contracts/revert_transaction_error/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"revert_transaction_error\"\n"
  },
  {
    "path": "e2e/sway/contracts/revert_transaction_error/src/main.sw",
    "content": "contract;\n\nabi MyContract {\n    fn make_transaction_fail(fail: bool) -> u64;\n}\n\nimpl MyContract for Contract {\n    fn make_transaction_fail(fail: bool) -> u64 {\n        if fail {\n            revert(128);\n        }\n\n        42\n    }\n}\n"
  },
  {
    "path": "e2e/sway/contracts/storage/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"storage\"\n"
  },
  {
    "path": "e2e/sway/contracts/storage/src/main.sw",
    "content": "contract;\n\nuse std::storage::storage_api::read;\n\nstorage {\n    x: u64 = 64,\n    y: b256 = 0x0101010101010101010101010101010101010101010101010101010101010101,\n}\n\nabi MyContract {\n    #[storage(write)]\n    fn set_storage(x: u64, y: b256);\n    #[storage(read)]\n    fn get_value_b256(key: b256) -> b256;\n    #[storage(read)]\n    fn get_value_u64(key: b256) -> u64;\n}\n\nimpl MyContract for Contract {\n    #[storage(write)]\n    fn set_storage(x: u64, y: b256) {\n        storage.x.write(x);\n        storage.y.write(y);\n    }\n\n    #[storage(read)]\n    fn get_value_b256(key: b256) -> b256 {\n        read::<b256>(key, 0).unwrap()\n    }\n\n    #[storage(read)]\n    fn get_value_u64(key: b256) -> u64 {\n        read::<u64>(key, 0).unwrap()\n    }\n}\n"
  },
  {
    "path": "e2e/sway/contracts/token_ops/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"token_ops\"\n"
  },
  {
    "path": "e2e/sway/contracts/token_ops/src/main.sw",
    "content": "contract;\n\nuse std::{asset::*, bytes::Bytes, context::balance_of, context::msg_amount, message::send_message};\n\nabi TestFuelCoin {\n    fn mint_coins(mint_amount: u64);\n    fn mint_to_addresses(mint_amount: u64, addresses: [Identity; 3]);\n    fn burn_coins(burn_amount: u64);\n    fn transfer(coins: u64, asset_id: AssetId, target: Identity);\n    fn get_balance(target: ContractId, asset_id: AssetId) -> u64;\n    #[payable]\n    fn get_msg_amount() -> u64;\n    fn send_message(recipient: b256, coins: u64);\n}\n\nimpl TestFuelCoin for Contract {\n    fn mint_coins(mint_amount: u64) {\n        mint(b256::zero(), mint_amount);\n    }\n    fn mint_to_addresses(mint_amount: u64, addresses: [Identity; 3]) {\n        let mut counter = 0;\n        while counter < 3 {\n            mint_to(addresses[counter], b256::zero(), mint_amount);\n            counter = counter + 1;\n        }\n    }\n\n    fn burn_coins(burn_amount: u64) {\n        burn(b256::zero(), burn_amount);\n    }\n\n    // ANCHOR: variable_outputs\n    fn transfer(coins: u64, asset_id: AssetId, recipient: Identity) {\n        transfer(recipient, asset_id, coins);\n    }\n    // ANCHOR_END: variable_outputs\n    fn get_balance(target: ContractId, asset_id: AssetId) -> u64 {\n        balance_of(target, asset_id)\n    }\n\n    #[payable]\n    fn get_msg_amount() -> u64 {\n        msg_amount()\n    }\n\n    fn send_message(recipient: b256, coins: u64) {\n        let mut data = Bytes::new();\n        data.push(1u8);\n        data.push(2u8);\n        data.push(3u8);\n\n        send_message(recipient, data, coins);\n    }\n}\n"
  },
  {
    "path": "e2e/sway/contracts/transaction_block_height/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"transaction_block_height\"\n"
  },
  {
    "path": "e2e/sway/contracts/transaction_block_height/src/main.sw",
    "content": "contract;\n\nabi MyContract {\n    fn get_current_height() -> u32;\n    fn calling_this_will_produce_a_block();\n}\n\nimpl MyContract for Contract {\n    fn get_current_height() -> u32 {\n        std::block::height()\n    }\n\n    fn calling_this_will_produce_a_block() {}\n}\n"
  },
  {
    "path": "e2e/sway/contracts/tx_input_output/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"tx_input_output\"\n"
  },
  {
    "path": "e2e/sway/contracts/tx_input_output/src/main.sw",
    "content": "contract;\n\nuse std::{inputs::*, outputs::*};\n\nconfigurable {\n    ASSET_ID: AssetId = AssetId::zero(),\n    OWNER: Address = Address::zero(),\n}\n\nabi TxContractTest {\n    fn check_input(index: u64);\n    fn check_output_is_change(index: u64);\n}\n\nimpl TxContractTest for Contract {\n    fn check_input(index: u64) {\n        // Checks if coin and maybe returns owner\n        if let Some(owner) = input_coin_owner(index) {\n            require(owner == OWNER, \"wrong owner\");\n\n            let asset_id = input_asset_id(index).unwrap();\n            require(asset_id == ASSET_ID, \"wrong asset id\");\n        } else {\n            revert_with_log(\"input is not a coin\");\n        }\n    }\n\n    fn check_output_is_change(index: u64) {\n        if let Some(Output::Change) = output_type(index) {\n            let asset_to = output_asset_to(index).unwrap();\n            require(asset_to == OWNER, \"wrong change address\");\n        } else {\n            revert_with_log(\"output is not change\");\n        }\n    }\n}\n"
  },
  {
    "path": "e2e/sway/contracts/var_outputs/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"var_outputs\"\n"
  },
  {
    "path": "e2e/sway/contracts/var_outputs/src/main.sw",
    "content": "contract;\n\nabi MyContract {\n    fn mint(coins: u64, recipient: Identity);\n}\n\nimpl MyContract for Contract {\n    fn mint(coins: u64, recipient: Identity) {\n        let mut counter = 0;\n        while counter < coins {\n            counter += 1;\n            std::asset::mint_to(recipient, b256::zero(), 1);\n        }\n    }\n}\n"
  },
  {
    "path": "e2e/sway/logs/contract_logs/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"contract_logs\"\n\n[dependencies]\ncontract_logs_abi = { path = \"../contract_logs_abi/\", package = \"contract_logs_abi\" }\n"
  },
  {
    "path": "e2e/sway/logs/contract_logs/src/main.sw",
    "content": "contract;\n\nuse std::{logging::log, string::String};\nuse contract_logs_abi::ContractLogs;\n\nstruct B {\n    id: u64,\n    val: u64,\n}\n\n#[error_type]\nenum MyError {\n    #[error(m = \"some error A\")]\n    A: (),\n    #[error(m = \"some complex error B\")]\n    B: B,\n}\n\n#[allow(dead_code)]\nstruct TestStruct {\n    field_1: bool,\n    field_2: b256,\n    field_3: u64,\n}\n\n#[allow(dead_code)]\nenum TestEnum {\n    VariantOne: (),\n    VariantTwo: (),\n}\n\n#[allow(dead_code)]\nstruct StructWithGeneric<D> {\n    field_1: D,\n    field_2: u64,\n}\n\n#[allow(dead_code)]\nenum EnumWithGeneric<D> {\n    VariantOne: D,\n    VariantTwo: (),\n}\n\n#[allow(dead_code)]\nstruct StructWithNestedGeneric<D> {\n    field_1: D,\n    field_2: u64,\n}\n\n#[allow(dead_code)]\nstruct StructDeeplyNestedGeneric<D> {\n    field_1: D,\n    field_2: u64,\n}\n\nimpl ContractLogs for Contract {\n    fn produce_logs_values() {\n        log(64u64);\n        log(32u32);\n        log(16u16);\n        log(8u8);\n    }\n\n    // ANCHOR: produce_logs\n    fn produce_logs_variables() {\n        let f: u64 = 64;\n        let u: b256 = 0xef86afa9696cf0dc6385e2c407a6e159a1103cefb7e2ae0636fb33d3cb2a9e4a;\n        let e: str[4] = __to_str_array(\"Fuel\");\n        let l: [u8; 3] = [1u8, 2u8, 3u8];\n\n        log(f);\n        log(u);\n        log(e);\n        log(l);\n    }\n    // ANCHOR_END: produce_logs\n    fn produce_logs_custom_types() {\n        let f: u64 = 64;\n        let u: b256 = 0xef86afa9696cf0dc6385e2c407a6e159a1103cefb7e2ae0636fb33d3cb2a9e4a;\n\n        let test_struct = TestStruct {\n            field_1: true,\n            field_2: u,\n            field_3: f,\n        };\n        let test_enum = TestEnum::VariantTwo;\n\n        log(test_struct);\n        log(test_enum);\n        log((test_struct, test_enum));\n    }\n\n    fn produce_logs_generic_types() {\n        let l: [u8; 3] = [1u8, 2u8, 3u8];\n\n        let test_struct = StructWithGeneric {\n            field_1: l,\n            field_2: 64,\n        };\n        let test_enum = EnumWithGeneric::VariantOne(l);\n        let test_struct_nested = StructWithNestedGeneric {\n            field_1: test_struct,\n            field_2: 64,\n        };\n        let test_deeply_nested_generic = StructDeeplyNestedGeneric {\n            field_1: test_struct_nested,\n            field_2: 64,\n        };\n\n        log(test_struct);\n        log(test_enum);\n        log(test_struct_nested);\n        log(test_deeply_nested_generic);\n    }\n\n    fn produce_multiple_logs() {\n        let f: u64 = 64;\n        let u: b256 = 0xef86afa9696cf0dc6385e2c407a6e159a1103cefb7e2ae0636fb33d3cb2a9e4a;\n        let e: str[4] = __to_str_array(\"Fuel\");\n        let l: [u8; 3] = [1u8, 2u8, 3u8];\n        let test_struct = TestStruct {\n            field_1: true,\n            field_2: u,\n            field_3: f,\n        };\n        let test_enum = TestEnum::VariantTwo;\n        let test_generic_struct = StructWithGeneric {\n            field_1: test_struct,\n            field_2: 64,\n        };\n\n        log(64);\n        log(32u32);\n        log(16u16);\n        log(8u8);\n        log(f);\n        log(u);\n        log(e);\n        log(l);\n        log(test_struct);\n        log(test_enum);\n        log(test_generic_struct);\n    }\n\n    fn produce_bad_logs() {\n        // produce a custom log with log id 128\n        // this log id will not be present in abi JSON\n        asm(r1: 0, r2: 128, r3: 0, r4: 0) {\n            log r1 r2 r3 r4;\n        }\n\n        log(123);\n    }\n\n    fn produce_string_slice_log() {\n        log(\"fuel\");\n    }\n\n    fn produce_string_log() {\n        log(String::from_ascii_str(\"fuel\"));\n    }\n\n    fn produce_bytes_log() {\n        log(String::from_ascii_str(\"fuel\").as_bytes());\n    }\n\n    fn produce_raw_slice_log() {\n        log(String::from_ascii_str(\"fuel\").as_raw_slice());\n    }\n\n    fn produce_vec_log() {\n        let mut v = Vec::new();\n        v.push(1u16);\n        v.push(2u16);\n        v.push(3u16);\n\n        let some_enum = EnumWithGeneric::VariantOne(v);\n        let other_enum = EnumWithGeneric::VariantTwo;\n\n        let mut v1 = Vec::new();\n        v1.push(some_enum);\n        v1.push(other_enum);\n        v1.push(some_enum);\n\n        let mut v2 = Vec::new();\n        v2.push(v1);\n        v2.push(v1);\n\n        let mut v3 = Vec::new();\n        v3.push(v2);\n\n        log(v3);\n    }\n\n    fn produce_panic() {\n        panic \"some panic message\";\n    }\n\n    fn produce_panic_with_error() {\n        panic MyError::B(B {\n            id: 42,\n            val: 36,\n        });\n    }\n}\n"
  },
  {
    "path": "e2e/sway/logs/contract_logs_abi/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"contract_logs_abi\"\n"
  },
  {
    "path": "e2e/sway/logs/contract_logs_abi/src/main.sw",
    "content": "library;\n\nuse std::logging::log;\n\nabi ContractLogs {\n    fn produce_logs_values();\n    fn produce_logs_variables();\n    fn produce_logs_custom_types();\n    fn produce_logs_generic_types();\n    fn produce_multiple_logs();\n    fn produce_bad_logs();\n    fn produce_string_slice_log();\n    fn produce_string_log();\n    fn produce_bytes_log();\n    fn produce_raw_slice_log();\n    fn produce_vec_log();\n\n    fn produce_panic();\n    fn produce_panic_with_error();\n}\n"
  },
  {
    "path": "e2e/sway/logs/contract_revert_logs/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"contract_revert_logs\"\n"
  },
  {
    "path": "e2e/sway/logs/contract_revert_logs/src/main.sw",
    "content": "contract;\n\nuse std::logging::log;\n\n#[allow(dead_code)]\nenum EnumWithGeneric<D> {\n    VariantOne: D,\n    VariantTwo: (),\n}\n\n#[allow(dead_code)]\nstruct StructWithNestedGeneric<D> {\n    field_1: D,\n    field_2: u64,\n}\n\n#[allow(dead_code)]\nstruct StructDeeplyNestedGeneric<D> {\n    field_1: D,\n    field_2: u64,\n}\n\nabi TestContract {\n    fn require_primitive();\n    fn require_string();\n    fn require_custom_generic();\n    fn require_with_additional_logs();\n\n    fn rev_w_log_primitive();\n    fn rev_w_log_string();\n    fn rev_w_log_custom_generic();\n}\n\nimpl TestContract for Contract {\n    fn require_primitive() {\n        require(false, 42);\n    }\n\n    fn require_string() {\n        require(false, __to_str_array(\"fuel\"));\n    }\n\n    fn require_custom_generic() {\n        let l: [u8; 3] = [1u8, 2u8, 3u8];\n\n        let test_enum = EnumWithGeneric::VariantOne(l);\n        let test_struct_nested = StructWithNestedGeneric {\n            field_1: test_enum,\n            field_2: 64,\n        };\n        let test_deeply_nested_generic = StructDeeplyNestedGeneric {\n            field_1: test_struct_nested,\n            field_2: 64,\n        };\n\n        require(false, test_deeply_nested_generic);\n    }\n\n    fn require_with_additional_logs() {\n        log(42);\n        log(__to_str_array(\"fuel\"));\n        require(false, 64);\n    }\n\n    fn rev_w_log_primitive() {\n        revert_with_log(42);\n    }\n\n    fn rev_w_log_string() {\n        revert_with_log(__to_str_array(\"fuel\"));\n    }\n\n    fn rev_w_log_custom_generic() {\n        let l: [u8; 3] = [1u8, 2u8, 3u8];\n\n        let test_enum = EnumWithGeneric::VariantOne(l);\n        let test_struct_nested = StructWithNestedGeneric {\n            field_1: test_enum,\n            field_2: 64,\n        };\n        let test_deeply_nested_generic = StructDeeplyNestedGeneric {\n            field_1: test_struct_nested,\n            field_2: 64,\n        };\n\n        revert_with_log(test_deeply_nested_generic);\n    }\n}\n"
  },
  {
    "path": "e2e/sway/logs/contract_with_contract_logs/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"contract_with_contract_logs\"\n\n[dependencies]\nlibrary = { path = \"../contract_logs_abi/\", package = \"contract_logs_abi\" }\n"
  },
  {
    "path": "e2e/sway/logs/contract_with_contract_logs/src/main.sw",
    "content": "contract;\n\nuse std::logging::log;\nuse library::ContractLogs;\n\nabi ContractCaller {\n    fn logs_from_external_contract(contract_id: ContractId) -> ();\n    fn panic_from_external_contract(contract_id: ContractId) -> ();\n    fn panic_error_from_external_contract(contract_id: ContractId) -> ();\n}\n\nimpl ContractCaller for Contract {\n    fn logs_from_external_contract(contract_id: ContractId) {\n        // Call contract with `contract_id` and make some logs\n        let contract_instance = abi(ContractLogs, contract_id.into());\n        contract_instance.produce_logs_values();\n    }\n\n    fn panic_from_external_contract(contract_id: ContractId) {\n        // Call contract with `contract_id` and make some logs\n        let contract_instance = abi(ContractLogs, contract_id.into());\n        contract_instance.produce_panic();\n    }\n\n    fn panic_error_from_external_contract(contract_id: ContractId) {\n        // Call contract with `contract_id` and make some logs\n        let contract_instance = abi(ContractLogs, contract_id.into());\n        contract_instance.produce_panic_with_error();\n    }\n}\n"
  },
  {
    "path": "e2e/sway/logs/script_heap_logs/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"script_heap_logs\"\n"
  },
  {
    "path": "e2e/sway/logs/script_heap_logs/src/main.sw",
    "content": "script;\n\nuse std::{logging::log, string::String};\n\n#[allow(dead_code)]\nenum EnumWithGeneric<D> {\n    VariantOne: D,\n    VariantTwo: (),\n}\n\nfn main() {\n    // String slice\n    log(\"fuel\");\n\n    // String\n    log(String::from_ascii_str(\"fuel\"));\n\n    // Bytes\n    log(String::from_ascii_str(\"fuel\").as_bytes());\n\n    // RawSlice\n    log(String::from_ascii_str(\"fuel\").as_raw_slice());\n\n    // Vector\n    let mut v = Vec::new();\n    v.push(1u16);\n    v.push(2u16);\n    v.push(3u16);\n\n    let some_enum = EnumWithGeneric::VariantOne(v);\n    let other_enum = EnumWithGeneric::VariantTwo;\n\n    let mut v1 = Vec::new();\n    v1.push(some_enum);\n    v1.push(other_enum);\n    v1.push(some_enum);\n\n    let mut v2 = Vec::new();\n    v2.push(v1);\n    v2.push(v1);\n\n    let mut v3 = Vec::new();\n    v3.push(v2);\n\n    log(v3);\n}\n"
  },
  {
    "path": "e2e/sway/logs/script_logs/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"script_logs\"\n"
  },
  {
    "path": "e2e/sway/logs/script_logs/src/main.sw",
    "content": "script;\n\nuse std::logging::log;\n\n#[allow(dead_code)]\nstruct TestStruct {\n    field_1: bool,\n    field_2: b256,\n    field_3: u64,\n}\n\n#[allow(dead_code)]\nenum TestEnum {\n    VariantOne: (),\n    VariantTwo: (),\n}\n\n#[allow(dead_code)]\nstruct StructWithGeneric<D> {\n    field_1: D,\n    field_2: u64,\n}\n\n#[allow(dead_code)]\nenum EnumWithGeneric<D> {\n    VariantOne: D,\n    VariantTwo: (),\n}\n\n#[allow(dead_code)]\nstruct StructWithNestedGeneric<D> {\n    field_1: D,\n    field_2: u64,\n}\n\n#[allow(dead_code)]\nstruct StructDeeplyNestedGeneric<D> {\n    field_1: D,\n    field_2: u64,\n}\n\nfn main() {\n    let f: u64 = 64;\n    let u: b256 = 0xef86afa9696cf0dc6385e2c407a6e159a1103cefb7e2ae0636fb33d3cb2a9e4a;\n    let e: str[4] = __to_str_array(\"Fuel\");\n    let l: [u8; 3] = [1u8, 2u8, 3u8];\n\n    let test_struct = TestStruct {\n        field_1: true,\n        field_2: u,\n        field_3: f,\n    };\n    let test_enum = TestEnum::VariantTwo;\n    let test_generic_struct = StructWithGeneric {\n        field_1: test_struct,\n        field_2: 64,\n    };\n\n    let test_generic_enum = EnumWithGeneric::VariantOne(l);\n    let test_struct_nested = StructWithNestedGeneric {\n        field_1: test_generic_struct,\n        field_2: 64,\n    };\n    let test_deeply_nested_generic = StructDeeplyNestedGeneric {\n        field_1: test_struct_nested,\n        field_2: 64,\n    };\n\n    log(128);\n    log(32u32);\n    log(16u16);\n    log(8u8);\n    log(f);\n    log(u);\n    log(e);\n    log(l);\n    log(test_struct);\n    log(test_enum);\n    log((test_struct, test_enum));\n    log(test_generic_struct);\n    log(test_generic_enum);\n    log(test_struct_nested);\n    log(test_deeply_nested_generic);\n}\n"
  },
  {
    "path": "e2e/sway/logs/script_revert_logs/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"script_revert_logs\"\n"
  },
  {
    "path": "e2e/sway/logs/script_revert_logs/src/main.sw",
    "content": "script;\n\nuse std::logging::log;\n\n#[allow(dead_code)]\nenum EnumWithGeneric<D> {\n    VariantOne: D,\n    VariantTwo: (),\n}\n\n#[allow(dead_code)]\nstruct StructWithNestedGeneric<D> {\n    field_1: D,\n    field_2: u64,\n}\n\n#[allow(dead_code)]\nstruct StructDeeplyNestedGeneric<D> {\n    field_1: D,\n    field_2: u64,\n}\n\nstruct B {\n    id: u64,\n    val: u64,\n}\n\n#[error_type]\nenum MyError {\n    #[error(m = \"some error A\")]\n    A: (),\n    #[error(m = \"some complex error B\")]\n    B: B,\n}\n\n#[allow(dead_code)]\nenum MatchEnum {\n    RequirePrimitive: (),\n    RequireString: (),\n    RequireCustomGeneric: (),\n    RequireWithAdditionalLogs: (),\n    RevWLogPrimitive: (),\n    RevWLogString: (),\n    RevWLogCustomGeneric: (),\n    Panic: (),\n    PanicError: (),\n}\n\nfn main(match_enum: MatchEnum) {\n    match match_enum {\n        MatchEnum::RequirePrimitive => require(false, 42),\n        MatchEnum::RequireString => require(false, __to_str_array(\"fuel\")),\n        MatchEnum::RequireCustomGeneric => {\n            let l: [u8; 3] = [1u8, 2u8, 3u8];\n\n            let test_enum = EnumWithGeneric::VariantOne(l);\n            let test_struct_nested = StructWithNestedGeneric {\n                field_1: test_enum,\n                field_2: 64,\n            };\n            let test_deeply_nested_generic = StructDeeplyNestedGeneric {\n                field_1: test_struct_nested,\n                field_2: 64,\n            };\n\n            require(false, test_deeply_nested_generic);\n        }\n        MatchEnum::RequireWithAdditionalLogs => {\n            log(42);\n            log(__to_str_array(\"fuel\"));\n            require(false, 64);\n        }\n        MatchEnum::RevWLogPrimitive => revert_with_log(42),\n        MatchEnum::RevWLogString => revert_with_log(__to_str_array(\"fuel\")),\n        MatchEnum::RevWLogCustomGeneric => {\n            let l: [u8; 3] = [1u8, 2u8, 3u8];\n\n            let test_enum = EnumWithGeneric::VariantOne(l);\n            let test_struct_nested = StructWithNestedGeneric {\n                field_1: test_enum,\n                field_2: 64,\n            };\n            let test_deeply_nested_generic = StructDeeplyNestedGeneric {\n                field_1: test_struct_nested,\n                field_2: 64,\n            };\n\n            revert_with_log(test_deeply_nested_generic);\n        }\n        MatchEnum::Panic => panic \"some panic message\",\n        MatchEnum::PanicError => panic MyError::B(B {\n            id: 42,\n            val: 36,\n        }),\n    }\n}\n"
  },
  {
    "path": "e2e/sway/logs/script_with_contract_logs/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"script_with_contract_logs\"\n\n[dependencies]\nlibrary = { path = \"../contract_logs_abi/\", package = \"contract_logs_abi\" }\n"
  },
  {
    "path": "e2e/sway/logs/script_with_contract_logs/src/main.sw",
    "content": "script;\n\nuse std::logging::log;\nuse library::ContractLogs;\n\n#[allow(dead_code)]\nenum MatchEnum {\n    Logs: (),\n    Panic: (),\n    PanicError: (),\n}\n\nfn main(contract_id: ContractId, match_enum: MatchEnum) {\n    let contract_instance = abi(ContractLogs, contract_id.into());\n    match match_enum {\n        MatchEnum::Logs => {\n            contract_instance.produce_logs_values();\n\n            let f: bool = true;\n            let u: u64 = 42;\n            let e: str[4] = __to_str_array(\"Fuel\");\n            let l: [u8; 3] = [1u8, 2u8, 3u8];\n            log(f);\n            log(u);\n            log(e);\n            log(l);\n        }\n        MatchEnum::Panic => {\n            contract_instance.produce_panic();\n        }\n        MatchEnum::PanicError => {\n            contract_instance.produce_panic_with_error();\n        }\n    }\n}\n"
  },
  {
    "path": "e2e/sway/predicates/basic_predicate/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"basic_predicate\"\n"
  },
  {
    "path": "e2e/sway/predicates/basic_predicate/src/main.sw",
    "content": "predicate;\n\nfn main(a: u32, b: u64) -> bool {\n    b == a.as_u64()\n}\n"
  },
  {
    "path": "e2e/sway/predicates/predicate_blobs/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"predicate_blobs\"\n"
  },
  {
    "path": "e2e/sway/predicates/predicate_blobs/src/main.sw",
    "content": "predicate;\n\nconfigurable {\n    SECRET_NUMBER: u64 = 9000,\n}\n\nfn main(arg1: u8, arg2: u8) -> bool {\n    arg1 == 1 && arg2 == 19 && SECRET_NUMBER == 10001\n}\n"
  },
  {
    "path": "e2e/sway/predicates/predicate_configurables/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"predicate_configurables\"\n"
  },
  {
    "path": "e2e/sway/predicates/predicate_configurables/src/main.sw",
    "content": "predicate;\n\nimpl PartialEq for StructWithGeneric<u8> {\n    fn eq(self, other: Self) -> bool {\n        self.field_1 == other.field_1 && self.field_2 == other.field_2\n    }\n}\nimpl Eq for StructWithGeneric<u8> {}\n\nimpl PartialEq for EnumWithGeneric<bool> {\n    fn eq(self, other: Self) -> bool {\n        match (self, other) {\n            (EnumWithGeneric::VariantOne, EnumWithGeneric::VariantOne) => true,\n            (EnumWithGeneric::VariantTwo, EnumWithGeneric::VariantTwo) => true,\n            _ => false,\n        }\n    }\n}\nimpl Eq for EnumWithGeneric<bool> {}\n\n// ANCHOR: predicate_configurables\n#[allow(dead_code)]\nenum EnumWithGeneric<D> {\n    VariantOne: D,\n    VariantTwo: (),\n}\n\nstruct StructWithGeneric<D> {\n    field_1: D,\n    field_2: u64,\n}\n\nconfigurable {\n    BOOL: bool = true,\n    U8: u8 = 8,\n    TUPLE: (u8, bool) = (8, true),\n    ARRAY: [u32; 3] = [253, 254, 255],\n    STRUCT: StructWithGeneric<u8> = StructWithGeneric {\n        field_1: 8,\n        field_2: 16,\n    },\n    ENUM: EnumWithGeneric<bool> = EnumWithGeneric::VariantOne(true),\n}\n\nfn main(\n    switch: bool,\n    u_8: u8,\n    some_tuple: (u8, bool),\n    some_array: [u32; 3],\n    some_struct: StructWithGeneric<u8>,\n    some_enum: EnumWithGeneric<bool>,\n) -> bool {\n    switch == BOOL && u_8 == U8 && some_tuple.0 == TUPLE.0 && some_tuple.1 == TUPLE.1 && some_array[0] == ARRAY[0] && some_array[1] == ARRAY[1] && some_array[2] == ARRAY[2] && some_struct == STRUCT && some_enum == ENUM\n}\n// ANCHOR_END: predicate_configurables\n"
  },
  {
    "path": "e2e/sway/predicates/predicate_tx_input_output/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"predicate_tx_input_output\"\n"
  },
  {
    "path": "e2e/sway/predicates/predicate_tx_input_output/src/main.sw",
    "content": "predicate;\n\nuse std::{inputs::*, outputs::*};\n\nconfigurable {\n    ASSET_ID: AssetId = AssetId::zero(),\n    OWNER: Address = Address::zero(),\n}\n\nfn main(input_index: u64, output_index: u64) -> bool {\n    // Checks if coin and maybe returns owner\n    let input_ok = if let Some(owner) = input_coin_owner(input_index) {\n        let is_owner = owner == OWNER;\n\n        let asset_id = input_asset_id(input_index).unwrap();\n\n        is_owner && asset_id == ASSET_ID\n    } else {\n        false\n    };\n\n    let output_ok = if let Some(Output::Change) = output_type(output_index) {\n        let asset_to = output_asset_to(output_index).unwrap();\n        asset_to == OWNER\n    } else {\n        false\n    };\n\n    input_ok && output_ok\n}\n"
  },
  {
    "path": "e2e/sway/predicates/predicate_witnesses/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"predicate_witnesses\"\n"
  },
  {
    "path": "e2e/sway/predicates/predicate_witnesses/src/main.sw",
    "content": "predicate;\n\nuse std::tx::tx_witness_data;\n\nfn main(witness_index: u64, witness_index2: u64) -> bool {\n    let witness: u8 = tx_witness_data(witness_index).unwrap();\n    let witness2: u64 = tx_witness_data(witness_index2).unwrap();\n\n    witness == 64 && witness2 == 4096\n}\n"
  },
  {
    "path": "e2e/sway/predicates/signatures/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"signatures\"\n"
  },
  {
    "path": "e2e/sway/predicates/signatures/src/main.sw",
    "content": "predicate;\n\nuse std::{\n    b512::B512,\n    crypto::{\n        message::Message,\n        secp256k1::Secp256k1,\n    },\n    inputs::input_predicate_data,\n};\n\nfn extract_public_key_and_match(signature: B512, expected_public_key: b256) -> u64 {\n    let signature = Secp256k1::from(signature);\n\n    if let Result::Ok(pub_key_sig) = signature.address(Message::from(b256::zero()))\n    {\n        if pub_key_sig == Address::from(expected_public_key) {\n            return 1;\n        }\n    }\n\n    0\n}\n\nfn main(signatures: [B512; 3]) -> bool {\n    let public_keys = [\n        0xd58573593432a30a800f97ad32f877425c223a9e427ab557aab5d5bb89156db0,\n        0x14df7c7e4e662db31fe2763b1734a3d680e7b743516319a49baaa22b2032a857,\n        0x3ff494fb136978c3125844625dad6baf6e87cdb1328c8a51f35bda5afe72425c,\n    ];\n\n    let mut matched_keys = 0;\n\n    matched_keys = extract_public_key_and_match(signatures[0], public_keys[0]);\n    matched_keys = matched_keys + extract_public_key_and_match(signatures[1], public_keys[1]);\n    matched_keys = matched_keys + extract_public_key_and_match(signatures[2], public_keys[2]);\n\n    matched_keys > 1\n}\n"
  },
  {
    "path": "e2e/sway/predicates/swap/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"swap\"\n\n[dependencies]\n"
  },
  {
    "path": "e2e/sway/predicates/swap/src/main.sw",
    "content": "predicate;\n\nuse std::outputs::{Output, output_amount, output_asset_id, output_asset_to};\nfn main() -> bool {\n    let receiver = Address::from(0x09c0b2d1a486c439a87bcba6b46a7a1a23f3897cc83a94521a96da5c23bc58db);\n    let ask_amount = 100;\n    let output_index = 0;\n    let to = Address::from(output_asset_to(output_index).unwrap());\n    let asset_id = output_asset_id(output_index).unwrap();\n    let amount = output_amount(output_index).unwrap();\n    (to == receiver) && (amount == ask_amount) && (asset_id == AssetId::zero())\n}\n"
  },
  {
    "path": "e2e/sway/scripts/arguments/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"arguments\"\n"
  },
  {
    "path": "e2e/sway/scripts/arguments/src/main.sw",
    "content": "script;\n\nstruct Bimbam {\n    val: u64,\n}\n\nstruct SugarySnack {\n    twix: u64,\n    mars: u64,\n}\n\nfn main(bim: Bimbam, bam: SugarySnack) -> Bimbam {\n    let val = bam.twix + bim.val + (bam.mars * 2);\n    Bimbam { val: val }\n}\n"
  },
  {
    "path": "e2e/sway/scripts/basic_script/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"basic_script\"\n"
  },
  {
    "path": "e2e/sway/scripts/basic_script/src/main.sw",
    "content": "script;\n\n/// Compares a to b and returns a `str[5]`\nfn main(a: u64, b: u32) -> str[5] {\n    if a < b.as_u64() {\n        let my_string: str[5] = __to_str_array(\"hello\");\n        my_string\n    } else {\n        let my_string: str[5] = __to_str_array(\"heyoo\");\n        my_string\n    }\n}\n"
  },
  {
    "path": "e2e/sway/scripts/empty/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"empty\"\n\n[dependencies]\n"
  },
  {
    "path": "e2e/sway/scripts/empty/src/main.sw",
    "content": "script;\n\nfn main() {}\n"
  },
  {
    "path": "e2e/sway/scripts/require_from_contract/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"require_from_contract\"\n\n[dependencies]\nlibrary = { path = \"../../contracts/lib_contract_abi\", package = \"lib_contract_abi\" }\n"
  },
  {
    "path": "e2e/sway/scripts/require_from_contract/src/main.sw",
    "content": "script;\n\nuse library::LibContract;\n\nfn main(contract_id: ContractId) {\n    let contract_instance = abi(LibContract, contract_id.into());\n    contract_instance.require();\n}\n"
  },
  {
    "path": "e2e/sway/scripts/reverting/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"reverting\"\n"
  },
  {
    "path": "e2e/sway/scripts/reverting/src/main.sw",
    "content": "script;\n\nfn main() {\n    assert(false)\n}\n"
  },
  {
    "path": "e2e/sway/scripts/script_array/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"script_array\"\n"
  },
  {
    "path": "e2e/sway/scripts/script_array/src/main.sw",
    "content": "script;\n\nfn main(foo: [u64; 4]) -> u64 {\n    foo[0] + foo[1] + foo[2] + foo[3]\n}\n"
  },
  {
    "path": "e2e/sway/scripts/script_asserts/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"script_asserts\"\n"
  },
  {
    "path": "e2e/sway/scripts/script_asserts/src/main.sw",
    "content": "script;\n\nstruct TestStruct {\n    field_1: bool,\n    field_2: u64,\n}\n\n#[allow(dead_code)]\nenum TestEnum {\n    VariantOne: (),\n    VariantTwo: (),\n}\n\nimpl PartialEq for TestStruct {\n    fn eq(self, other: Self) -> bool {\n        self.field_1 == other.field_1 && self.field_2 == other.field_2\n    }\n}\nimpl Eq for TestStruct {}\n\nimpl PartialEq for TestEnum {\n    fn eq(self, other: Self) -> bool {\n        match (self, other) {\n            (TestEnum::VariantOne, TestEnum::VariantOne) => true,\n            (TestEnum::VariantTwo, TestEnum::VariantTwo) => true,\n            _ => false,\n        }\n    }\n}\nimpl Eq for TestEnum {}\n\n#[allow(dead_code)]\nenum MatchEnum {\n    AssertPrimitive: (u64, u64),\n    AssertEqPrimitive: (u64, u64),\n    AssertEqStruct: (TestStruct, TestStruct),\n    AssertEqEnum: (TestEnum, TestEnum),\n    AssertNePrimitive: (u64, u64),\n    AssertNeStruct: (TestStruct, TestStruct),\n    AssertNeEnum: (TestEnum, TestEnum),\n}\n\nfn main(match_enum: MatchEnum) {\n    if let MatchEnum::AssertPrimitive((a, b)) = match_enum {\n        assert(a == b);\n    } else if let MatchEnum::AssertEqPrimitive((a, b)) = match_enum {\n        assert_eq(a, b);\n    } else if let MatchEnum::AssertEqStruct((test_struct, test_struct2)) = match_enum\n    {\n        assert_eq(test_struct, test_struct2);\n    } else if let MatchEnum::AssertEqEnum((test_enum, test_enum2)) = match_enum\n    {\n        assert_eq(test_enum, test_enum2);\n    } else if let MatchEnum::AssertNePrimitive((a, b)) = match_enum {\n        assert_ne(a, b);\n    } else if let MatchEnum::AssertNeStruct((test_struct, test_struct2)) = match_enum\n    {\n        assert_ne(test_struct, test_struct2);\n    } else if let MatchEnum::AssertNeEnum((test_enum, test_enum2)) = match_enum\n    {\n        assert_ne(test_enum, test_enum2);\n    }\n}\n"
  },
  {
    "path": "e2e/sway/scripts/script_blobs/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"script_blobs\"\n"
  },
  {
    "path": "e2e/sway/scripts/script_blobs/src/main.sw",
    "content": "script;\n\nconfigurable {\n    SECRET_NUMBER: u64 = 9000,\n}\n\nenum MyEnum {\n    A: u64,\n    B: u8,\n    C: (),\n}\n\nstruct MyStruct {\n    field_a: MyEnum,\n    field_b: b256,\n}\n\nfn main(arg1: MyStruct) -> u64 {\n    assert_eq(SECRET_NUMBER, 10001);\n\n    match arg1.field_a {\n        MyEnum::B(value) => {\n            assert_eq(value, 99);\n        }\n        _ => {\n            assert(false)\n        }\n    }\n\n    assert_eq(\n        arg1.field_b,\n        0x1111111111111111111111111111111111111111111111111111111111111111,\n    );\n\n    return SECRET_NUMBER;\n}\n"
  },
  {
    "path": "e2e/sway/scripts/script_configurables/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"script_configurables\"\n"
  },
  {
    "path": "e2e/sway/scripts/script_configurables/src/main.sw",
    "content": "script;\n\n#[allow(dead_code)]\nenum EnumWithGeneric<D> {\n    VariantOne: D,\n    VariantTwo: (),\n}\n\nstruct StructWithGeneric<D> {\n    field_1: D,\n    field_2: u64,\n}\n\nconfigurable {\n    BOOL: bool = true,\n    U8: u8 = 8,\n    U16: u16 = 16,\n    U32: u32 = 32,\n    U64: u64 = 63,\n    U256: u256 = 0x0000000000000000000000000000000000000000000000000000000000000008u256,\n    B256: b256 = 0x0101010101010101010101010101010101010101010101010101010101010101,\n    STR_4: str[4] = __to_str_array(\"fuel\"),\n    TUPLE: (u8, bool) = (8, true),\n    ARRAY: [u32; 3] = [253, 254, 255],\n    STRUCT: StructWithGeneric<u8> = StructWithGeneric {\n        field_1: 8,\n        field_2: 16,\n    },\n    ENUM: EnumWithGeneric<bool> = EnumWithGeneric::VariantOne(true),\n}\n//U128: u128 = 128, //TODO: add once https://github.com/FuelLabs/sway/issues/5356 is done\n\nfn main() -> (bool, u8, u16, u32, u64, u256, b256, str[4], (u8, bool), [u32; 3], StructWithGeneric<u8>, EnumWithGeneric<bool>) {\n    (BOOL, U8, U16, U32, U64, U256, B256, STR_4, TUPLE, ARRAY, STRUCT, ENUM)\n}\n"
  },
  {
    "path": "e2e/sway/scripts/script_enum/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"script_enum\"\n"
  },
  {
    "path": "e2e/sway/scripts/script_enum/src/main.sw",
    "content": "script;\n\n#[allow(dead_code)]\nenum MyEnum {\n    One: (),\n    Two: (),\n    Three: (),\n}\n\nfn main(my_enum: MyEnum) -> u64 {\n    match my_enum {\n        MyEnum::One => 1,\n        MyEnum::Two => 2,\n        MyEnum::Three => 3,\n    }\n}\n"
  },
  {
    "path": "e2e/sway/scripts/script_needs_custom_decoder/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"script_needs_custom_decoder\"\n\n[dependencies]\n"
  },
  {
    "path": "e2e/sway/scripts/script_needs_custom_decoder/src/main.sw",
    "content": "script;\n\nimpl AbiEncode for [u8; 1000] {\n    #[allow(dead_code)]\n    fn abi_encode(self, buffer: Buffer) -> Buffer {\n        let mut buffer = buffer;\n        let mut i = 0;\n        while i < 1000 {\n            buffer = self[i].abi_encode(buffer);\n            i += 1;\n        };\n\n        buffer\n    }\n}\n\nfn main(log_instead_of_return: bool) -> Option<[u8; 1000]> {\n    let arr: [u8; 1000] = [0; 1000];\n\n    if log_instead_of_return {\n        log(arr);\n\n        return None;\n    }\n\n    Some(arr)\n}\n"
  },
  {
    "path": "e2e/sway/scripts/script_proxy/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"script_proxy\"\n"
  },
  {
    "path": "e2e/sway/scripts/script_proxy/src/main.sw",
    "content": "script;\n\nabi Proxy {\n    #[storage(write)]\n    fn set_target_contract(id: ContractId);\n\n    // methods of the `huge_contract` in our e2e sway contracts\n    #[storage(read)]\n    fn something() -> u64;\n\n    #[storage(read)]\n    fn write_some_u64(some: u64);\n\n    #[storage(read)]\n    fn read_some_u64() -> u64;\n}\n\nfn main(proxy_contract_id: ContractId) -> bool {\n    let proxy_instance = abi(Proxy, proxy_contract_id.into());\n    let _ = proxy_instance.something();\n    proxy_instance.write_some_u64(10001);\n    let read_u_64 = proxy_instance.read_some_u64();\n    return read_u_64 == 10001;\n}\n"
  },
  {
    "path": "e2e/sway/scripts/script_struct/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"script_struct\"\n"
  },
  {
    "path": "e2e/sway/scripts/script_struct/src/main.sw",
    "content": "script;\n\nconfigurable {\n    MY_STRUCT: MyStruct = MyStruct {\n        number: 10,\n        boolean: true,\n    },\n    A_NUMBER: u64 = 11,\n}\n\nstruct MyStruct {\n    number: u64,\n    boolean: bool,\n}\n\nfn main(arg: MyStruct) -> u64 {\n    let _calc = MY_STRUCT.number + A_NUMBER;\n    if arg.boolean { arg.number } else { 0 }\n}\n"
  },
  {
    "path": "e2e/sway/scripts/script_tx_input_output/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"script_tx_input_output\"\n"
  },
  {
    "path": "e2e/sway/scripts/script_tx_input_output/src/main.sw",
    "content": "script;\n\nuse std::{inputs::*, outputs::*};\n\nconfigurable {\n    ASSET_ID: AssetId = AssetId::zero(),\n    OWNER: Address = Address::zero(),\n}\n\nfn main(input_index: u64, output_index: u64) {\n    // Checks if coin and maybe returns owner\n    if let Some(owner) = input_coin_owner(input_index) {\n        require(owner == OWNER, \"wrong owner\");\n\n        let asset_id = input_asset_id(input_index).unwrap();\n        require(asset_id == ASSET_ID, \"wrong asset id\");\n    } else {\n        revert_with_log(\"input is not a coin\");\n    }\n\n    if let Some(Output::Change) = output_type(output_index) {\n        let asset_to = output_asset_to(output_index).unwrap();\n        require(asset_to == OWNER, \"wrong change address\");\n    } else {\n        revert_with_log(\"output is not change\");\n    }\n}\n"
  },
  {
    "path": "e2e/sway/scripts/transfer_script/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"transfer_script\"\n"
  },
  {
    "path": "e2e/sway/scripts/transfer_script/src/main.sw",
    "content": "script;\n\nuse std::asset::transfer;\n\nfn main(amount: u64, asset: AssetId, receiver: Identity) -> () {\n    transfer(receiver, asset, amount);\n}\n"
  },
  {
    "path": "e2e/sway/types/contracts/b256/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"b256\"\n"
  },
  {
    "path": "e2e/sway/types/contracts/b256/src/main.sw",
    "content": "contract;\n\nabi MyContract {\n    fn b256_as_output() -> b256;\n    fn b256_as_input(foo: b256) -> bool;\n}\n\nimpl MyContract for Contract {\n    fn b256_as_output() -> b256 {\n        0x0202020202020202020202020202020202020202020202020202020202020202\n    }\n\n    fn b256_as_input(foo: b256) -> bool {\n        foo == 0x0101010101010101010101010101010101010101010101010101010101010101\n    }\n}\n"
  },
  {
    "path": "e2e/sway/types/contracts/b512/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"b512\"\n"
  },
  {
    "path": "e2e/sway/types/contracts/b512/src/main.sw",
    "content": "contract;\n\nuse std::b512::B512;\n\nconst HI_BITS = 0xbd0c9b8792876713afa8bff383eebf31c43437823ed761cc3600d0016de5110c;\nconst LO_BITS = 0x44ac566bd156b4fc71a4a4cb2655d3dd360c695edb17dc3b64d611e122fea23d;\nconst LO_BITS2 = 0x54ac566bd156b4fc71a4a4cb2655d3dd360c695edb17dc3b64d611e122fea23d;\n\nabi MyContract {\n    fn b512_as_output() -> B512;\n    fn b512_as_input(b512: B512) -> bool;\n}\n\nimpl MyContract for Contract {\n    fn b512_as_output() -> B512 {\n        B512::from((HI_BITS, LO_BITS))\n    }\n\n    fn b512_as_input(b512: B512) -> bool {\n        let expected_b512 = B512::from((HI_BITS, LO_BITS2));\n\n        b512 == expected_b512\n    }\n}\n"
  },
  {
    "path": "e2e/sway/types/contracts/bytes/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"bytes\"\n"
  },
  {
    "path": "e2e/sway/types/contracts/bytes/src/main.sw",
    "content": "contract;\n\nuse std::bytes::Bytes;\n\n#[allow(dead_code)]\nenum SomeEnum<T> {\n    First: bool,\n    Second: T,\n}\n\nstruct Wrapper<T> {\n    inner: T,\n    inner_enum: SomeEnum<Bytes>,\n}\n\nfn expected_bytes() -> Bytes {\n    let mut bytes = Bytes::new();\n\n    bytes.push(40u8);\n    bytes.push(41u8);\n    bytes.push(42u8);\n\n    bytes\n}\n\nabi MyContract {\n    fn accept_bytes(bytes: Bytes);\n    fn accept_nested_bytes(wrapper: Wrapper<Vec<Bytes>>);\n    fn return_bytes(len: u8) -> Bytes;\n}\n\nimpl MyContract for Contract {\n    fn accept_bytes(bytes: Bytes) {\n        require(\n            bytes == expected_bytes(),\n            \"given bytes didn't match the expected bytes\",\n        );\n    }\n\n    fn accept_nested_bytes(wrapper: Wrapper<Vec<Bytes>>) {\n        if let SomeEnum::Second(enum_bytes) = wrapper.inner_enum {\n            require(\n                enum_bytes == expected_bytes(),\n                \"wrapper.inner_enum didn't carry the expected bytes\",\n            );\n        } else {\n            require(false, \"enum was not of variant Second\");\n        }\n\n        let inner_vec = wrapper.inner;\n        require(\n            inner_vec\n                .len() == 2,\n            \"Expected wrapper.inner vector to have 2 elements\",\n        );\n        require(\n            inner_vec\n                .get(0)\n                .unwrap() == expected_bytes(),\n            \"wrapper.inner[0] didn't match expectation\",\n        );\n        require(\n            inner_vec\n                .get(1)\n                .unwrap() == expected_bytes(),\n            \"wrapper.inner[1] didn't match expectation\",\n        );\n    }\n\n    fn return_bytes(len: u8) -> Bytes {\n        let mut bytes = Bytes::new();\n        let mut i: u8 = 0;\n        while i < len {\n            bytes.push(i);\n            i += 1u8;\n        }\n        bytes\n    }\n}\n"
  },
  {
    "path": "e2e/sway/types/contracts/call_empty_return/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"call_empty_return\"\n"
  },
  {
    "path": "e2e/sway/types/contracts/call_empty_return/src/main.sw",
    "content": "contract;\n\nuse std::storage::storage_api::write;\n\nabi TestContract {\n    #[storage(write)]\n    fn store_value(val: u64);\n}\n\nconst COUNTER_KEY = 0x0000000000000000000000000000000000000000000000000000000000000000;\n\nimpl TestContract for Contract {\n    #[storage(write)]\n    fn store_value(val: u64) {\n        write(COUNTER_KEY, 0, val);\n    }\n}\n"
  },
  {
    "path": "e2e/sway/types/contracts/complex_types_contract/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"complex_types_contract\"\n"
  },
  {
    "path": "e2e/sway/types/contracts/complex_types_contract/src/main.sw",
    "content": "contract;\n\nuse std::storage::storage_api::{read, write};\n\nstruct EmptyStruct {}\n\n#[allow(dead_code)]\nstruct CounterConfig {\n    dummy: bool,\n    initial_value: u64,\n}\n\nabi TestContract {\n    #[storage(write)]\n    fn initialize_counter(config: CounterConfig) -> u64;\n    #[storage(read, write)]\n    fn increment_counter(amount: u64) -> u64;\n    fn get_empty_struct() -> EmptyStruct;\n    fn input_empty_struct(es: EmptyStruct) -> bool;\n}\n\nconst COUNTER_KEY = 0x0000000000000000000000000000000000000000000000000000000000000000;\n\nimpl TestContract for Contract {\n    #[storage(write)]\n    fn initialize_counter(config: CounterConfig) -> u64 {\n        let value = config.initial_value;\n        write(COUNTER_KEY, 0, value);\n        value\n    }\n\n    #[storage(read, write)]\n    fn increment_counter(amount: u64) -> u64 {\n        let value = read::<u64>(COUNTER_KEY, 0).unwrap_or(0) + amount;\n        write(COUNTER_KEY, 0, value);\n        value\n    }\n\n    fn get_empty_struct() -> EmptyStruct {\n        EmptyStruct {}\n    }\n\n    fn input_empty_struct(es: EmptyStruct) -> bool {\n        let EmptyStruct {} = es;\n\n        true\n    }\n}\n"
  },
  {
    "path": "e2e/sway/types/contracts/contract_output_test/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"contract_output_test\"\n"
  },
  {
    "path": "e2e/sway/types/contracts/contract_output_test/src/main.sw",
    "content": "contract;\n\nstruct MyStruct {\n    foo: u8,\n    bar: bool,\n}\n\nabi TestContract {\n    fn is_even(value: u64) -> bool;\n    fn return_my_string(value: str[4]) -> str[4];\n    fn return_my_struct(value: MyStruct) -> MyStruct;\n}\n\nimpl TestContract for Contract {\n    fn is_even(value: u64) -> bool {\n        if (value / 2) * 2 == value {\n            true\n        } else {\n            false\n        }\n    }\n\n    fn return_my_string(value: str[4]) -> str[4] {\n        value\n    }\n\n    fn return_my_struct(value: MyStruct) -> MyStruct {\n        value\n    }\n}\n"
  },
  {
    "path": "e2e/sway/types/contracts/empty_arguments/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"empty_arguments\"\n"
  },
  {
    "path": "e2e/sway/types/contracts/empty_arguments/src/main.sw",
    "content": "contract;\n\nabi TestContract {\n    fn method_with_empty_argument() -> u64;\n}\n\nimpl TestContract for Contract {\n    fn method_with_empty_argument() -> u64 {\n        63\n    }\n}\n"
  },
  {
    "path": "e2e/sway/types/contracts/enum_as_input/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"enum_as_input\"\n"
  },
  {
    "path": "e2e/sway/types/contracts/enum_as_input/src/main.sw",
    "content": "contract;\n\n#[allow(dead_code)]\nenum StandardEnum {\n    One: b256,\n    Two: u32,\n    Three: bool,\n}\n\n#[allow(dead_code)]\nenum UnitEnum {\n    One: (),\n    Two: (),\n    Three: (),\n}\n\n#[allow(dead_code)]\nenum MaxedOutVariantsEnum {\n    Variant0: u8,\n    Variant1: u8,\n    Variant2: u8,\n    Variant3: u8,\n    Variant4: u8,\n    Variant5: u8,\n    Variant6: u8,\n    Variant7: u8,\n    Variant8: u8,\n    Variant9: u8,\n    Variant10: u8,\n    Variant11: u8,\n    Variant12: u8,\n    Variant13: u8,\n    Variant14: u8,\n    Variant15: u8,\n    Variant16: u8,\n    Variant17: u8,\n    Variant18: u8,\n    Variant19: u8,\n    Variant20: u8,\n    Variant21: u8,\n    Variant22: u8,\n    Variant23: u8,\n    Variant24: u8,\n    Variant25: u8,\n    Variant26: u8,\n    Variant27: u8,\n    Variant28: u8,\n    Variant29: u8,\n    Variant30: u8,\n    Variant31: u8,\n    Variant32: u8,\n    Variant33: u8,\n    Variant34: u8,\n    Variant35: u8,\n    Variant36: u8,\n    Variant37: u8,\n    Variant38: u8,\n    Variant39: u8,\n    Variant40: u8,\n    Variant41: u8,\n    Variant42: u8,\n    Variant43: u8,\n    Variant44: u8,\n    Variant45: u8,\n    Variant46: u8,\n    Variant47: u8,\n    Variant48: u8,\n    Variant49: u8,\n    Variant50: u8,\n    Variant51: u8,\n    Variant52: u8,\n    Variant53: u8,\n    Variant54: u8,\n    Variant55: u8,\n    Variant56: u8,\n    Variant57: u8,\n    Variant58: u8,\n    Variant59: u8,\n    Variant60: u8,\n    Variant61: u8,\n    Variant62: u8,\n    Variant63: u8,\n    Variant64: u8,\n    Variant65: u8,\n    Variant66: u8,\n    Variant67: u8,\n    Variant68: u8,\n    Variant69: u8,\n    Variant70: u8,\n    Variant71: u8,\n    Variant72: u8,\n    Variant73: u8,\n    Variant74: u8,\n    Variant75: u8,\n    Variant76: u8,\n    Variant77: u8,\n    Variant78: u8,\n    Variant79: u8,\n    Variant80: u8,\n    Variant81: u8,\n    Variant82: u8,\n    Variant83: u8,\n    Variant84: u8,\n    Variant85: u8,\n    Variant86: u8,\n    Variant87: u8,\n    Variant88: u8,\n    Variant89: u8,\n    Variant90: u8,\n    Variant91: u8,\n    Variant92: u8,\n    Variant93: u8,\n    Variant94: u8,\n    Variant95: u8,\n    Variant96: u8,\n    Variant97: u8,\n    Variant98: u8,\n    Variant99: u8,\n    Variant100: u8,\n    Variant101: u8,\n    Variant102: u8,\n    Variant103: u8,\n    Variant104: u8,\n    Variant105: u8,\n    Variant106: u8,\n    Variant107: u8,\n    Variant108: u8,\n    Variant109: u8,\n    Variant110: u8,\n    Variant111: u8,\n    Variant112: u8,\n    Variant113: u8,\n    Variant114: u8,\n    Variant115: u8,\n    Variant116: u8,\n    Variant117: u8,\n    Variant118: u8,\n    Variant119: u8,\n    Variant120: u8,\n    Variant121: u8,\n    Variant122: u8,\n    Variant123: u8,\n    Variant124: u8,\n    Variant125: u8,\n    Variant126: u8,\n    Variant127: u8,\n    Variant128: u8,\n    Variant129: u8,\n    Variant130: u8,\n    Variant131: u8,\n    Variant132: u8,\n    Variant133: u8,\n    Variant134: u8,\n    Variant135: u8,\n    Variant136: u8,\n    Variant137: u8,\n    Variant138: u8,\n    Variant139: u8,\n    Variant140: u8,\n    Variant141: u8,\n    Variant142: u8,\n    Variant143: u8,\n    Variant144: u8,\n    Variant145: u8,\n    Variant146: u8,\n    Variant147: u8,\n    Variant148: u8,\n    Variant149: u8,\n    Variant150: u8,\n    Variant151: u8,\n    Variant152: u8,\n    Variant153: u8,\n    Variant154: u8,\n    Variant155: u8,\n    Variant156: u8,\n    Variant157: u8,\n    Variant158: u8,\n    Variant159: u8,\n    Variant160: u8,\n    Variant161: u8,\n    Variant162: u8,\n    Variant163: u8,\n    Variant164: u8,\n    Variant165: u8,\n    Variant166: u8,\n    Variant167: u8,\n    Variant168: u8,\n    Variant169: u8,\n    Variant170: u8,\n    Variant171: u8,\n    Variant172: u8,\n    Variant173: u8,\n    Variant174: u8,\n    Variant175: u8,\n    Variant176: u8,\n    Variant177: u8,\n    Variant178: u8,\n    Variant179: u8,\n    Variant180: u8,\n    Variant181: u8,\n    Variant182: u8,\n    Variant183: u8,\n    Variant184: u8,\n    Variant185: u8,\n    Variant186: u8,\n    Variant187: u8,\n    Variant188: u8,\n    Variant189: u8,\n    Variant190: u8,\n    Variant191: u8,\n    Variant192: u8,\n    Variant193: u8,\n    Variant194: u8,\n    Variant195: u8,\n    Variant196: u8,\n    Variant197: u8,\n    Variant198: u8,\n    Variant199: u8,\n    Variant200: u8,\n    Variant201: u8,\n    Variant202: u8,\n    Variant203: u8,\n    Variant204: u8,\n    Variant205: u8,\n    Variant206: u8,\n    Variant207: u8,\n    Variant208: u8,\n    Variant209: u8,\n    Variant210: u8,\n    Variant211: u8,\n    Variant212: u8,\n    Variant213: u8,\n    Variant214: u8,\n    Variant215: u8,\n    Variant216: u8,\n    Variant217: u8,\n    Variant218: u8,\n    Variant219: u8,\n    Variant220: u8,\n    Variant221: u8,\n    Variant222: u8,\n    Variant223: u8,\n    Variant224: u8,\n    Variant225: u8,\n    Variant226: u8,\n    Variant227: u8,\n    Variant228: u8,\n    Variant229: u8,\n    Variant230: u8,\n    Variant231: u8,\n    Variant232: u8,\n    Variant233: u8,\n    Variant234: u8,\n    Variant235: u8,\n    Variant236: u8,\n    Variant237: u8,\n    Variant238: u8,\n    Variant239: u8,\n    Variant240: u8,\n    Variant241: u8,\n    Variant242: u8,\n    Variant243: u8,\n    Variant244: u8,\n    Variant245: u8,\n    Variant246: u8,\n    Variant247: u8,\n    Variant248: u8,\n    Variant249: u8,\n    Variant250: u8,\n    Variant251: u8,\n    Variant252: u8,\n    Variant253: u8,\n    Variant254: u8,\n    Variant255: u8,\n}\n\nabi EnumTesting {\n    fn get_standard_enum() -> StandardEnum;\n\n    fn check_standard_enum_integrity(arg: StandardEnum) -> bool;\n    fn get_max_variant() -> MaxedOutVariantsEnum;\n\n    fn get_unit_enum() -> UnitEnum;\n    fn check_unit_enum_integrity(arg: UnitEnum) -> bool;\n}\n\nimpl EnumTesting for Contract {\n    fn get_standard_enum() -> StandardEnum {\n        StandardEnum::Two(12345u32)\n    }\n    fn check_standard_enum_integrity(arg: StandardEnum) -> bool {\n        match arg {\n            StandardEnum::Two(value) => {\n                value == 12345u32\n            },\n            _ => {\n                false\n            }\n        }\n    }\n\n    fn get_max_variant() -> MaxedOutVariantsEnum {\n        MaxedOutVariantsEnum::Variant255(11)\n    }\n\n    fn get_unit_enum() -> UnitEnum {\n        UnitEnum::Two\n    }\n    fn check_unit_enum_integrity(arg: UnitEnum) -> bool {\n        match arg {\n            UnitEnum::Two => {\n                true\n            },\n            _ => {\n                false\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "e2e/sway/types/contracts/enum_encoding/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"enum_encoding\"\n"
  },
  {
    "path": "e2e/sway/types/contracts/enum_encoding/src/main.sw",
    "content": "contract;\n\n#[allow(dead_code)]\nenum EnumThatHasABigAndSmallVariant {\n    Big: b256,\n    Small: u32,\n}\n\nstruct BigBundle {\n    arg_1: EnumThatHasABigAndSmallVariant,\n    arg_2: u64,\n    arg_3: u64,\n    arg_4: u64,\n}\n\n#[allow(dead_code)]\nenum UnitEnum {\n    var1: (),\n    var2: (),\n}\n\nstruct UnitBundle {\n    arg_1: UnitEnum,\n    arg_2: u64,\n}\n\nabi EnumTesting {\n    fn get_big_bundle() -> BigBundle;\n    fn check_big_bundle_integrity(arg: BigBundle) -> bool;\n\n    fn get_unit_bundle() -> UnitBundle;\n    fn check_unit_bundle_integrity(arg: UnitBundle) -> bool;\n}\n\nimpl EnumTesting for Contract {\n    fn get_big_bundle() -> BigBundle {\n        let arg_1 = EnumThatHasABigAndSmallVariant::Small(12345u32);\n        let arg_2 = 6666;\n        let arg_3 = 7777;\n        let arg_4 = 8888;\n        BigBundle {\n            arg_1,\n            arg_2,\n            arg_3,\n            arg_4,\n        }\n    }\n    fn check_big_bundle_integrity(arg: BigBundle) -> bool {\n        let arg_1_is_correct = match arg.arg_1 {\n            EnumThatHasABigAndSmallVariant::Small(value) => {\n                value == 12345u32\n            },\n            _ => false,\n        };\n\n        arg_1_is_correct && arg.arg_2 == 6666 && arg.arg_3 == 7777 && arg.arg_4 == 8888\n    }\n\n    fn get_unit_bundle() -> UnitBundle {\n        UnitBundle {\n            arg_1: UnitEnum::var2,\n            arg_2: 18_446_744_073_709_551_615u64,\n        }\n    }\n    fn check_unit_bundle_integrity(arg: UnitBundle) -> bool {\n        let arg_1_is_correct = match arg.arg_1 {\n            UnitEnum::var2 => true,\n            _ => false,\n        };\n\n        arg_1_is_correct && arg.arg_2 == 18_446_744_073_709_551_615u64\n    }\n}\n"
  },
  {
    "path": "e2e/sway/types/contracts/enum_inside_struct/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"enum_inside_struct\"\n"
  },
  {
    "path": "e2e/sway/types/contracts/enum_inside_struct/src/main.sw",
    "content": "contract;\n\n#[allow(dead_code)]\nenum Shaker {\n    Cosmopolitan: u64,\n    Mojito: u64,\n}\n\nstruct Cocktail {\n    the_thing_you_mix_in: Shaker,\n    glass: u64,\n}\n\nabi TestContract {\n    fn return_enum_inside_struct(a: u64) -> Cocktail;\n    fn take_enum_inside_struct(c: Cocktail) -> u64;\n}\n\nimpl TestContract for Contract {\n    fn return_enum_inside_struct(a: u64) -> Cocktail {\n        Cocktail {\n            the_thing_you_mix_in: Shaker::Mojito(a),\n            glass: 333,\n        }\n    }\n\n    fn take_enum_inside_struct(c: Cocktail) -> u64 {\n        c.glass\n    }\n}\n"
  },
  {
    "path": "e2e/sway/types/contracts/evm_address/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"evm_address\"\n"
  },
  {
    "path": "e2e/sway/types/contracts/evm_address/src/main.sw",
    "content": "contract;\n\nuse std::vm::evm::evm_address::EvmAddress;\n\nabi EvmTest {\n    fn evm_address_as_input(evm_addr: EvmAddress) -> bool;\n    fn evm_address_from_literal() -> EvmAddress;\n    fn evm_address_from_argument(raw_address: b256) -> EvmAddress;\n}\n\nimpl EvmTest for Contract {\n    fn evm_address_as_input(evm_addr: EvmAddress) -> bool {\n        let evm_addr2 = EvmAddress::from(0x1616060606060606060606060606060606060606060606060606060606060606);\n\n        evm_addr == evm_addr2\n    }\n\n    fn evm_address_from_literal() -> EvmAddress {\n        EvmAddress::from(0x0606060606060606060606060606060606060606060606060606060606060606)\n    }\n\n    fn evm_address_from_argument(raw_address: b256) -> EvmAddress {\n        EvmAddress::from(raw_address)\n    }\n}\n"
  },
  {
    "path": "e2e/sway/types/contracts/generics/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"generics\"\n"
  },
  {
    "path": "e2e/sway/types/contracts/generics/src/main.sw",
    "content": "contract;\n\nuse std::hash::*;\n\n#[allow(dead_code)]\nstruct StructUnusedGeneric<T, K> {\n    field: u64,\n}\n\n#[allow(dead_code)]\nenum EnumUnusedGeneric<T, K> {\n    One: u64,\n}\n\nstruct StructTwoUnusedGenericParams<T, K> {}\n\n#[allow(dead_code)]\nenum EnumTwoUnusedGenericParams<T, K> {\n    One: (),\n}\n\nstruct StructUsedAndUnusedGenericParams<T, K, Z> {\n    field: K,\n}\n\n#[allow(dead_code)]\nenum EnumUsedAndUnusedGenericParams<T, K, Z> {\n    One: str[3],\n    Two: K,\n}\n\nstruct SimpleGeneric<T> {\n    single_generic_param: T,\n}\n\nstruct PassTheGenericOn<K> {\n    one: SimpleGeneric<K>,\n}\n\nstruct StructWArrayGeneric<L> {\n    a: [L; 2],\n}\n\nstruct StructWTupleGeneric<M> {\n    a: (M, M),\n}\n\n#[allow(dead_code)]\nenum EnumWGeneric<N> {\n    A: u64,\n    B: N,\n}\n\n#[allow(dead_code)]\nstruct StructWTwoGenerics<T, U> {\n    a: T,\n    b: U,\n}\n\nstruct StructWArrWGenericStruct<S> {\n    a: [StructWTwoGenerics<S, u8>; 3],\n}\n\n#[allow(dead_code)]\nstruct MegaExample<T, U> {\n    a: ([U; 2], T),\n    b: Vec<([EnumWGeneric<StructWTupleGeneric<StructWArrayGeneric<PassTheGenericOn<T>>>>; 1], u32)>,\n}\n\nabi MyContract {\n    fn unused_generic_args(\n        arg_1: StructUnusedGeneric<u64, u32>,\n        arg_2: EnumUnusedGeneric<u32, u32>,\n    );\n    fn two_unused_generic_args(\n        arg_1: StructTwoUnusedGenericParams<u32, u64>,\n        arg_2: EnumTwoUnusedGenericParams<u64, u32>,\n    );\n    fn used_and_unused_generic_args(\n        arg_1: StructUsedAndUnusedGenericParams<u32, u8, u64>,\n        arg_2: EnumUsedAndUnusedGenericParams<u64, u8, u32>,\n    ) -> (StructUsedAndUnusedGenericParams<u64, u8, u32>, EnumUsedAndUnusedGenericParams<u32, u8, u64>);\n    fn struct_w_generic(arg1: SimpleGeneric<u64>) -> SimpleGeneric<u64>;\n    fn struct_delegating_generic(arg1: PassTheGenericOn<str[3]>) -> PassTheGenericOn<str[3]>;\n    fn struct_w_generic_in_array(arg1: StructWArrayGeneric<u32>) -> StructWArrayGeneric<u32>;\n    fn struct_w_generic_in_tuple(arg1: StructWTupleGeneric<u32>) -> StructWTupleGeneric<u32>;\n\n    fn enum_w_generic(arg1: EnumWGeneric<u64>) -> EnumWGeneric<u64>;\n\n    fn complex_test(arg1: MegaExample<str[2], b256>);\n    fn array_with_generic_struct(\n        arg: StructWArrWGenericStruct<b256>,\n    ) -> StructWArrWGenericStruct<b256>;\n}\n\nimpl MyContract for Contract {\n    fn unused_generic_args(\n        _arg_1: StructUnusedGeneric<u64, u32>,\n        _arg_2: EnumUnusedGeneric<u32, u32>,\n    ) {}\n\n    fn two_unused_generic_args(\n        _arg_1: StructTwoUnusedGenericParams<u32, u64>,\n        _arg_2: EnumTwoUnusedGenericParams<u64, u32>,\n    ) {}\n\n    fn used_and_unused_generic_args(\n        arg_1: StructUsedAndUnusedGenericParams<u32, u8, u64>,\n        arg_2: EnumUsedAndUnusedGenericParams<u64, u8, u32>,\n    ) -> (StructUsedAndUnusedGenericParams<u64, u8, u32>, EnumUsedAndUnusedGenericParams<u32, u8, u64>) {\n        assert_eq(arg_1.field, 10u8);\n\n        if let EnumUsedAndUnusedGenericParams::Two(val) = arg_2 {\n            assert_eq(val, 11u8);\n        } else {\n            require(\n                false,\n                \"Expected the variant EnumUsedAndUnusedGenericParams::Two\",\n            );\n        }\n        (\n            StructUsedAndUnusedGenericParams { field: 12u8 },\n            EnumUsedAndUnusedGenericParams::Two(13u8),\n        )\n    }\n\n    fn struct_w_generic(arg1: SimpleGeneric<u64>) -> SimpleGeneric<u64> {\n        let expected = SimpleGeneric {\n            single_generic_param: 123u64,\n        };\n\n        assert(arg1.single_generic_param == expected.single_generic_param);\n\n        expected\n    }\n\n    fn struct_delegating_generic(arg1: PassTheGenericOn<str[3]>) -> PassTheGenericOn<str[3]> {\n        let expected = PassTheGenericOn {\n            one: SimpleGeneric {\n                single_generic_param: __to_str_array(\"abc\"),\n            },\n        };\n\n        assert(\n            sha256(from_str_array(expected.one.single_generic_param)) == sha256(from_str_array(arg1.one.single_generic_param)),\n        );\n\n        expected\n    }\n\n    fn struct_w_generic_in_array(arg1: StructWArrayGeneric<u32>) -> StructWArrayGeneric<u32> {\n        let expected = StructWArrayGeneric {\n            a: [1u32, 2u32],\n        };\n\n        assert(expected.a[0] == arg1.a[0]);\n        assert(expected.a[1] == arg1.a[1]);\n\n        expected\n    }\n\n    fn struct_w_generic_in_tuple(arg1: StructWTupleGeneric<u32>) -> StructWTupleGeneric<u32> {\n        let expected = StructWTupleGeneric {\n            a: (1u32, 2u32),\n        };\n        assert(expected.a.0 == arg1.a.0);\n        assert(expected.a.1 == arg1.a.1);\n\n        expected\n    }\n\n    fn enum_w_generic(arg1: EnumWGeneric<u64>) -> EnumWGeneric<u64> {\n        match arg1 {\n            EnumWGeneric::B(value) => {\n                assert(value == 10u64);\n            }\n            _ => {\n                assert(false)\n            }\n        }\n        EnumWGeneric::B(10)\n    }\n\n    fn complex_test(_arg: MegaExample<str[2], b256>) {}\n\n    fn array_with_generic_struct(\n        arg: StructWArrWGenericStruct<b256>,\n    ) -> StructWArrWGenericStruct<b256> {\n        arg\n    }\n}\n"
  },
  {
    "path": "e2e/sway/types/contracts/heap_type_in_enums/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"heap_type_in_enums\"\n\n[dependencies]\n"
  },
  {
    "path": "e2e/sway/types/contracts/heap_type_in_enums/src/main.sw",
    "content": "contract;\n\nuse std::bytes::Bytes;\nuse std::string::String;\n\npub enum TestError {\n    Something: [u8; 5],\n    Else: u64,\n}\n\npub struct Bimbam {\n    something: Bytes,\n}\n\nabi MyContract {\n    fn returns_bytes_result(return_ok: bool) -> Result<Bytes, TestError>;\n    fn returns_vec_result(return_ok: bool) -> Result<Vec<u64>, TestError>;\n    fn returns_string_result(return_ok: bool) -> Result<String, TestError>;\n    fn returns_str_result(return_ok: bool) -> Result<str, TestError>;\n    fn returns_bytes_option(return_some: bool) -> Option<Bytes>;\n    fn returns_vec_option(return_some: bool) -> Option<Vec<u64>>;\n    fn returns_string_option(return_some: bool) -> Option<String>;\n    fn returns_str_option(return_some: bool) -> Option<str>;\n    fn would_raise_a_memory_overflow() -> Result<Bytes, b256>;\n    fn returns_a_heap_type_too_deep() -> Result<Bimbam, u64>;\n}\n\nimpl MyContract for Contract {\n    fn returns_bytes_result(return_ok: bool) -> Result<Bytes, TestError> {\n        return if return_ok {\n            let mut b = Bytes::new();\n            b.push(1u8);\n            b.push(1u8);\n            b.push(1u8);\n            b.push(1u8);\n            Result::Ok(b)\n        } else {\n            Result::Err(TestError::Something([255u8, 255u8, 255u8, 255u8, 255u8]))\n        }\n    }\n\n    fn returns_vec_result(return_ok: bool) -> Result<Vec<u64>, TestError> {\n        return if return_ok {\n            let mut v = Vec::new();\n            v.push(2);\n            v.push(2);\n            v.push(2);\n            v.push(2);\n            v.push(2);\n            Result::Ok(v)\n        } else {\n            Result::Err(TestError::Else(7777))\n        }\n    }\n\n    fn returns_string_result(return_ok: bool) -> Result<String, TestError> {\n        return if return_ok {\n            let s = String::from_ascii_str(\"Hello World\");\n            Result::Ok(s)\n        } else {\n            Result::Err(TestError::Else(3333))\n        }\n    }\n\n    fn returns_str_result(return_ok: bool) -> Result<str, TestError> {\n        return if return_ok {\n            Result::Ok(\"Hello World\")\n        } else {\n            Result::Err(TestError::Else(3333))\n        }\n    }\n\n    fn returns_bytes_option(return_some: bool) -> Option<Bytes> {\n        return if return_some {\n            let mut b = Bytes::new();\n            b.push(1u8);\n            b.push(1u8);\n            b.push(1u8);\n            b.push(1u8);\n            Option::Some(b)\n        } else {\n            Option::None\n        }\n    }\n\n    fn returns_vec_option(return_some: bool) -> Option<Vec<u64>> {\n        return if return_some {\n            let mut v = Vec::new();\n            v.push(2);\n            v.push(2);\n            v.push(2);\n            v.push(2);\n            v.push(2);\n            Option::Some(v)\n        } else {\n            None\n        }\n    }\n\n    fn returns_string_option(return_some: bool) -> Option<String> {\n        return if return_some {\n            let s = String::from_ascii_str(\"Hello World\");\n            Option::Some(s)\n        } else {\n            None\n        }\n    }\n\n    fn returns_str_option(return_some: bool) -> Option<str> {\n        return if return_some {\n            Option::Some(\"Hello World\")\n        } else {\n            None\n        }\n    }\n\n    fn would_raise_a_memory_overflow() -> Result<Bytes, b256> {\n        Result::Err(0x1111111111111111111111111111111111111111111111111111111111111111)\n    }\n\n    fn returns_a_heap_type_too_deep() -> Result<Bimbam, u64> {\n        let mut b = Bytes::new();\n        b.push(2u8);\n        b.push(2u8);\n        b.push(2u8);\n        Result::Ok(Bimbam { something: b })\n    }\n}\n"
  },
  {
    "path": "e2e/sway/types/contracts/heap_types/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"heap_types\"\n"
  },
  {
    "path": "e2e/sway/types/contracts/heap_types/src/main.sw",
    "content": "contract;\n\nuse std::bytes::Bytes;\nuse std::string::String;\n\n#[allow(dead_code)]\nstruct StructGenerics<T, K, U> {\n    one: T,\n    two: K,\n    three: U,\n}\n\n#[allow(dead_code)]\nenum EnumGeneric<H, I> {\n    One: H,\n    Two: I,\n}\n\nabi HeapTypesContract {\n    fn nested_heap_types() -> EnumGeneric<Vec<StructGenerics<Bytes, String, raw_slice>>, String>;\n}\n\nimpl HeapTypesContract for Contract {\n    fn nested_heap_types() -> EnumGeneric<Vec<StructGenerics<Bytes, String, raw_slice>>, String> {\n        let mut some_vec = Vec::new();\n        some_vec.push(2u8);\n        some_vec.push(4u8);\n        some_vec.push(8u8);\n\n        let struct_generics = StructGenerics {\n            one: Bytes::from(some_vec),\n            two: String::from_ascii_str(\"fuel\"),\n            three: some_vec.as_raw_slice(),\n        };\n\n        let mut enum_vec = Vec::new();\n        enum_vec.push(struct_generics);\n        enum_vec.push(struct_generics);\n\n        EnumGeneric::One(enum_vec)\n    }\n}\n"
  },
  {
    "path": "e2e/sway/types/contracts/identity/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"identity\"\n"
  },
  {
    "path": "e2e/sway/types/contracts/identity/src/main.sw",
    "content": "contract;\n\nstruct TestStruct {\n    identity: Identity,\n}\n\n#[allow(dead_code)]\nenum TestEnum {\n    EnumIdentity: Identity,\n    OtherValue: bool,\n}\n\nconst ADDR = 0xd58573593432a30a800f97ad32f877425c223a9e427ab557aab5d5bb89156db0;\n\nabi MyContract {\n    fn get_identity_address() -> Identity;\n    fn get_identity_contract_id() -> Identity;\n    fn get_struct_with_identity() -> TestStruct;\n    fn get_enum_with_identity() -> TestEnum;\n    fn get_identity_tuple() -> (TestStruct, TestEnum);\n    fn input_identity(i: Identity) -> bool;\n    fn input_struct_with_identity(s: TestStruct) -> bool;\n    fn input_enum_with_identity(s: TestEnum) -> bool;\n}\n\nimpl MyContract for Contract {\n    fn get_identity_address() -> Identity {\n        Identity::Address(Address::from(ADDR))\n    }\n\n    fn get_identity_contract_id() -> Identity {\n        Identity::ContractId(ContractId::from(ADDR))\n    }\n\n    fn get_struct_with_identity() -> TestStruct {\n        TestStruct {\n            identity: Identity::Address(Address::from(ADDR)),\n        }\n    }\n\n    fn get_enum_with_identity() -> TestEnum {\n        TestEnum::EnumIdentity(Identity::ContractId(ContractId::from(ADDR)))\n    }\n\n    fn get_identity_tuple() -> (TestStruct, TestEnum) {\n        let s = TestStruct {\n            identity: Identity::Address(Address::from(ADDR)),\n        };\n        let e = TestEnum::EnumIdentity(Identity::ContractId(ContractId::from(ADDR)));\n        (s, e)\n    }\n\n    fn input_identity(input: Identity) -> bool {\n        if let Identity::Address(a) = input {\n            return a == Address::from(ADDR);\n        }\n        false\n    }\n\n    fn input_struct_with_identity(input: TestStruct) -> bool {\n        if let Identity::Address(a) = input.identity {\n            return a == Address::from(ADDR);\n        }\n        false\n    }\n\n    fn input_enum_with_identity(input: TestEnum) -> bool {\n        if let TestEnum::EnumIdentity(identity) = input {\n            if let Identity::ContractId(c) = identity {\n                return c == ContractId::from(ADDR);\n            }\n        }\n        false\n    }\n}\n"
  },
  {
    "path": "e2e/sway/types/contracts/native_types/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"native_types\"\n"
  },
  {
    "path": "e2e/sway/types/contracts/native_types/src/main.sw",
    "content": "contract;\n\nstruct User {\n    address: Address,\n    weight: u64,\n}\n\nabi MyContract {\n    fn wrapped_address(user: User) -> User;\n    fn unwrapped_address(addr: Address) -> Address;\n}\n\nimpl MyContract for Contract {\n    fn wrapped_address(user: User) -> User {\n        user\n    }\n\n    fn unwrapped_address(addr: Address) -> Address {\n        addr\n    }\n}\n"
  },
  {
    "path": "e2e/sway/types/contracts/nested_structs/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"nested_structs\"\n"
  },
  {
    "path": "e2e/sway/types/contracts/nested_structs/src/main.sw",
    "content": "contract;\n\npub struct SomeStruct {\n    field: u32,\n    field_2: bool,\n}\n\npub struct AllStruct {\n    some_struct: SomeStruct,\n}\n\npub struct CallData {\n    memory_address: MemoryAddress,\n    num_coins_to_forward: u64,\n    asset_id_of_coins_to_forward: ContractId,\n    amount_of_gas_to_forward: u64,\n}\n\n#[allow(dead_code)]\nstruct MemoryAddress {\n    contract_id: ContractId,\n    function_selector: u64,\n    function_data: u64,\n}\n\nabi MyContract {\n    fn get_struct() -> AllStruct;\n    #[payable]\n    fn check_struct_integrity(arg: AllStruct) -> bool;\n    #[payable]\n    fn i_am_called_differently(_arg1: AllStruct, _arg2: MemoryAddress);\n    fn nested_struct_with_reserved_keyword_substring(call_data: CallData) -> CallData;\n}\n\nimpl MyContract for Contract {\n    fn get_struct() -> AllStruct {\n        AllStruct {\n            some_struct: SomeStruct {\n                field: 12345u32,\n                field_2: true,\n            },\n        }\n    }\n\n    #[payable]\n    fn check_struct_integrity(arg: AllStruct) -> bool {\n        arg.some_struct.field == 12345u32 && arg.some_struct.field_2 == true\n    }\n\n    #[payable]\n    fn i_am_called_differently(_arg1: AllStruct, _arg2: MemoryAddress) {}\n\n    fn nested_struct_with_reserved_keyword_substring(call_data: CallData) -> CallData {\n        call_data\n    }\n}\n"
  },
  {
    "path": "e2e/sway/types/contracts/options/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"options\"\n"
  },
  {
    "path": "e2e/sway/types/contracts/options/src/main.sw",
    "content": "contract;\n\nstruct TestStruct {\n    option: Option<Address>,\n}\n\n#[allow(dead_code)]\nenum TestEnum {\n    EnumOption: Option<Address>,\n    OtherValue: bool,\n}\n\nconst ADDR = 0xd58573593432a30a800f97ad32f877425c223a9e427ab557aab5d5bb89156db0;\n\nabi MyContract {\n    fn get_some_u64() -> Option<u64>;\n    fn get_some_address() -> Option<Address>;\n    fn get_some_struct() -> Option<TestStruct>;\n    fn get_some_enum() -> Option<TestEnum>;\n    fn get_some_tuple() -> Option<(TestStruct, TestEnum)>;\n    fn get_none() -> Option<Address>;\n    fn input_primitive(s: Option<u64>) -> bool;\n    fn input_struct(s: Option<TestStruct>) -> bool;\n    fn input_enum(e: Option<TestEnum>) -> bool;\n    fn input_none(none: Option<Address>) -> bool;\n}\n\nimpl MyContract for Contract {\n    fn get_some_u64() -> Option<u64> {\n        Option::Some(10)\n    }\n\n    fn get_some_address() -> Option<Address> {\n        Option::Some(Address::from(ADDR))\n    }\n\n    fn get_some_struct() -> Option<TestStruct> {\n        Option::Some(TestStruct {\n            option: Option::Some(Address::from(ADDR)),\n        })\n    }\n\n    fn get_some_enum() -> Option<TestEnum> {\n        Option::Some(TestEnum::EnumOption(Option::Some(Address::from(ADDR))))\n    }\n\n    fn get_some_tuple() -> Option<(TestStruct, TestEnum)> {\n        let s = TestStruct {\n            option: Option::Some(Address::from(ADDR)),\n        };\n        let e = TestEnum::EnumOption(Option::Some(Address::from(ADDR)));\n        Option::Some((s, e))\n    }\n\n    fn get_none() -> Option<Address> {\n        Option::None\n    }\n\n    fn input_primitive(input: Option<u64>) -> bool {\n        if let Option::Some(u) = input {\n            return u == 36;\n        }\n        false\n    }\n\n    fn input_struct(input: Option<TestStruct>) -> bool {\n        if let Option::Some(s) = input {\n            if let Option::Some(a) = s.option {\n                return a == Address::from(ADDR);\n            }\n        }\n        false\n    }\n\n    fn input_enum(input: Option<TestEnum>) -> bool {\n        if let Option::Some(test_enum) = input {\n            if let TestEnum::EnumOption(option) = test_enum {\n                if let Option::Some(a) = option {\n                    return a == Address::from(ADDR);\n                }\n            }\n        }\n        false\n    }\n\n    fn input_none(none: Option<Address>) -> bool {\n        if let Option::None = none {\n            return true;\n        }\n        false\n    }\n}\n"
  },
  {
    "path": "e2e/sway/types/contracts/raw_slice/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"raw_slice\"\n"
  },
  {
    "path": "e2e/sway/types/contracts/raw_slice/src/main.sw",
    "content": "contract;\n\n#[allow(dead_code)]\nenum SomeEnum<T> {\n    First: bool,\n    Second: T,\n}\n\nstruct Wrapper<T> {\n    inner: T,\n    inner_enum: SomeEnum<raw_slice>,\n}\n\nabi RawSliceContract {\n    fn return_raw_slice(length: u8) -> raw_slice;\n    fn accept_raw_slice(slice: raw_slice);\n    fn accept_nested_raw_slice(wrapper: Wrapper<Vec<raw_slice>>);\n}\n\nfn validate_raw_slice(input: raw_slice) {\n    let vec: Vec<u8> = Vec::from(input);\n    require(vec.len() == 3, \"raw slice len is not 3\");\n    require(\n        vec\n            .get(2)\n            .unwrap() == 42,\n        \"expected 3rd slice entry to be 42\",\n    );\n    require(\n        vec\n            .get(1)\n            .unwrap() == 41,\n        \"expected 2nd slice entry to be 41\",\n    );\n    require(\n        vec\n            .get(0)\n            .unwrap() == 40,\n        \"expected 1st slice entry to be 40\",\n    );\n}\n\nfn validate_vec(vec: Vec<raw_slice>) {\n    require(vec.len() == 2, \"vec should have two elements\");\n    validate_raw_slice(vec.get(0).unwrap());\n    validate_raw_slice(vec.get(1).unwrap());\n}\n\nimpl RawSliceContract for Contract {\n    fn return_raw_slice(length: u8) -> raw_slice {\n        let mut vec = Vec::new();\n        let mut counter = 0u8;\n        while counter < length {\n            vec.push(counter);\n            counter = counter + 1;\n        }\n        vec.as_raw_slice()\n    }\n\n    fn accept_raw_slice(slice: raw_slice) {\n        validate_raw_slice(slice);\n    }\n\n    fn accept_nested_raw_slice(wrapper: Wrapper<Vec<raw_slice>>) {\n        if let SomeEnum::Second(enum_raw_slice) = wrapper.inner_enum\n        {\n            validate_raw_slice(enum_raw_slice);\n        } else {\n            require(false, \"enum was not of variant Second\");\n        }\n\n        validate_vec(wrapper.inner);\n    }\n}\n"
  },
  {
    "path": "e2e/sway/types/contracts/results/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"results\"\n"
  },
  {
    "path": "e2e/sway/types/contracts/results/src/main.sw",
    "content": "contract;\n\nstruct TestStruct {\n    option: Option<Address>,\n}\n\nenum TestEnum {\n    EnumOption: Option<Address>,\n}\n\npub enum TestError {\n    NoAddress: str[5],\n    OtherError: (),\n}\n\nconst ADDR = 0xd58573593432a30a800f97ad32f877425c223a9e427ab557aab5d5bb89156db0;\n\nabi MyContract {\n    fn get_ok_u64() -> Result<u64, TestError>;\n    fn get_ok_address() -> Result<Address, TestError>;\n    fn get_ok_struct() -> Result<TestStruct, TestError>;\n    fn get_ok_enum() -> Result<TestEnum, TestError>;\n    fn get_ok_tuple() -> Result<(TestStruct, TestEnum), TestError>;\n    fn get_error() -> Result<Address, TestError>;\n    fn input_ok(ok_address: Result<Address, TestError>) -> bool;\n    fn input_error(test_error: Result<Address, TestError>) -> bool;\n}\n\nimpl MyContract for Contract {\n    fn get_ok_u64() -> Result<u64, TestError> {\n        Result::Ok(10)\n    }\n\n    fn get_ok_address() -> Result<Address, TestError> {\n        Result::Ok(Address::from(ADDR))\n    }\n\n    fn get_ok_struct() -> Result<TestStruct, TestError> {\n        Result::Ok(TestStruct {\n            option: Option::Some(Address::from(ADDR)),\n        })\n    }\n\n    fn get_ok_enum() -> Result<TestEnum, TestError> {\n        Result::Ok(TestEnum::EnumOption(Option::Some(Address::from(ADDR))))\n    }\n\n    fn get_ok_tuple() -> Result<(TestStruct, TestEnum), TestError> {\n        let s = TestStruct {\n            option: Option::Some(Address::from(ADDR)),\n        };\n        let e = TestEnum::EnumOption(Option::Some(Address::from(ADDR)));\n        Result::Ok((s, e))\n    }\n\n    fn get_error() -> Result<Address, TestError> {\n        Result::Err(TestError::NoAddress(__to_str_array(\"error\")))\n    }\n\n    fn input_ok(ok_address: Result<Address, TestError>) -> bool {\n        if let Result::Ok(a) = ok_address {\n            return a == Address::from(ADDR);\n        }\n        false\n    }\n\n    fn input_error(test_result: Result<Address, TestError>) -> bool {\n        if let Result::Err(test_error) = test_result {\n            if let TestError::NoAddress(_err_msg) = test_error {\n                return true;\n            }\n        }\n        false\n    }\n}\n"
  },
  {
    "path": "e2e/sway/types/contracts/std_lib_string/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"std_lib_string\"\n"
  },
  {
    "path": "e2e/sway/types/contracts/std_lib_string/src/main.sw",
    "content": "contract;\n\nuse std::string::String;\nuse std::assert::assert_eq;\nuse std::bytes::Bytes;\n\nabi MyContract {\n    fn return_dynamic_string() -> String;\n    fn accepts_dynamic_string(s: String);\n    fn echoes_dynamic_string(s: String) -> String;\n}\n\nimpl MyContract for Contract {\n    fn return_dynamic_string() -> String {\n        String::from_ascii_str(\"Hello World\")\n    }\n\n    fn accepts_dynamic_string(string: String) {\n        assert_eq(string, String::from_ascii_str(\"Hello World\"));\n    }\n\n    fn echoes_dynamic_string(string: String) -> String {\n        string\n    }\n}\n"
  },
  {
    "path": "e2e/sway/types/contracts/str_in_array/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"str_in_array\"\n"
  },
  {
    "path": "e2e/sway/types/contracts/str_in_array/src/main.sw",
    "content": "contract;\n\nabi TestContract {\n    fn take_array_string_shuffle(a: [str[3]; 3]) -> [str[3]; 3];\n    fn take_array_string_return_single(a: [str[3]; 3]) -> [str[3]; 1];\n    fn take_array_string_return_single_element(a: [str[3]; 3]) -> str[3];\n}\n\nimpl TestContract for Contract {\n    fn take_array_string_shuffle(a: [str[3]; 3]) -> [str[3]; 3] {\n        [a[2], a[0], a[1]]\n    }\n\n    fn take_array_string_return_single(a: [str[3]; 3]) -> [str[3]; 1] {\n        [a[0]]\n    }\n\n    fn take_array_string_return_single_element(a: [str[3]; 3]) -> str[3] {\n        a[1]\n    }\n}\n"
  },
  {
    "path": "e2e/sway/types/contracts/string_slice/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"string_slice\"\n"
  },
  {
    "path": "e2e/sway/types/contracts/string_slice/src/main.sw",
    "content": "contract;\n\nabi RawSliceContract {\n    fn handles_str(input: str) -> str;\n}\n\nimpl RawSliceContract for Contract {\n    fn handles_str(input: str) -> str {\n        assert_eq(input, \"contract-input\");\n\n        \"contract-return\"\n    }\n}\n"
  },
  {
    "path": "e2e/sway/types/contracts/tuples/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"tuples\"\n"
  },
  {
    "path": "e2e/sway/types/contracts/tuples/src/main.sw",
    "content": "contract;\n\nuse std::hash::*;\n\nstruct Person {\n    name: str[4],\n}\n\n#[allow(dead_code)]\nenum State {\n    A: (),\n    B: (),\n    C: (),\n}\n\nabi MyContract {\n    fn returns_tuple(input: (u64, u64)) -> (u64, u64);\n    fn returns_struct_in_tuple(input: (u64, Person)) -> (u64, Person);\n    fn returns_enum_in_tuple(input: (u64, State)) -> (u64, State);\n    fn single_element_tuple(input: (u64, )) -> (u64, );\n    fn tuple_with_b256(p: (b256, u8)) -> (b256, u8);\n}\n\nimpl MyContract for Contract {\n    fn returns_tuple(input: (u64, u64)) -> (u64, u64) {\n        let expected = (1u64, 2u64);\n\n        assert(expected.0 == input.0);\n        assert(expected.1 == input.1);\n\n        expected\n    }\n\n    fn returns_struct_in_tuple(input: (u64, Person)) -> (u64, Person) {\n        let expected = (42, Person {\n            name: __to_str_array(\"Jane\"),\n        });\n        assert(input.0 == expected.0);\n        assert(sha256(from_str_array(input.1.name)) == sha256(from_str_array(expected.1.name)));\n\n        expected\n    }\n\n    fn returns_enum_in_tuple(input: (u64, State)) -> (u64, State) {\n        let expected = (42, State::A);\n\n        assert(input.0 == expected.0);\n\n        match input.1 {\n            State::A => {},\n            _ => {\n                assert(false)\n            }\n        };\n\n        expected\n    }\n\n    fn single_element_tuple(input: (u64, )) -> (u64, ) {\n        let expected = (123u64, );\n\n        assert(expected.0 == input.0);\n\n        expected\n    }\n\n    fn tuple_with_b256(p: (b256, u8)) -> (b256, u8) {\n        let expected = (b256::zero(), 10u8);\n\n        assert(p.0 == expected.0);\n        assert(p.1 == expected.1);\n\n        expected\n    }\n}\n"
  },
  {
    "path": "e2e/sway/types/contracts/two_structs/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"two_structs\"\n"
  },
  {
    "path": "e2e/sway/types/contracts/two_structs/src/main.sw",
    "content": "contract;\n\npub struct StructOne {\n    foo: u64,\n}\n\npub struct StructTwo {\n    bar: u64,\n}\n\nabi MyTest {\n    fn something(input: StructOne) -> u64;\n    fn something_else(input: StructTwo) -> u64;\n}\n\nimpl MyTest for Contract {\n    fn something(input: StructOne) -> u64 {\n        let v = input.foo;\n        v + 1\n    }\n    fn something_else(input: StructTwo) -> u64 {\n        let v = input.bar;\n        v - 1\n    }\n}\n"
  },
  {
    "path": "e2e/sway/types/contracts/type_inside_enum/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"type_inside_enum\"\n"
  },
  {
    "path": "e2e/sway/types/contracts/type_inside_enum/src/main.sw",
    "content": "contract;\n\n#[allow(dead_code)]\nenum SomeEnum {\n    SomeStr: str[4],\n    SomeArr: [u64; 4],\n}\n\n#[allow(dead_code)]\nenum Shaker {\n    Cosmopolitan: Recipe,\n    Mojito: u32,\n}\n\n#[allow(dead_code)]\nstruct Recipe {\n    ice: u8,\n    sugar: u16,\n}\n\n#[allow(dead_code)]\nenum EnumLevel1 {\n    Num: u32,\n    check: bool,\n}\n\n#[allow(dead_code)]\nenum EnumLevel2 {\n    El1: EnumLevel1,\n    Check: bool,\n}\n\n#[allow(dead_code)]\nenum EnumLevel3 {\n    El2: EnumLevel2,\n    Num: u8,\n}\n\nabi MyContract {\n    fn str_inside_enum(my_enum: SomeEnum) -> SomeEnum;\n    fn arr_inside_enum(my_enum: SomeEnum) -> SomeEnum;\n\n    fn return_struct_inside_enum(c: u16) -> Shaker;\n    fn take_struct_inside_enum(s: Shaker) -> u64;\n\n    fn get_nested_enum() -> EnumLevel3;\n    fn check_nested_enum_integrity(e: EnumLevel3) -> bool;\n}\n\nimpl MyContract for Contract {\n    fn str_inside_enum(my_enum: SomeEnum) -> SomeEnum {\n        my_enum\n    }\n    fn arr_inside_enum(my_enum: SomeEnum) -> SomeEnum {\n        my_enum\n    }\n\n    fn return_struct_inside_enum(c: u16) -> Shaker {\n        Shaker::Cosmopolitan(Recipe {\n            ice: 22u8,\n            sugar: c,\n        })\n    }\n    fn take_struct_inside_enum(_s: Shaker) -> u64 {\n        8888\n    }\n\n    fn get_nested_enum() -> EnumLevel3 {\n        EnumLevel3::El2(EnumLevel2::El1(EnumLevel1::Num(42u32)))\n    }\n    fn check_nested_enum_integrity(e: EnumLevel3) -> bool {\n        let arg_is_correct = match e {\n            EnumLevel3::El2(EnumLevel2::El1(EnumLevel1::Num(value))) => {\n                value == 42u32\n            },\n            _ => false,\n        };\n\n        arg_is_correct\n    }\n}\n"
  },
  {
    "path": "e2e/sway/types/contracts/u128/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"u128\"\n"
  },
  {
    "path": "e2e/sway/types/contracts/u128/src/main.sw",
    "content": "contract;\n\nuse std::u128::U128;\n\n#[allow(dead_code)]\nenum SomeEnum<T> {\n    A: bool,\n    B: T,\n}\n\nabi MyContract {\n    fn u128_sum_and_ret(some_u128: U128) -> U128;\n    fn u128_in_enum_input(some_enum: SomeEnum<U128>);\n    fn u128_in_enum_output() -> SomeEnum<U128>;\n}\n\nimpl MyContract for Contract {\n    fn u128_sum_and_ret(arg: U128) -> U128 {\n        arg + U128::from((3, 4))\n    }\n\n    fn u128_in_enum_input(some_enum: SomeEnum<U128>) {\n        if let SomeEnum::B(some_u128) = some_enum {\n            let expected_u128 = U128::from((3, 3));\n            require(\n                some_u128 == expected_u128,\n                \"given u128 didn't match the expected u128\",\n            );\n        } else {\n            require(false, \"enum was not of variant B: u128\");\n        }\n    }\n\n    fn u128_in_enum_output() -> SomeEnum<U128> {\n        SomeEnum::B(U128::from((4, 4)))\n    }\n}\n"
  },
  {
    "path": "e2e/sway/types/contracts/u256/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"u256\"\n"
  },
  {
    "path": "e2e/sway/types/contracts/u256/src/main.sw",
    "content": "contract;\n\n#[allow(dead_code)]\nenum SomeEnum<T> {\n    A: bool,\n    B: T,\n}\n\nabi MyContract {\n    fn u256_sum_and_ret(some_u256: u256) -> u256;\n    fn u256_in_enum_output() -> SomeEnum<u256>;\n    fn u256_in_enum_input(some_enum: SomeEnum<u256>);\n}\n\nimpl MyContract for Contract {\n    fn u256_sum_and_ret(arg: u256) -> u256 {\n        arg + 0x0000000000000003000000000000000400000000000000050000000000000006u256\n    }\n\n    fn u256_in_enum_output() -> SomeEnum<u256> {\n        SomeEnum::B(0x0000000000000001000000000000000200000000000000030000000000000004u256)\n    }\n\n    fn u256_in_enum_input(some_enum: SomeEnum<u256>) {\n        if let SomeEnum::B(some_u256) = some_enum {\n            require(\n                some_u256 == 0x0000000000000002000000000000000300000000000000040000000000000005u256,\n                \"given u256 didn't match the expected u256\",\n            );\n        } else {\n            require(false, \"enum was not of variant B: u256\");\n        }\n    }\n}\n"
  },
  {
    "path": "e2e/sway/types/contracts/vector_output/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"vector_output\"\n"
  },
  {
    "path": "e2e/sway/types/contracts/vector_output/src/main.sw",
    "content": "contract;\n\nstruct Bimbam {\n    bim: u64,\n    bam: u32,\n}\n\nenum Pasta {\n    Rigatoni: u64,\n    Spaghetti: bool,\n    Tortelini: Bimbam,\n}\n\nstruct ZimZam {\n    vec_component: Vec<u64>,\n}\n\nabi VectorsOutputContract {\n    fn vec_inside_type() -> ZimZam;\n    fn array_in_vec() -> Vec<[u64; 4]>;\n    fn bool_in_vec() -> Vec<bool>;\n    fn enum_in_vec() -> Vec<Pasta>;\n    fn str_in_vec() -> Vec<str[4]>;\n    fn struct_in_vec() -> Vec<Bimbam>;\n    fn tuple_in_vec() -> Vec<(u64, u32)>;\n    fn u16_in_vec(len: u16) -> Vec<u16>;\n    fn u32_in_vec(len: u32) -> Vec<u32>;\n    fn u64_in_vec(len: u64) -> Vec<u64>;\n    fn u8_in_vec(len: u8) -> Vec<u8>;\n    fn b256_in_vec(len: u8) -> Vec<b256>;\n}\n\nimpl VectorsOutputContract for Contract {\n    fn vec_inside_type() -> ZimZam {\n        let mut b = Vec::new();\n        b.push(255);\n        b.push(255);\n        b.push(255);\n        b.push(255);\n        ZimZam {\n            vec_component: b,\n        }\n    }\n\n    fn array_in_vec() -> Vec<[u64; 4]> {\n        let mut vec: Vec<[u64; 4]> = Vec::new();\n        vec.push([1, 1, 1, 1]);\n        vec.push([2, 2, 2, 2]);\n        vec.push([3, 3, 3, 3]);\n        vec.push([4, 4, 4, 4]);\n        vec\n    }\n\n    fn bool_in_vec() -> Vec<bool> {\n        let mut vec: Vec<bool> = Vec::new();\n        vec.push(true);\n        vec.push(false);\n        vec.push(true);\n        vec.push(false);\n        vec\n    }\n\n    fn enum_in_vec() -> Vec<Pasta> {\n        let mut vec: Vec<Pasta> = Vec::new();\n        vec.push(Pasta::Tortelini(Bimbam {\n            bim: 1111,\n            bam: 2222_u32,\n        }));\n        vec.push(Pasta::Rigatoni(1987));\n        vec.push(Pasta::Spaghetti(true));\n        vec\n    }\n\n    fn str_in_vec() -> Vec<str[4]> {\n        let mut vec: Vec<str[4]> = Vec::new();\n        vec.push(__to_str_array(\"hell\"));\n        vec.push(__to_str_array(\"ello\"));\n        vec.push(__to_str_array(\"lloh\"));\n        vec\n    }\n\n    fn struct_in_vec() -> Vec<Bimbam> {\n        let mut vec: Vec<Bimbam> = Vec::new();\n        let a = Bimbam {\n            bim: 1111,\n            bam: 2222_u32,\n        };\n        vec.push(a);\n        let b = Bimbam {\n            bim: 3333,\n            bam: 4444_u32,\n        };\n        vec.push(b);\n        let c = Bimbam {\n            bim: 5555,\n            bam: 6666_u32,\n        };\n        vec.push(c);\n        vec\n    }\n\n    fn tuple_in_vec() -> Vec<(u64, u32)> {\n        let mut vec: Vec<(u64, u32)> = Vec::new();\n        vec.push((1111, 2222_u32));\n        vec.push((3333, 4444_u32));\n        vec.push((5555, 6666_u32));\n        vec\n    }\n\n    fn u8_in_vec(len: u8) -> Vec<u8> {\n        let mut vec: Vec<u8> = Vec::new();\n        let mut i: u8 = 0;\n        while i < len {\n            vec.push(i);\n            i += 1u8;\n        }\n        vec\n    }\n\n    fn u16_in_vec(len: u16) -> Vec<u16> {\n        let mut vec: Vec<u16> = Vec::new();\n        let mut i: u16 = 0;\n        while i < len {\n            vec.push(i);\n            i += 1_u16;\n        }\n        vec\n    }\n\n    fn u32_in_vec(len: u32) -> Vec<u32> {\n        let mut vec: Vec<u32> = Vec::new();\n        let mut i: u32 = 0;\n        while i < len {\n            vec.push(i);\n            i += 1_u32;\n        }\n        vec\n    }\n\n    fn u64_in_vec(len: u64) -> Vec<u64> {\n        let mut vec: Vec<u64> = Vec::new();\n        let mut i: u64 = 0;\n        while i < len {\n            vec.push(i);\n            i += 1_u64;\n        }\n        vec\n    }\n\n    fn b256_in_vec(len: u8) -> Vec<b256> {\n        let mut vec: Vec<b256> = Vec::new();\n        let mut i = 0u8;\n        while i < len {\n            vec.push(0x0202020202020202020202020202020202020202020202020202020202020202);\n            i += 1;\n        }\n        vec\n    }\n}\n"
  },
  {
    "path": "e2e/sway/types/contracts/vectors/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"vectors\"\n"
  },
  {
    "path": "e2e/sway/types/contracts/vectors/src/data_structures.sw",
    "content": "library;\n\npub struct SomeStruct<T> {\n    pub a: T,\n}\n\npub enum SomeEnum<T> {\n    a: T,\n}\n"
  },
  {
    "path": "e2e/sway/types/contracts/vectors/src/eq_impls.sw",
    "content": "library;\n\nuse ::data_structures::{SomeEnum, SomeStruct};\n\nimpl PartialEq for SomeEnum<u32> {\n    fn eq(self, other: Self) -> bool {\n        match self {\n            SomeEnum::a(val) => {\n                match other {\n                    SomeEnum::a(other_val) => {\n                        val == other_val\n                    }\n                }\n            }\n        }\n    }\n}\n\nimpl PartialEq for SomeStruct<u32> {\n    fn eq(self, other: Self) -> bool {\n        self.a == other.a\n    }\n}\n\nimpl PartialEq for [Vec<u32>; 2] {\n    fn eq(self, other: Self) -> bool {\n        let mut i = 0;\n        while i < 2 {\n            if self[i] != other[i] {\n                return false;\n            }\n            i += 1;\n        }\n        true\n    }\n}\n\nimpl PartialEq for [u64; 2] {\n    fn eq(self, other: Self) -> bool {\n        let mut i = 0;\n        while i < 2 {\n            if self[i] != other[i] {\n                return false;\n            }\n            i += 1;\n        }\n        true\n    }\n}\n\nimpl PartialEq for SomeEnum<Vec<u32>> {\n    fn eq(self, other: Self) -> bool {\n        match self {\n            SomeEnum::a(val) => {\n                match other {\n                    SomeEnum::a(other_val) => {\n                        val == other_val\n                    }\n                }\n            }\n        }\n    }\n}\n\nimpl PartialEq for SomeStruct<Vec<u32>> {\n    fn eq(self, other: Self) -> bool {\n        self.a == other.a\n    }\n}\n\nimpl PartialEq for SomeStruct<Vec<Vec<u32>>> {\n    fn eq(self, other: Self) -> bool {\n        self.a == other.a\n    }\n}\n"
  },
  {
    "path": "e2e/sway/types/contracts/vectors/src/main.sw",
    "content": "contract;\n\npub mod data_structures;\nmod eq_impls;\nmod utils;\n\nuse eq_impls::*;\nuse utils::*;\nuse data_structures::*;\n\nabi MyContract {\n    fn u32_vec(arg: Vec<u32>);\n    fn struct_in_vec(arg: Vec<SomeStruct<u32>>);\n    fn vec_in_struct(arg: SomeStruct<Vec<u32>>);\n    fn array_in_vec(arg: Vec<[u64; 2]>);\n    fn vec_in_array(arg: [Vec<u32>; 2]);\n    fn enum_in_vec(arg: Vec<SomeEnum<u32>>);\n    fn vec_in_enum(arg: SomeEnum<Vec<u32>>);\n    fn tuple_in_vec(arg: Vec<(u32, u32)>);\n    fn vec_in_tuple(arg: (Vec<u32>, Vec<u32>));\n    fn vec_in_vec(arg: Vec<Vec<u32>>);\n    fn vec_in_a_vec_in_a_struct_in_a_vec(arg: Vec<SomeStruct<Vec<Vec<u32>>>>);\n}\n\nimpl MyContract for Contract {\n    fn u32_vec(arg: Vec<u32>) {\n        let expected = vec_from([0, 1, 2]);\n\n        assert(arg == expected);\n    }\n\n    fn vec_in_vec(arg: Vec<Vec<u32>>) {\n        let mut expected = Vec::new();\n        expected.push(vec_from([0, 1, 2]));\n        expected.push(vec_from([0, 1, 2]));\n\n        assert_eq(arg, expected);\n    }\n\n    fn struct_in_vec(arg: Vec<SomeStruct<u32>>) {\n        let mut expected = Vec::new();\n        expected.push(SomeStruct { a: 0u32 });\n        expected.push(SomeStruct { a: 1u32 });\n\n        assert_eq(arg, expected);\n    }\n\n    fn vec_in_struct(arg: SomeStruct<Vec<u32>>) {\n        let expected = SomeStruct {\n            a: vec_from([0, 1, 2]),\n        };\n\n        assert_eq(arg, expected);\n    }\n\n    fn array_in_vec(arg: Vec<[u64; 2]>) {\n        let mut expected = Vec::new();\n        expected.push([0, 1]);\n        expected.push([0, 1]);\n\n        assert_eq(arg, expected);\n    }\n\n    fn vec_in_array(arg: [Vec<u32>; 2]) {\n        let expected = [vec_from([0, 1, 2]), vec_from([0, 1, 2])];\n\n        assert_eq(arg, expected);\n    }\n\n    fn vec_in_enum(arg: SomeEnum<Vec<u32>>) {\n        let vec = vec_from([0, 1, 2]);\n        let expected = SomeEnum::a(vec);\n\n        assert_eq(arg, expected);\n    }\n    fn enum_in_vec(arg: Vec<SomeEnum<u32>>) {\n        let mut expected = Vec::new();\n        expected.push(SomeEnum::a(0u32));\n        expected.push(SomeEnum::a(1u32));\n\n        assert_eq(arg, expected);\n    }\n\n    fn tuple_in_vec(arg: Vec<(u32, u32)>) {\n        let mut expected = Vec::new();\n        expected.push((0u32, 0u32));\n        expected.push((1u32, 1u32));\n\n        assert_eq(arg, expected);\n    }\n\n    fn vec_in_tuple(arg: (Vec<u32>, Vec<u32>)) {\n        let expected = (vec_from([0, 1, 2]), vec_from([0, 1, 2]));\n\n        assert_eq(arg, expected);\n    }\n\n    fn vec_in_a_vec_in_a_struct_in_a_vec(arg: Vec<SomeStruct<Vec<Vec<u32>>>>) {\n        let mut expected = Vec::new();\n\n        let mut inner_vec_1 = Vec::new();\n\n        let inner_inner_vec_1 = vec_from([0, 1, 2]);\n        inner_vec_1.push(inner_inner_vec_1);\n\n        let inner_inner_vec_2 = vec_from([3, 4, 5]);\n        inner_vec_1.push(inner_inner_vec_2);\n\n        expected.push(SomeStruct { a: inner_vec_1 });\n\n        let mut inner_vec_2 = Vec::new();\n\n        let inner_inner_vec_3 = vec_from([6, 7, 8]);\n        inner_vec_2.push(inner_inner_vec_3);\n\n        let inner_inner_vec_4 = vec_from([9, 10, 11]);\n        inner_vec_2.push(inner_inner_vec_4);\n\n        expected.push(SomeStruct { a: inner_vec_2 });\n\n        assert_eq(arg, expected);\n    }\n}\n"
  },
  {
    "path": "e2e/sway/types/contracts/vectors/src/utils.sw",
    "content": "library;\n\npub fn vec_from(vals: [u32; 3]) -> Vec<u32> {\n    let mut vec = Vec::new();\n    vec.push(vals[0]);\n    vec.push(vals[1]);\n    vec.push(vals[2]);\n    vec\n}\n"
  },
  {
    "path": "e2e/sway/types/predicates/address/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"address\"\n"
  },
  {
    "path": "e2e/sway/types/predicates/address/src/main.sw",
    "content": "predicate;\n\nfn main(input: Address) -> bool {\n    let expected_addr = Address::from(0xef86afa9696cf0dc6385e2c407a6e159a1103cefb7e2ae0636fb33d3cb2a9e4a);\n\n    input == expected_addr\n}\n"
  },
  {
    "path": "e2e/sway/types/predicates/enums/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"enums\"\n"
  },
  {
    "path": "e2e/sway/types/predicates/enums/src/main.sw",
    "content": "predicate;\n\n#[allow(dead_code)]\nenum TestEnum {\n    A: u64,\n    B: bool,\n}\n\n#[allow(dead_code)]\nenum AnotherTestEnum {\n    A: u64,\n    B: u64,\n}\n\nfn main(test_enum: TestEnum, test_enum2: AnotherTestEnum) -> bool {\n    if let TestEnum::A(a) = test_enum {\n        if let AnotherTestEnum::B(b) = test_enum2 {\n            return a == b;\n        }\n    }\n\n    false\n}\n"
  },
  {
    "path": "e2e/sway/types/predicates/predicate_b256/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"predicate_b256\"\n"
  },
  {
    "path": "e2e/sway/types/predicates/predicate_b256/src/main.sw",
    "content": "predicate;\n\nfn main(foo: b256) -> bool {\n    foo == 0x0101010101010101010101010101010101010101010101010101010101010101\n}\n"
  },
  {
    "path": "e2e/sway/types/predicates/predicate_bytes/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"predicate_bytes\"\n"
  },
  {
    "path": "e2e/sway/types/predicates/predicate_bytes/src/main.sw",
    "content": "predicate;\n\nuse std::bytes::Bytes;\n\n#[allow(dead_code)]\nenum SomeEnum<T> {\n    First: bool,\n    Second: T,\n}\n\nstruct Wrapper<T> {\n    inner: T,\n    inner_enum: SomeEnum<Bytes>,\n}\n\nfn expected_bytes() -> Bytes {\n    let mut bytes = Bytes::new();\n\n    bytes.push(40u8);\n    bytes.push(41u8);\n    bytes.push(42u8);\n\n    bytes\n}\n\nfn valid_bytes(bytes: Bytes) -> bool {\n    bytes == expected_bytes()\n}\n\nfn valid_vec(arg: Vec<Bytes>) -> bool {\n    if arg.len() != 2 {\n        return false;\n    }\n\n    valid_bytes(arg.get(0).unwrap()) && valid_bytes(arg.get(1).unwrap())\n}\n\nfn main(wrapper: Wrapper<Vec<Bytes>>) -> bool {\n    if let SomeEnum::Second(enum_bytes) = wrapper.inner_enum {\n        valid_bytes(enum_bytes) && valid_vec(wrapper.inner)\n    } else {\n        false\n    }\n}\n"
  },
  {
    "path": "e2e/sway/types/predicates/predicate_bytes_hash/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"predicate_bytes_hash\"\n"
  },
  {
    "path": "e2e/sway/types/predicates/predicate_bytes_hash/src/main.sw",
    "content": "predicate;\n\nuse std::bytes::Bytes;\nuse std::hash::{Hash, sha256};\n\nfn main(bytes: Bytes, hash: b256) -> bool {\n    sha256(bytes) == hash\n}\n"
  },
  {
    "path": "e2e/sway/types/predicates/predicate_generics/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"predicate_generics\"\n"
  },
  {
    "path": "e2e/sway/types/predicates/predicate_generics/src/main.sw",
    "content": "predicate;\n\nstruct GenericStruct<U> {\n    value: U,\n}\n\n#[allow(dead_code)]\nenum GenericEnum<T, V> {\n    Generic: GenericStruct<T>,\n    AnotherGeneric: V,\n}\n\nfn main(\n    generic_struct: GenericStruct<u8>,\n    generic_enum: GenericEnum<u16, u32>,\n) -> bool {\n    if let GenericEnum::Generic(other_struct) = generic_enum {\n        return other_struct.value == generic_struct.value.as_u16();\n    }\n\n    false\n}\n"
  },
  {
    "path": "e2e/sway/types/predicates/predicate_raw_slice/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"predicate_raw_slice\"\n"
  },
  {
    "path": "e2e/sway/types/predicates/predicate_raw_slice/src/main.sw",
    "content": "predicate;\n\n#[allow(dead_code)]\nenum SomeEnum<T> {\n    First: bool,\n    Second: T,\n}\n\nstruct Wrapper<T> {\n    inner: T,\n    inner_enum: SomeEnum<raw_slice>,\n}\n\nfn valid_raw_slice(slice: raw_slice) -> bool {\n    let vec: Vec<u8> = Vec::from(slice);\n    vec.len() == 3 && vec.get(0).unwrap() == 40 && vec.get(1).unwrap() == 41 && vec.get(2).unwrap() == 42\n}\n\nfn valid_vec(vec: Vec<raw_slice>) -> bool {\n    vec.len() == 2 && valid_raw_slice(vec.get(0).unwrap()) && valid_raw_slice(vec.get(1).unwrap())\n}\n\nfn main(wrapper: Wrapper<Vec<raw_slice>>) -> bool {\n    if let SomeEnum::Second(enum_raw_slice) = wrapper.inner_enum\n    {\n        valid_raw_slice(enum_raw_slice) && valid_vec(wrapper.inner)\n    } else {\n        false\n    }\n}\n"
  },
  {
    "path": "e2e/sway/types/predicates/predicate_std_lib_string/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"predicate_std_lib_string\"\n"
  },
  {
    "path": "e2e/sway/types/predicates/predicate_std_lib_string/src/main.sw",
    "content": "predicate;\n\nuse std::string::String;\n\nfn main(_arg_0: u64, _arg_1: u64, string: String) -> bool {\n    string == String::from_ascii_str(\"Hello World\")\n}\n"
  },
  {
    "path": "e2e/sway/types/predicates/predicate_string_slice/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"predicate_string_slice\"\n"
  },
  {
    "path": "e2e/sway/types/predicates/predicate_string_slice/src/main.sw",
    "content": "predicate;\n\nfn main(input: str) -> bool {\n    input == \"predicate-input\"\n}\n"
  },
  {
    "path": "e2e/sway/types/predicates/predicate_tuples/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"predicate_tuples\"\n"
  },
  {
    "path": "e2e/sway/types/predicates/predicate_tuples/src/main.sw",
    "content": "predicate;\n\nstruct TestStruct {\n    value: u32,\n}\n\n#[allow(dead_code)]\nenum TestEnum {\n    Value: u64,\n    OtherValue: u32,\n}\n\nfn main(input_tuple: (u64, TestStruct, TestEnum), number: u64) -> bool {\n    let (u64_number, test_struct, test_enum) = input_tuple;\n\n    if let TestEnum::Value(enum_value) = test_enum {\n        return u64_number == 16 && test_struct.value == 32u32 && enum_value == 64 && number == 128;\n    }\n\n    false\n}\n"
  },
  {
    "path": "e2e/sway/types/predicates/predicate_u128/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"predicate_u128\"\n"
  },
  {
    "path": "e2e/sway/types/predicates/predicate_u128/src/main.sw",
    "content": "predicate;\n\nuse std::u128::U128;\n\nfn main(arg: U128) -> bool {\n    arg == U128::from((8, 2))\n}\n"
  },
  {
    "path": "e2e/sway/types/predicates/predicate_u256/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"predicate_u256\"\n"
  },
  {
    "path": "e2e/sway/types/predicates/predicate_u256/src/main.sw",
    "content": "predicate;\n\nfn main(arg: u256) -> bool {\n    arg == 0x000000000000000a000000000000000b000000000000000c000000000000000du256\n}\n"
  },
  {
    "path": "e2e/sway/types/predicates/predicate_vector/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"predicate_vector\"\n"
  },
  {
    "path": "e2e/sway/types/predicates/predicate_vector/src/main.sw",
    "content": "predicate;\n\nfn main(a: u32, b: u64, c: Vec<u64>) -> bool {\n    let number: u64 = c.get(2).unwrap();\n    number == (b + a.as_u64())\n}\n"
  },
  {
    "path": "e2e/sway/types/predicates/predicate_vectors/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"predicate_vectors\"\n"
  },
  {
    "path": "e2e/sway/types/predicates/predicate_vectors/src/main.sw",
    "content": "predicate;\n\npub struct SomeStruct<T> {\n    a: T,\n}\n\npub enum SomeEnum<T> {\n    A: T,\n    B: bool,\n}\n\nfn main(\n    u32_vec: Vec<u32>,\n    vec_in_vec: Vec<Vec<u32>>,\n    struct_in_vec: Vec<SomeStruct<u32>>,\n    vec_in_struct: SomeStruct<Vec<u32>>,\n    array_in_vec: Vec<[u64; 2]>,\n    vec_in_array: [Vec<u32>; 2],\n    vec_in_enum: SomeEnum<Vec<u32>>,\n    enum_in_vec: Vec<SomeEnum<u32>>,\n    b256_in_vec: Vec<b256>,\n    tuple_in_vec: Vec<(u32, u32)>,\n    vec_in_tuple: (Vec<u32>, Vec<u32>),\n    vec_in_a_vec_in_a_struct_in_a_vec: Vec<SomeStruct<Vec<Vec<u32>>>>,\n) -> bool {\n    let mut result = true;\n\n    result = result && (u32_vec.get(1).unwrap() == 4u32);\n\n    result = result && (vec_in_vec.get(0).unwrap().get(1).unwrap() == 2u32);\n\n    result = result && (struct_in_vec.get(0).unwrap().a == 8u32);\n\n    result = result && (vec_in_struct.a.get(1).unwrap() == 16u32);\n\n    let array: [u64; 2] = array_in_vec.get(1).unwrap();\n    result = result && (array[0] == 32u64);\n\n    result = result && (vec_in_array[0].get(1).unwrap() == 64u32);\n\n    if let SomeEnum::A(some_vec) = vec_in_enum {\n        result = result && (some_vec.get(2).unwrap() == 128u32);\n    } else {\n        result = false;\n    }\n\n    let enum_a = enum_in_vec.get(1).unwrap();\n    if let SomeEnum::A(a) = enum_a {\n        result = result && (a == 16u32)\n    } else {\n        result = false;\n    }\n\n    result = result\n        && (b256_in_vec\n                .get(1)\n                .unwrap() == 0x0202020202020202020202020202020202020202020202020202020202020202);\n\n    result = result && (tuple_in_vec.get(1).unwrap().0 == 128u32);\n\n    let (tuple_a, _) = vec_in_tuple;\n    result = result && (tuple_a.get(1).unwrap() == 64u32);\n\n    result = result\n        && (vec_in_a_vec_in_a_struct_in_a_vec\n                .get(1)\n                .unwrap()\n                .a\n                .get(1)\n                .unwrap()\n                .get(1)\n                .unwrap() == 32u32);\n\n    result\n}\n"
  },
  {
    "path": "e2e/sway/types/predicates/structs/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"structs\"\n"
  },
  {
    "path": "e2e/sway/types/predicates/structs/src/main.sw",
    "content": "predicate;\n\nstruct TestStruct {\n    value: u64,\n}\n\nstruct AnotherTestStruct {\n    value: u64,\n    number: u64,\n}\n\nfn main(test_struct: TestStruct, test_struct2: AnotherTestStruct) -> bool {\n    test_struct.value == (test_struct2.value + test_struct2.number)\n}\n"
  },
  {
    "path": "e2e/sway/types/predicates/u64/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"u64\"\n"
  },
  {
    "path": "e2e/sway/types/predicates/u64/src/main.sw",
    "content": "predicate;\n\nfn main(a: u64) -> bool {\n    a == 32768\n}\n"
  },
  {
    "path": "e2e/sway/types/scripts/options_results/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"options_results\"\n"
  },
  {
    "path": "e2e/sway/types/scripts/options_results/src/main.sw",
    "content": "script;\n\npub enum TestError {\n    ZimZam: str[5],\n}\n\nfn main(bim: Option<u32>, _bam: Option<u64>) -> Result<Option<bool>, TestError> {\n    if let Option::Some(42) = bim {\n        Result::Ok(Option::Some(true))\n    } else if let Option::Some(_) = bim {\n        Result::Ok(Option::None)\n    } else {\n        Result::Err(TestError::ZimZam(__to_str_array(\"error\")))\n    }\n}\n"
  },
  {
    "path": "e2e/sway/types/scripts/script_b256/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"script_b256\"\n"
  },
  {
    "path": "e2e/sway/types/scripts/script_b256/src/main.sw",
    "content": "script;\n\nfn main(foo: b256) -> b256 {\n    assert_eq(\n        foo,\n        0x0101010101010101010101010101010101010101010101010101010101010101,\n    );\n\n    0x0202020202020202020202020202020202020202020202020202020202020202\n}\n"
  },
  {
    "path": "e2e/sway/types/scripts/script_bytes/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"script_bytes\"\n"
  },
  {
    "path": "e2e/sway/types/scripts/script_bytes/src/main.sw",
    "content": "script;\n\nuse std::bytes::Bytes;\n\n#[allow(dead_code)]\nenum SomeEnum<T> {\n    First: bool,\n    Second: T,\n}\n\nstruct Wrapper<T> {\n    inner: T,\n    inner_enum: SomeEnum<Bytes>,\n}\n\nfn expected_bytes() -> Bytes {\n    let mut bytes = Bytes::new();\n\n    bytes.push(40u8);\n    bytes.push(41u8);\n    bytes.push(42u8);\n\n    bytes\n}\n\nfn main(_arg: u64, wrapper: Wrapper<Vec<Bytes>>) {\n    if let SomeEnum::Second(enum_bytes) = wrapper.inner_enum {\n        require(\n            enum_bytes == expected_bytes(),\n            \"wrapper.inner_enum didn't carry the expected bytes\",\n        )\n    } else {\n        require(false, \"enum was not of variant Second\");\n    }\n\n    let inner_vec = wrapper.inner;\n    require(\n        inner_vec\n            .len() == 2,\n        \"Expected wrapper.inner vector to have 2 elements\",\n    );\n    require(\n        inner_vec\n            .get(0)\n            .unwrap() == expected_bytes(),\n        \"wrapper.inner[0] didn't match expectation\",\n    );\n    require(\n        inner_vec\n            .get(1)\n            .unwrap() == expected_bytes(),\n        \"wrapper.inner[1] didn't match expectation\",\n    );\n}\n"
  },
  {
    "path": "e2e/sway/types/scripts/script_generics/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"script_generics\"\n"
  },
  {
    "path": "e2e/sway/types/scripts/script_generics/src/main.sw",
    "content": "script;\n\nstruct GenericBimbam<U> {\n    val: U,\n}\n\n#[allow(dead_code)]\nstruct GenericSnack<T, V> {\n    twix: GenericBimbam<T>,\n    mars: V,\n}\n\nfn main(\n    bim: GenericBimbam<u8>,\n    bam: GenericSnack<u16, u32>,\n) -> (GenericSnack<u64, u32>, GenericBimbam<u8>) {\n    (\n        GenericSnack {\n            twix: GenericBimbam {\n                val: bam.mars.as_u64(),\n            },\n            mars: 2u32 * bim.val.as_u32(),\n        },\n        GenericBimbam { val: 255u8 },\n    )\n}\n"
  },
  {
    "path": "e2e/sway/types/scripts/script_heap_types/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"script_heap_types\"\n"
  },
  {
    "path": "e2e/sway/types/scripts/script_heap_types/src/main.sw",
    "content": "script;\n\nuse std::bytes::Bytes;\nuse std::string::String;\n\n#[allow(dead_code)]\nstruct StructGenerics<T, K, U> {\n    one: T,\n    two: K,\n    three: U,\n}\n\n#[allow(dead_code)]\nenum EnumGeneric<H, I> {\n    One: H,\n    Two: I,\n}\n\nfn main() -> EnumGeneric<Vec<StructGenerics<Bytes, String, Vec<u8>>>, String> {\n    let mut some_vec = Vec::new();\n    some_vec.push(2u8);\n    some_vec.push(4u8);\n    some_vec.push(8u8);\n\n    let struct_generics = StructGenerics {\n        one: Bytes::from(some_vec),\n        two: String::from_ascii_str(\"fuel\"),\n        three: some_vec,\n    };\n\n    let mut enum_vec = Vec::new();\n    enum_vec.push(struct_generics);\n    enum_vec.push(struct_generics);\n\n    EnumGeneric::One(enum_vec)\n}\n"
  },
  {
    "path": "e2e/sway/types/scripts/script_raw_slice/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"script_raw_slice\"\n"
  },
  {
    "path": "e2e/sway/types/scripts/script_raw_slice/src/main.sw",
    "content": "script;\n\n#[allow(dead_code)]\nenum SomeEnum<T> {\n    First: bool,\n    Second: T,\n}\n\nstruct Wrapper<T> {\n    inner: T,\n    inner_enum: SomeEnum<raw_slice>,\n}\n\nfn validate_raw_slice(input: raw_slice) {\n    let vec: Vec<u8> = Vec::from(input);\n    require(vec.len() == 3, \"raw slice len is not 3\");\n    require(\n        vec\n            .get(2)\n            .unwrap() == 42,\n        \"expected 3rd slice entry to be 42\",\n    );\n    require(\n        vec\n            .get(1)\n            .unwrap() == 41,\n        \"expected 2nd slice entry to be 41\",\n    );\n    require(\n        vec\n            .get(0)\n            .unwrap() == 40,\n        \"expected 1st slice entry to be 40\",\n    );\n}\n\nfn validate_vec(vec: Vec<raw_slice>) {\n    require(vec.len() == 2, \"vec should have two elements\");\n    validate_raw_slice(vec.get(0).unwrap());\n    validate_raw_slice(vec.get(1).unwrap());\n}\n\nfn main(length: u8, wrapper: Wrapper<Vec<raw_slice>>) -> raw_slice {\n    if let SomeEnum::Second(enum_raw_slice) = wrapper.inner_enum\n    {\n        validate_raw_slice(enum_raw_slice);\n    } else {\n        require(false, \"enum was not of variant Second\");\n    }\n\n    validate_vec(wrapper.inner);\n\n    let mut vec = Vec::new();\n    let mut counter = 0u8;\n    while counter < length {\n        vec.push(counter);\n        counter = counter + 1;\n    }\n    vec.as_raw_slice()\n}\n"
  },
  {
    "path": "e2e/sway/types/scripts/script_std_lib_string/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"script_std_lib_string\"\n"
  },
  {
    "path": "e2e/sway/types/scripts/script_std_lib_string/src/main.sw",
    "content": "script;\n\nuse std::string::String;\n\nfn main(string: String) -> String {\n    assert_eq(string, String::from_ascii_str(\"script-input\"));\n\n    String::from_ascii_str(\"script-return\")\n}\n"
  },
  {
    "path": "e2e/sway/types/scripts/script_string_slice/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"script_string_slice\"\n"
  },
  {
    "path": "e2e/sway/types/scripts/script_string_slice/src/main.sw",
    "content": "script;\n\nfn main(input: str) -> str {\n    assert_eq(input, \"script-input\");\n\n    \"script-return\"\n}\n"
  },
  {
    "path": "e2e/sway/types/scripts/script_tuples/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"script_tuples\"\n"
  },
  {
    "path": "e2e/sway/types/scripts/script_tuples/src/main.sw",
    "content": "script;\n\n#[allow(dead_code)]\nstruct Bim {\n    bim: u64,\n}\n\n#[allow(dead_code)]\nstruct Bam {\n    bam: str[5],\n}\n\n#[allow(dead_code)]\nstruct Boum {\n    boum: bool,\n}\n\nfn main(_my_tuple: (Bim, Bam, Boum), _zim: Bam) -> ((Boum, Bim, Bam), u64) {\n    (\n        (\n            Boum { boum: true },\n            Bim { bim: 193817 },\n            Bam {\n                bam: __to_str_array(\"hello\"),\n            },\n        ),\n        42242,\n    )\n}\n"
  },
  {
    "path": "e2e/sway/types/scripts/script_u128/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"script_u128\"\n"
  },
  {
    "path": "e2e/sway/types/scripts/script_u128/src/main.sw",
    "content": "script;\n\nuse std::u128::U128;\n\nfn main(arg: U128) -> U128 {\n    arg + U128::from((8, 2))\n}\n"
  },
  {
    "path": "e2e/sway/types/scripts/script_u256/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"script_u256\"\n"
  },
  {
    "path": "e2e/sway/types/scripts/script_u256/src/main.sw",
    "content": "script;\n\nfn main(arg: u256) -> u256 {\n    arg + 0x0000000000000006000000000000000700000000000000080000000000000009u256\n}\n"
  },
  {
    "path": "e2e/sway/types/scripts/script_vectors/Forc.toml",
    "content": "[project]\nauthors = [\"Fuel Labs <contact@fuel.sh>\"]\nentry = \"main.sw\"\nlicense = \"Apache-2.0\"\nname = \"script_vectors\"\n"
  },
  {
    "path": "e2e/sway/types/scripts/script_vectors/src/data_structures.sw",
    "content": "library;\n\npub struct SomeStruct<T> {\n    pub a: T,\n}\n\npub enum SomeEnum<T> {\n    a: T,\n}\n"
  },
  {
    "path": "e2e/sway/types/scripts/script_vectors/src/eq_impls.sw",
    "content": "library;\n\nuse ::data_structures::{SomeEnum, SomeStruct};\n\nimpl PartialEq for SomeEnum<u32> {\n    fn eq(self, other: Self) -> bool {\n        match self {\n            SomeEnum::a(val) => {\n                match other {\n                    SomeEnum::a(other_val) => {\n                        val == other_val\n                    }\n                }\n            }\n        }\n    }\n}\n\nimpl PartialEq for SomeStruct<u32> {\n    fn eq(self, other: Self) -> bool {\n        self.a == other.a\n    }\n}\n\nimpl PartialEq for [Vec<u32>; 2] {\n    fn eq(self, other: Self) -> bool {\n        let mut i = 0;\n        while i < 2 {\n            if self[i] != other[i] {\n                return false;\n            }\n            i += 1;\n        }\n        true\n    }\n}\n\nimpl PartialEq for [u64; 2] {\n    fn eq(self, other: Self) -> bool {\n        let mut i = 0;\n        while i < 2 {\n            if self[i] != other[i] {\n                return false;\n            }\n            i += 1;\n        }\n        true\n    }\n}\n\nimpl PartialEq for SomeEnum<Vec<u32>> {\n    fn eq(self, other: Self) -> bool {\n        match self {\n            SomeEnum::a(val) => {\n                match other {\n                    SomeEnum::a(other_val) => {\n                        val == other_val\n                    }\n                }\n            }\n        }\n    }\n}\n\nimpl PartialEq for SomeStruct<Vec<u32>> {\n    fn eq(self, other: Self) -> bool {\n        self.a == other.a\n    }\n}\n\nimpl PartialEq for SomeStruct<Vec<Vec<u32>>> {\n    fn eq(self, other: Self) -> bool {\n        self.a == other.a\n    }\n}\n"
  },
  {
    "path": "e2e/sway/types/scripts/script_vectors/src/main.sw",
    "content": "script;\n\npub mod data_structures;\nmod eq_impls;\nmod utils;\n\nuse eq_impls::*;\nuse utils::*;\nuse data_structures::*;\n\nfn main(\n    u32_vec: Vec<u32>,\n    vec_in_vec: Vec<Vec<u32>>,\n    struct_in_vec: Vec<SomeStruct<u32>>,\n    vec_in_struct: SomeStruct<Vec<u32>>,\n    array_in_vec: Vec<[u64; 2]>,\n    vec_in_array: [Vec<u32>; 2],\n    vec_in_enum: SomeEnum<Vec<u32>>,\n    enum_in_vec: Vec<SomeEnum<u32>>,\n    b256_in_vec: Vec<b256>,\n    tuple_in_vec: Vec<(u32, u32)>,\n    vec_in_tuple: (Vec<u32>, Vec<u32>),\n    vec_in_a_vec_in_a_struct_in_a_vec: Vec<SomeStruct<Vec<Vec<u32>>>>,\n) -> bool {\n    {\n        let exp_u32_vec = vec_from([0u32, 1u32, 2u32]);\n\n        require(u32_vec == exp_u32_vec, \"u32_vec_error\");\n    }\n    {\n        let mut exp_vec_in_vec = Vec::new();\n        exp_vec_in_vec.push(vec_from([0u32, 1u32, 2u32]));\n        exp_vec_in_vec.push(vec_from([0u32, 1u32, 2u32]));\n\n        require(vec_in_vec == exp_vec_in_vec, \"vec_in_vec err\");\n    }\n    {\n        let mut exp_struct_in_vec = Vec::new();\n        exp_struct_in_vec.push(SomeStruct { a: 0u32 });\n        exp_struct_in_vec.push(SomeStruct { a: 1u32 });\n\n        require(struct_in_vec == exp_struct_in_vec, \"struct_in_vec err\");\n    }\n    {\n        let exp_vec_in_struct = SomeStruct {\n            a: vec_from([0u32, 1u32, 2u32]),\n        };\n\n        require(vec_in_struct.a == exp_vec_in_struct.a, \"vec_in_struct err\");\n    }\n    {\n        let mut exp_array_in_vec = Vec::new();\n        exp_array_in_vec.push([0, 1]);\n        exp_array_in_vec.push([0, 1]);\n\n        require(array_in_vec == exp_array_in_vec, \"array_in_vec err\");\n    }\n    {\n        let exp_vec_in_array = [vec_from([0u32, 1u32, 2u32]), vec_from([0u32, 1u32, 2u32])];\n\n        require(vec_in_array == exp_vec_in_array, \"vec_in_array err\");\n    }\n    {\n        let exp_u32_vec = vec_from([0u32, 1u32, 2u32]);\n        let exp_vec_in_enum = SomeEnum::a(exp_u32_vec);\n\n        require(vec_in_enum == exp_vec_in_enum, \"vec_in_enum err\");\n    }\n    {\n        let mut exp_enum_in_vec = Vec::new();\n        exp_enum_in_vec.push(SomeEnum::a(0u32));\n        exp_enum_in_vec.push(SomeEnum::a(1u32));\n\n        require(enum_in_vec == exp_enum_in_vec, \"enum_in_vec err\");\n    }\n    {\n        let mut exp_b256_in_vec = Vec::new();\n        exp_b256_in_vec.push(0x0202020202020202020202020202020202020202020202020202020202020202);\n        exp_b256_in_vec.push(0x0202020202020202020202020202020202020202020202020202020202020202);\n\n        require(b256_in_vec == exp_b256_in_vec, \"b256_in_vec err\");\n    }\n    {\n        let mut exp_tuple_in_vec = Vec::new();\n        exp_tuple_in_vec.push((0u32, 0u32));\n        exp_tuple_in_vec.push((1u32, 1u32));\n\n        require(tuple_in_vec == exp_tuple_in_vec, \"tuple_in_vec err\");\n    }\n    {\n        let exp_vec_in_tuple = (vec_from([0u32, 1u32, 2u32]), vec_from([0u32, 1u32, 2u32]));\n\n        require(vec_in_tuple == exp_vec_in_tuple, \"vec_in_tuple err\");\n    }\n    {\n        let mut exp_vec_in_a_vec_in_a_struct_in_a_vec = Vec::new();\n\n        let mut inner_vec_1 = Vec::new();\n\n        let inner_inner_vec_1 = vec_from([0u32, 1u32, 2u32]);\n        inner_vec_1.push(inner_inner_vec_1);\n\n        let inner_inner_vec_2 = vec_from([3u32, 4u32, 5u32]);\n        inner_vec_1.push(inner_inner_vec_2);\n\n        exp_vec_in_a_vec_in_a_struct_in_a_vec.push(SomeStruct { a: inner_vec_1 });\n\n        let mut inner_vec_2 = Vec::new();\n\n        let inner_inner_vec_3 = vec_from([6u32, 7u32, 8u32]);\n        inner_vec_2.push(inner_inner_vec_3);\n\n        let inner_inner_vec_4 = vec_from([9u32, 10u32, 11u32]);\n        inner_vec_2.push(inner_inner_vec_4);\n\n        exp_vec_in_a_vec_in_a_struct_in_a_vec.push(SomeStruct { a: inner_vec_2 });\n\n        require(\n            vec_in_a_vec_in_a_struct_in_a_vec == exp_vec_in_a_vec_in_a_struct_in_a_vec,\n            \"vec_in_a_vec_in_a_struct_in_a_vec err\",\n        );\n    }\n\n    true\n}\n"
  },
  {
    "path": "e2e/sway/types/scripts/script_vectors/src/utils.sw",
    "content": "library;\n\npub fn vec_from(vals: [u32; 3]) -> Vec<u32> {\n    let mut vec = Vec::new();\n    vec.push(vals[0]);\n    vec.push(vals[1]);\n    vec.push(vals[2]);\n    vec\n}\n"
  },
  {
    "path": "e2e/tests/aws.rs",
    "content": "#[cfg(test)]\nmod tests {\n    use anyhow::Result;\n    use e2e::e2e_helpers::start_aws_kms;\n    use fuels::{\n        accounts::{Account, ViewOnlyAccount, signers::kms::aws::AwsKmsSigner, wallet::Wallet},\n        core::traits::Signer,\n        prelude::{\n            AssetId, Contract, LoadConfiguration, TxPolicies, launch_provider_and_get_wallet,\n        },\n        types::errors::Context,\n    };\n\n    #[tokio::test(flavor = \"multi_thread\")]\n    async fn fund_aws_wallet() -> Result<()> {\n        let kms = start_aws_kms(false).await?;\n        let wallet = launch_provider_and_get_wallet().await?;\n\n        let amount = 500000000;\n        let key = kms.create_signer().await?;\n        let address = key.address();\n\n        wallet\n            .transfer(address, amount, AssetId::zeroed(), TxPolicies::default())\n            .await\n            .context(\"Failed to transfer funds\")?;\n\n        let your_kms_key_id = key.key_id();\n        let provider = wallet.provider().clone();\n\n        let aws_client = kms.client();\n        // ANCHOR: use_kms_wallet\n        let kms_signer = AwsKmsSigner::new(your_kms_key_id, aws_client).await?;\n        let wallet = Wallet::new(kms_signer, provider);\n        // ANCHOR_END: use_kms_wallet\n\n        let total_base_balance = wallet.get_asset_balance(&AssetId::zeroed()).await?;\n        assert_eq!(total_base_balance, amount as u128);\n        Ok(())\n    }\n\n    #[tokio::test(flavor = \"multi_thread\")]\n    async fn deploy_contract() -> Result<()> {\n        let kms = start_aws_kms(false).await?;\n\n        let wallet = launch_provider_and_get_wallet().await?;\n\n        let amount = 500000000;\n        let key = kms.create_signer().await?;\n        let address = key.address();\n\n        wallet\n            .transfer(address, amount, AssetId::zeroed(), TxPolicies::default())\n            .await\n            .context(\"Failed to transfer funds\")?;\n\n        let your_kms_key_id = key.key_id();\n        let provider = wallet.provider().clone();\n\n        let kms_signer = AwsKmsSigner::new(your_kms_key_id, kms.client()).await?;\n        let aws_wallet = Wallet::new(kms_signer, provider);\n\n        Contract::load_from(\n            \"../e2e/sway/contracts/contract_test/out/release/contract_test.bin\",\n            LoadConfiguration::default(),\n        )?\n        .deploy(&aws_wallet, TxPolicies::default())\n        .await?;\n\n        Ok(())\n    }\n}\n"
  },
  {
    "path": "e2e/tests/binary_format.rs",
    "content": "#[cfg(test)]\nmod tests {\n    use std::{convert::TryInto, ops::Range};\n\n    use fuels::programs::executable::{Executable, Regular};\n\n    const DATA_OFFSET_LOCATION: Range<usize> = 8..16;\n    const CONFIGURABLES_OFFSET_LOCATION: Range<usize> = 16..24;\n\n    const LEGACY_BINARY_PATH: &str =\n        \"../e2e/assets/precompiled_sway/legacy_format_simple_contract.bin\";\n    const NEW_BINARY_PATH: &str =\n        \"../e2e/sway/bindings/simple_contract/out/release/simple_contract.bin\";\n\n    #[test]\n    fn no_configurables_offset_for_old_sway_binaries() {\n        // given\n        let (_, executable) = load(LEGACY_BINARY_PATH);\n\n        // when\n        let configurables_offset = executable.configurables_offset_in_code().unwrap();\n\n        // then\n        assert_eq!(configurables_offset, None);\n    }\n\n    #[test]\n    fn correct_data_offset_for_old_sway_binaries() {\n        // given\n        let (binary, executable) = load(LEGACY_BINARY_PATH);\n        let expected_data_offset = read_offset(&binary, DATA_OFFSET_LOCATION);\n\n        // when\n        let data_offset = executable.data_offset_in_code().unwrap();\n\n        // then\n        assert_eq!(data_offset, expected_data_offset);\n    }\n\n    #[test]\n    fn correct_data_offset_for_new_sway_binaries() {\n        // given\n        let (binary, executable) = load(NEW_BINARY_PATH);\n        let expected_data_offset = read_offset(&binary, DATA_OFFSET_LOCATION);\n\n        // when\n        let data_offset = executable.data_offset_in_code().unwrap();\n\n        // then\n        assert_eq!(data_offset, expected_data_offset);\n    }\n\n    #[test]\n    fn correct_configurables_offset_for_new_sway_binaries() {\n        // given\n        let (binary, executable) = load(NEW_BINARY_PATH);\n        let expected_configurables_offset = read_offset(&binary, CONFIGURABLES_OFFSET_LOCATION);\n\n        // when\n        let configurables_offset = executable.configurables_offset_in_code();\n\n        // then\n        let configurables_offset = configurables_offset\n            .expect(\"to successfully detect a modern binary is used\")\n            .expect(\"to extract the configurables_offset\");\n        assert_eq!(configurables_offset, expected_configurables_offset);\n    }\n\n    pub fn read_offset(binary: &[u8], range: Range<usize>) -> usize {\n        assert_eq!(range.clone().count(), 8, \"must be a range of 8 B\");\n        let data: [u8; 8] = binary[range].try_into().unwrap();\n        u64::from_be_bytes(data) as usize\n    }\n\n    fn load(path: &str) -> (Vec<u8>, Executable<Regular>) {\n        let binary = std::fs::read(path).unwrap();\n        let executable = Executable::from_bytes(binary.clone());\n        (binary, executable)\n    }\n}\n"
  },
  {
    "path": "e2e/tests/bindings.rs",
    "content": "use fuels::prelude::*;\n\nmod hygiene {\n    #[tokio::test]\n    async fn setup_program_test_is_hygienic() {\n        fuels::prelude::setup_program_test!(\n            Wallets(\"wallet\"),\n            Abigen(Contract(\n                name = \"SimpleContract\",\n                project = \"e2e/sway/bindings/simple_contract\"\n            )),\n            Deploy(\n                name = \"simple_contract_instance\",\n                contract = \"SimpleContract\",\n                wallet = \"wallet\",\n                random_salt = false,\n            ),\n        );\n    }\n}\n\n#[tokio::test]\nasync fn compile_bindings_from_contract_file() {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"SimpleContract\",\n            project = \"e2e/sway/bindings/simple_contract\"\n        )),\n        Deploy(\n            name = \"simple_contract_instance\",\n            contract = \"SimpleContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    let call_handler = simple_contract_instance\n        .methods()\n        .takes_int_returns_bool(42);\n\n    let encoded_args = call_handler.call.encoded_args.unwrap();\n\n    assert_eq!(encoded_args, [0, 0, 0, 42]);\n}\n\n#[tokio::test]\nasync fn compile_bindings_from_inline_contract() -> Result<()> {\n    abigen!(Contract(\n        name = \"SimpleContract\",\n        // abi generated with: \"e2e/sway/abi/simple_contract\"\n        abi = r#\"\n        {\n          \"programType\": \"contract\",\n          \"specVersion\": \"1\",\n          \"encodingVersion\": \"1\",\n          \"concreteTypes\": [\n            {\n              \"type\": \"bool\",\n              \"concreteTypeId\": \"b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903\"\n            },\n            {\n              \"type\": \"u32\",\n              \"concreteTypeId\": \"d7649d428b9ff33d188ecbf38a7e4d8fd167fa01b2e10fe9a8f9308e52f1d7cc\"\n            }\n          ],\n          \"metadataTypes\": [],\n          \"functions\": [\n            {\n              \"inputs\": [\n                {\n                  \"name\": \"_arg\",\n                  \"concreteTypeId\": \"d7649d428b9ff33d188ecbf38a7e4d8fd167fa01b2e10fe9a8f9308e52f1d7cc\"\n                }\n              ],\n              \"name\": \"takes_u32_returns_bool\",\n              \"output\": \"b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903\",\n              \"attributes\": null\n            }\n          ],\n          \"loggedTypes\": [],\n          \"messagesTypes\": [],\n          \"configurables\": []\n        }\n        \"#,\n    ));\n\n    let wallet = launch_provider_and_get_wallet().await?;\n\n    let contract_instance = SimpleContract::new(ContractId::zeroed(), wallet);\n\n    let call_handler = contract_instance.methods().takes_u32_returns_bool(42_u32);\n    let encoded_args = call_handler.call.encoded_args.unwrap();\n\n    assert_eq!(encoded_args, [0, 0, 0, 42]);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn shared_types() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(\n            Contract(\n                name = \"ContractA\",\n                project = \"e2e/sway/bindings/sharing_types/contract_a\"\n            ),\n            Contract(\n                name = \"ContractB\",\n                project = \"e2e/sway/bindings/sharing_types/contract_b\"\n            ),\n        ),\n        Deploy(\n            name = \"contract_a\",\n            contract = \"ContractA\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n        Deploy(\n            name = \"contract_b\",\n            contract = \"ContractB\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n    {\n        let methods = contract_a.methods();\n\n        {\n            let shared_struct_2 = SharedStruct2 {\n                a: 11u32,\n                b: SharedStruct1 { a: 12u32 },\n            };\n            let shared_enum = SharedEnum::a(10u64);\n            let response = methods\n                .uses_shared_type(shared_struct_2.clone(), shared_enum.clone())\n                .call()\n                .await?\n                .value;\n\n            assert_eq!(response, (shared_struct_2, shared_enum));\n        }\n        {\n            let same_name_struct =\n                abigen_bindings::contract_a_mod::StructSameNameButDifferentInternals { a: 13u32 };\n            let same_name_enum =\n                abigen_bindings::contract_a_mod::EnumSameNameButDifferentInternals::a(14u32);\n            let response = methods\n                .uses_types_that_share_only_names(same_name_struct.clone(), same_name_enum.clone())\n                .call()\n                .await?\n                .value;\n            assert_eq!(response, (same_name_struct, same_name_enum));\n        }\n        {\n            let arg = UniqueStructToContractA {\n                a: SharedStruct2 {\n                    a: 15u32,\n                    b: SharedStruct1 { a: 5u8 },\n                },\n            };\n            let response = methods\n                .uses_shared_type_inside_owned_one(arg.clone())\n                .call()\n                .await?\n                .value;\n            assert_eq!(response, arg);\n        }\n    }\n    {\n        let methods = contract_b.methods();\n\n        {\n            let shared_struct_2 = SharedStruct2 {\n                a: 11u32,\n                b: SharedStruct1 { a: 12u32 },\n            };\n            let shared_enum = SharedEnum::a(10u64);\n            let response = methods\n                .uses_shared_type(shared_struct_2.clone(), shared_enum.clone())\n                .call()\n                .await?\n                .value;\n\n            assert_eq!(response, (shared_struct_2, shared_enum));\n        }\n        {\n            let same_name_struct =\n                abigen_bindings::contract_b_mod::StructSameNameButDifferentInternals { a: [13u64] };\n            let same_name_enum =\n                abigen_bindings::contract_b_mod::EnumSameNameButDifferentInternals::a([14u64]);\n            let response = methods\n                .uses_types_that_share_only_names(same_name_struct.clone(), same_name_enum.clone())\n                .call()\n                .await?\n                .value;\n            assert_eq!(response, (same_name_struct, same_name_enum));\n        }\n        {\n            let arg = UniqueStructToContractB {\n                a: SharedStruct2 {\n                    a: 15u32,\n                    b: SharedStruct1 { a: 5u8 },\n                },\n            };\n            let response = methods\n                .uses_shared_type_inside_owned_one(arg.clone())\n                .call()\n                .await?\n                .value;\n            assert_eq!(response, arg);\n        }\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn type_paths_respected() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"ContractA\",\n            project = \"e2e/sway/bindings/type_paths\"\n        )),\n        Deploy(\n            name = \"contract_a_instance\",\n            contract = \"ContractA\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n    {\n        let contract_a_type =\n            abigen_bindings::contract_a_mod::contract_a_types::VeryCommonNameStruct {\n                another_field: 10u32,\n            };\n\n        let rtn = contract_a_instance\n            .methods()\n            .test_function(AWrapper {\n                field: contract_a_type,\n            })\n            .call()\n            .await?\n            .value;\n\n        let rtn_using_the_other_type =\n            abigen_bindings::contract_a_mod::another_lib::VeryCommonNameStruct { field_a: 10u32 };\n\n        assert_eq!(rtn, rtn_using_the_other_type);\n    }\n\n    Ok(())\n}\n"
  },
  {
    "path": "e2e/tests/configurables.rs",
    "content": "use fuels::{\n    core::codec::EncoderConfig,\n    prelude::*,\n    types::{Bits256, SizedAsciiString, U256},\n};\n\n#[tokio::test]\nasync fn contract_default_configurables() -> Result<()> {\n    abigen!(Contract(\n        name = \"MyContract\",\n        abi = \"e2e/sway/contracts/configurables/out/release/configurables-abi.json\"\n    ));\n\n    let wallet = launch_provider_and_get_wallet().await?;\n\n    let contract_id = Contract::load_from(\n        \"sway/contracts/configurables/out/release/configurables.bin\",\n        LoadConfiguration::default(),\n    )?\n    .deploy_if_not_exists(&wallet, TxPolicies::default())\n    .await?\n    .contract_id;\n\n    let contract_instance = MyContract::new(contract_id, wallet.clone());\n\n    let response = contract_instance\n        .methods()\n        .return_configurables()\n        .call()\n        .await?;\n\n    let expected_value = (\n        true,\n        8,\n        16,\n        32,\n        63,\n        U256::from(8),\n        Bits256([1; 32]),\n        \"fuel\".try_into()?,\n        (8, true),\n        [253, 254, 255],\n        StructWithGeneric {\n            field_1: 8u8,\n            field_2: 16,\n        },\n        EnumWithGeneric::VariantOne(true),\n    );\n\n    assert_eq!(response.value, expected_value);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn script_default_configurables() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Script(\n            name = \"MyScript\",\n            project = \"e2e/sway/scripts/script_configurables\"\n        )),\n        LoadScript(\n            name = \"script_instance\",\n            script = \"MyScript\",\n            wallet = \"wallet\"\n        )\n    );\n\n    let mut script_instance = script_instance;\n    script_instance.convert_into_loader().await?;\n\n    let response = script_instance.main().call().await?;\n\n    let expected_value = (\n        true,\n        8,\n        16,\n        32,\n        63,\n        U256::from(8),\n        Bits256([1; 32]),\n        \"fuel\".try_into()?,\n        (8, true),\n        [253, 254, 255],\n        StructWithGeneric {\n            field_1: 8u8,\n            field_2: 16,\n        },\n        EnumWithGeneric::VariantOne(true),\n    );\n\n    assert_eq!(response.value, expected_value);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn contract_configurables() -> Result<()> {\n    // ANCHOR: contract_configurables\n    abigen!(Contract(\n        name = \"MyContract\",\n        abi = \"e2e/sway/contracts/configurables/out/release/configurables-abi.json\"\n    ));\n\n    let wallet = launch_provider_and_get_wallet().await?;\n\n    let str_4: SizedAsciiString<4> = \"FUEL\".try_into()?;\n    let new_struct = StructWithGeneric {\n        field_1: 16u8,\n        field_2: 32,\n    };\n    let new_enum = EnumWithGeneric::VariantTwo;\n\n    let configurables = MyContractConfigurables::default()\n        .with_BOOL(false)?\n        .with_U8(7)?\n        .with_U16(15)?\n        .with_U32(31)?\n        .with_U64(63)?\n        .with_U256(U256::from(8))?\n        .with_B256(Bits256([2; 32]))?\n        .with_STR_4(str_4.clone())?\n        .with_TUPLE((7, false))?\n        .with_ARRAY([252, 253, 254])?\n        .with_STRUCT(new_struct.clone())?\n        .with_ENUM(new_enum.clone())?;\n\n    let contract_id = Contract::load_from(\n        \"sway/contracts/configurables/out/release/configurables.bin\",\n        LoadConfiguration::default().with_configurables(configurables),\n    )?\n    .deploy_if_not_exists(&wallet, TxPolicies::default())\n    .await?\n    .contract_id;\n\n    let contract_instance = MyContract::new(contract_id, wallet.clone());\n    // ANCHOR_END: contract_configurables\n\n    let response = contract_instance\n        .methods()\n        .return_configurables()\n        .call()\n        .await?;\n\n    let expected_value = (\n        false,\n        7,\n        15,\n        31,\n        63,\n        U256::from(8),\n        Bits256([2; 32]),\n        str_4,\n        (7, false),\n        [252, 253, 254],\n        new_struct,\n        new_enum,\n    );\n\n    assert_eq!(response.value, expected_value);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn contract_manual_configurables() -> Result<()> {\n    setup_program_test!(\n        Abigen(Contract(\n            name = \"MyContract\",\n            project = \"e2e/sway/contracts/configurables\"\n        )),\n        Wallets(\"wallet\")\n    );\n\n    let str_4: SizedAsciiString<4> = \"FUEL\".try_into()?;\n    let new_struct = StructWithGeneric {\n        field_1: 16u8,\n        field_2: 32,\n    };\n    let new_enum = EnumWithGeneric::VariantTwo;\n\n    let configurables = MyContractConfigurables::default()\n        .with_BOOL(false)?\n        .with_U8(7)?\n        .with_U16(15)?\n        .with_U32(31)?\n        .with_U64(63)?\n        .with_U256(U256::from(8))?\n        .with_B256(Bits256([2; 32]))?\n        .with_STR_4(str_4.clone())?\n        .with_TUPLE((7, false))?\n        .with_ARRAY([252, 253, 254])?\n        .with_STRUCT(new_struct.clone())?\n        .with_ENUM(new_enum.clone())?;\n\n    let contract_id = Contract::load_from(\n        \"sway/contracts/configurables/out/release/configurables.bin\",\n        LoadConfiguration::default(),\n    )?\n    .with_configurables(configurables)\n    .deploy_if_not_exists(&wallet, TxPolicies::default())\n    .await?\n    .contract_id;\n\n    let contract_instance = MyContract::new(contract_id, wallet.clone());\n\n    let response = contract_instance\n        .methods()\n        .return_configurables()\n        .call()\n        .await?;\n\n    let expected_value = (\n        false,\n        7,\n        15,\n        31,\n        63,\n        U256::from(8),\n        Bits256([2; 32]),\n        str_4,\n        (7, false),\n        [252, 253, 254],\n        new_struct,\n        new_enum,\n    );\n\n    assert_eq!(response.value, expected_value);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn script_configurables() -> Result<()> {\n    // ANCHOR: script_configurables\n    abigen!(Script(\n        name = \"MyScript\",\n        abi = \"e2e/sway/scripts/script_configurables/out/release/script_configurables-abi.json\"\n    ));\n\n    let wallet = launch_provider_and_get_wallet().await?;\n    let bin_path = \"sway/scripts/script_configurables/out/release/script_configurables.bin\";\n    let instance = MyScript::new(wallet, bin_path);\n\n    let str_4: SizedAsciiString<4> = \"FUEL\".try_into()?;\n    let new_struct = StructWithGeneric {\n        field_1: 16u8,\n        field_2: 32,\n    };\n    let new_enum = EnumWithGeneric::VariantTwo;\n\n    let configurables = MyScriptConfigurables::new(EncoderConfig {\n        max_tokens: 5,\n        ..Default::default()\n    })\n    .with_BOOL(false)?\n    .with_U8(7)?\n    .with_U16(15)?\n    .with_U32(31)?\n    .with_U64(63)?\n    .with_U256(U256::from(8))?\n    .with_B256(Bits256([2; 32]))?\n    .with_STR_4(str_4.clone())?\n    .with_TUPLE((7, false))?\n    .with_ARRAY([252, 253, 254])?\n    .with_STRUCT(new_struct.clone())?\n    .with_ENUM(new_enum.clone())?;\n\n    let response = instance\n        .with_configurables(configurables)\n        .main()\n        .call()\n        .await?;\n    // ANCHOR_END: script_configurables\n\n    let expected_value = (\n        false,\n        7,\n        15,\n        31,\n        63,\n        U256::from(8),\n        Bits256([2; 32]),\n        str_4,\n        (7, false),\n        [252, 253, 254],\n        new_struct,\n        new_enum,\n    );\n\n    assert_eq!(response.value, expected_value);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn configurable_encoder_config_is_applied() {\n    abigen!(Script(\n        name = \"MyScript\",\n        abi = \"e2e/sway/scripts/script_configurables/out/release/script_configurables-abi.json\"\n    ));\n\n    let new_struct = StructWithGeneric {\n        field_1: 16u8,\n        field_2: 32,\n    };\n\n    {\n        let _configurables = MyScriptConfigurables::default()\n            .with_STRUCT(new_struct.clone())\n            .expect(\"no encoder config, it works\");\n    }\n    {\n        let encoder_config = EncoderConfig {\n            max_tokens: 1,\n            ..Default::default()\n        };\n\n        // Fails when a wrong encoder config is set\n        let configurables_error = MyScriptConfigurables::new(encoder_config)\n            .with_STRUCT(new_struct)\n            .expect_err(\"should error\");\n\n        assert!(\n            configurables_error\n                .to_string()\n                .contains(\"token limit `1` reached while encoding. Try increasing it\"),\n        )\n    }\n}\n"
  },
  {
    "path": "e2e/tests/contracts.rs",
    "content": "use std::time::Duration;\n\nuse fuel_tx::SubAssetId;\nuse fuels::{\n    accounts::signers::private_key::PrivateKeySigner,\n    core::codec::{DecoderConfig, EncoderConfig, calldata, encode_fn_selector},\n    prelude::*,\n    programs::DEFAULT_MAX_FEE_ESTIMATION_TOLERANCE,\n    tx::{\n        ConsensusParameters, ContractIdExt, ContractParameters, FeeParameters,\n        consensus_parameters::{ConsensusParametersV1, FeeParametersV1},\n    },\n    types::{\n        Bits256, Identity, SizedAsciiString, errors::transaction::Reason, input::Input,\n        output::Output,\n    },\n};\nuse rand::thread_rng;\nuse tokio::time::Instant;\n\n#[tokio::test]\nasync fn test_multiple_args() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TestContract\",\n            project = \"e2e/sway/contracts/contract_test\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TestContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    // Make sure we can call the contract with multiple arguments\n    let contract_methods = contract_instance.methods();\n    let response = contract_methods.get(5, 6).call().await?;\n\n    assert_eq!(response.value, 11);\n\n    let t = MyType { x: 5, y: 6 };\n    let response = contract_methods.get_alt(t.clone()).call().await?;\n    assert_eq!(response.value, t);\n\n    let response = contract_methods.get_single(5).call().await?;\n    assert_eq!(response.value, 5);\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_contract_calling_contract() -> Result<()> {\n    // Tests a contract call that calls another contract (FooCaller calls FooContract underneath)\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(\n            Contract(\n                name = \"LibContract\",\n                project = \"e2e/sway/contracts/lib_contract\"\n            ),\n            Contract(\n                name = \"LibContractCaller\",\n                project = \"e2e/sway/contracts/lib_contract_caller\"\n            ),\n        ),\n        Deploy(\n            name = \"lib_contract_instance\",\n            contract = \"LibContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n        Deploy(\n            name = \"lib_contract_instance2\",\n            contract = \"LibContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n        Deploy(\n            name = \"contract_caller_instance\",\n            contract = \"LibContractCaller\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n    let lib_contract_id = lib_contract_instance.contract_id();\n    let lib_contract_id2 = lib_contract_instance2.contract_id();\n\n    // Call the contract directly. It increments the given value.\n    let response = lib_contract_instance.methods().increment(42).call().await?;\n\n    assert_eq!(43, response.value);\n\n    let response = contract_caller_instance\n        .methods()\n        .increment_from_contracts(lib_contract_id, lib_contract_id2, 42)\n        // Note that the two lib_contract_instances have different types\n        .with_contracts(&[&lib_contract_instance, &lib_contract_instance2])\n        .call()\n        .await?;\n\n    assert_eq!(86, response.value);\n\n    // ANCHOR: external_contract\n    let response = contract_caller_instance\n        .methods()\n        .increment_from_contract(lib_contract_id, 42)\n        .with_contracts(&[&lib_contract_instance])\n        .call()\n        .await?;\n    // ANCHOR_END: external_contract\n\n    assert_eq!(43, response.value);\n\n    // ANCHOR: external_contract_ids\n    let response = contract_caller_instance\n        .methods()\n        .increment_from_contract(lib_contract_id, 42)\n        .with_contract_ids(&[lib_contract_id])\n        .call()\n        .await?;\n    // ANCHOR_END: external_contract_ids\n\n    assert_eq!(43, response.value);\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_reverting_transaction() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"RevertContract\",\n            project = \"e2e/sway/contracts/revert_transaction_error\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"RevertContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    let response = contract_instance\n        .methods()\n        .make_transaction_fail(true)\n        .call()\n        .await;\n\n    assert!(matches!(\n        response,\n        Err(Error::Transaction(Reason::Failure { revert_id, .. })) if revert_id == Some(128)\n    ));\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_multiple_read_calls() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"MultiReadContract\",\n            project = \"e2e/sway/contracts/multiple_read_calls\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"MultiReadContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    let contract_methods = contract_instance.methods();\n    contract_methods.store(42).call().await?;\n\n    // Use \"simulate\" because the methods don't actually\n    // run a transaction, but just a dry-run\n    let stored = contract_methods\n        .read()\n        .simulate(Execution::state_read_only())\n        .await?;\n\n    assert_eq!(stored.value, 42);\n\n    let stored = contract_methods\n        .read()\n        .simulate(Execution::state_read_only())\n        .await?;\n\n    assert_eq!(stored.value, 42);\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_multi_call_beginner() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TestContract\",\n            project = \"e2e/sway/contracts/contract_test\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TestContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    let contract_methods = contract_instance.methods();\n    let call_handler_1 = contract_methods.get_single(7);\n    let call_handler_2 = contract_methods.get_single(42);\n\n    let multi_call_handler = CallHandler::new_multi_call(wallet.clone())\n        .add_call(call_handler_1)\n        .add_call(call_handler_2);\n\n    let (val_1, val_2): (u64, u64) = multi_call_handler.call().await?.value;\n\n    assert_eq!(val_1, 7);\n    assert_eq!(val_2, 42);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_multi_call_pro() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TestContract\",\n            project = \"e2e/sway/contracts/contract_test\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TestContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    let my_type_1 = MyType { x: 1, y: 2 };\n    let my_type_2 = MyType { x: 3, y: 4 };\n\n    let contract_methods = contract_instance.methods();\n    let call_handler_1 = contract_methods.get_single(5);\n    let call_handler_2 = contract_methods.get_single(6);\n    let call_handler_3 = contract_methods.get_alt(my_type_1.clone());\n    let call_handler_4 = contract_methods.get_alt(my_type_2.clone());\n    let call_handler_5 = contract_methods.get_array([7; 2]);\n    let call_handler_6 = contract_methods.get_array([42; 2]);\n\n    let multi_call_handler = CallHandler::new_multi_call(wallet.clone())\n        .add_call(call_handler_1)\n        .add_call(call_handler_2)\n        .add_call(call_handler_3)\n        .add_call(call_handler_4)\n        .add_call(call_handler_5)\n        .add_call(call_handler_6);\n\n    let (val_1, val_2, type_1, type_2, array_1, array_2): (\n        u64,\n        u64,\n        MyType,\n        MyType,\n        [u64; 2],\n        [u64; 2],\n    ) = multi_call_handler.call().await?.value;\n\n    assert_eq!(val_1, 5);\n    assert_eq!(val_2, 6);\n    assert_eq!(type_1, my_type_1);\n    assert_eq!(type_2, my_type_2);\n    assert_eq!(array_1, [7; 2]);\n    assert_eq!(array_2, [42; 2]);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_contract_call_fee_estimation() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TestContract\",\n            project = \"e2e/sway/contracts/contract_test\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TestContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    let gas_limit = 800;\n    let tolerance = Some(0.2);\n    let block_horizon = Some(1);\n    let expected_script_gas = 800;\n    let expected_total_gas = 8463;\n    let expected_metered_bytes_size = 824;\n\n    let estimated_transaction_cost = contract_instance\n        .methods()\n        .initialize_counter(42)\n        .with_tx_policies(TxPolicies::default().with_script_gas_limit(gas_limit))\n        .estimate_transaction_cost(tolerance, block_horizon)\n        .await?;\n\n    assert_eq!(estimated_transaction_cost.script_gas, expected_script_gas);\n    assert_eq!(estimated_transaction_cost.total_gas, expected_total_gas);\n    assert_eq!(\n        estimated_transaction_cost.metered_bytes_size,\n        expected_metered_bytes_size\n    );\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn contract_call_has_same_estimated_and_used_gas() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TestContract\",\n            project = \"e2e/sway/contracts/contract_test\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TestContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n    let contract_methods = contract_instance.methods();\n\n    let tolerance = Some(0.0);\n    let block_horizon = Some(1);\n\n    let estimated_total_gas = contract_methods\n        .initialize_counter(42)\n        .estimate_transaction_cost(tolerance, block_horizon)\n        .await?\n        .total_gas;\n\n    let gas_used = contract_methods\n        .initialize_counter(42)\n        .call()\n        .await?\n        .tx_status\n        .total_gas;\n\n    assert_eq!(estimated_total_gas, gas_used);\n    Ok(())\n}\n\n#[tokio::test]\nasync fn mult_call_has_same_estimated_and_used_gas() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TestContract\",\n            project = \"e2e/sway/contracts/contract_test\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TestContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    let contract_methods = contract_instance.methods();\n    let call_handler_1 = contract_methods.initialize_counter(42);\n    let call_handler_2 = contract_methods.get_array([42; 2]);\n\n    let multi_call_handler = CallHandler::new_multi_call(wallet.clone())\n        .add_call(call_handler_1)\n        .add_call(call_handler_2);\n\n    let tolerance = Some(0.0);\n    let block_horizon = Some(1);\n    let estimated_total_gas = multi_call_handler\n        .estimate_transaction_cost(tolerance, block_horizon)\n        .await?\n        .total_gas;\n\n    let total_gas = multi_call_handler\n        .call::<(u64, [u64; 2])>()\n        .await?\n        .tx_status\n        .total_gas;\n\n    assert_eq!(estimated_total_gas, total_gas);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn contract_method_call_respects_maturity_and_expiration() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"BlockHeightContract\",\n            project = \"e2e/sway/contracts/transaction_block_height\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"BlockHeightContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n    let provider = wallet.provider();\n\n    let maturity = 10;\n    let expiration = 20;\n    let call_handler = contract_instance\n        .methods()\n        .calling_this_will_produce_a_block()\n        .with_tx_policies(\n            TxPolicies::default()\n                .with_maturity(maturity)\n                .with_expiration(expiration),\n        );\n\n    {\n        let err = call_handler\n            .clone()\n            .call()\n            .await\n            .expect_err(\"maturity not reached\");\n\n        assert!(err.to_string().contains(\"TransactionMaturity\"));\n    }\n    {\n        provider.produce_blocks(15, None).await?;\n        call_handler\n            .clone()\n            .call()\n            .await\n            .expect(\"should succeed. Block height between `maturity` and `expiration`\");\n    }\n    {\n        provider.produce_blocks(15, None).await?;\n        let err = call_handler.call().await.expect_err(\"expiration reached\");\n\n        assert!(err.to_string().contains(\"TransactionExpiration\"));\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_auth_msg_sender_from_sdk() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"AuthContract\",\n            project = \"e2e/sway/contracts/auth_testing_contract\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"AuthContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    // Contract returns true if `msg_sender()` matches `wallet.address()`.\n    let response = contract_instance\n        .methods()\n        .check_msg_sender(wallet.address())\n        .call()\n        .await?;\n\n    assert!(response.value);\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_large_return_data() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TestContract\",\n            project = \"e2e/sway/contracts/large_return_data\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TestContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    let contract_methods = contract_instance.methods();\n    let res = contract_methods.get_id().call().await?;\n\n    assert_eq!(\n        res.value.0,\n        [\n            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,\n            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255\n        ]\n    );\n\n    // One word-sized string\n    let res = contract_methods.get_small_string().call().await?;\n    assert_eq!(res.value, \"gggggggg\");\n\n    // Two word-sized string\n    let res = contract_methods.get_large_string().call().await?;\n    assert_eq!(res.value, \"ggggggggg\");\n\n    // Large struct will be bigger than a `WORD`.\n    let res = contract_methods.get_large_struct().call().await?;\n    assert_eq!(res.value.foo, 12);\n    assert_eq!(res.value.bar, 42);\n\n    // Array will be returned in `ReturnData`.\n    let res = contract_methods.get_large_array().call().await?;\n    assert_eq!(res.value, [1, 2]);\n\n    let res = contract_methods.get_contract_id().call().await?;\n\n    // First `value` is from `CallResponse`.\n    // Second `value` is from the `ContractId` type.\n    assert_eq!(\n        res.value,\n        ContractId::from([\n            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,\n            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255\n        ])\n    );\n    Ok(())\n}\n\n#[tokio::test]\nasync fn can_handle_function_called_new() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TestContract\",\n            project = \"e2e/sway/contracts/contract_test\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TestContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    let response = contract_instance.methods().new().call().await?.value;\n\n    assert_eq!(response, 12345);\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_contract_setup_macro_deploy_with_salt() -> Result<()> {\n    // ANCHOR: contract_setup_macro_multi\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(\n            Contract(\n                name = \"LibContract\",\n                project = \"e2e/sway/contracts/lib_contract\"\n            ),\n            Contract(\n                name = \"LibContractCaller\",\n                project = \"e2e/sway/contracts/lib_contract_caller\"\n            ),\n        ),\n        Deploy(\n            name = \"lib_contract_instance\",\n            contract = \"LibContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n        Deploy(\n            name = \"contract_caller_instance\",\n            contract = \"LibContractCaller\",\n            wallet = \"wallet\",\n        ),\n        Deploy(\n            name = \"contract_caller_instance2\",\n            contract = \"LibContractCaller\",\n            wallet = \"wallet\",\n        ),\n    );\n    let lib_contract_id = lib_contract_instance.contract_id();\n\n    let contract_caller_id = contract_caller_instance.contract_id();\n\n    let contract_caller_id2 = contract_caller_instance2.contract_id();\n\n    // Because we deploy with salt, we can deploy the same contract multiple times\n    assert_ne!(contract_caller_id, contract_caller_id2);\n\n    // The first contract can be called because they were deployed on the same provider\n    let response = contract_caller_instance\n        .methods()\n        .increment_from_contract(lib_contract_id, 42)\n        .with_contracts(&[&lib_contract_instance])\n        .call()\n        .await?;\n\n    assert_eq!(43, response.value);\n\n    let response = contract_caller_instance2\n        .methods()\n        .increment_from_contract(lib_contract_id, 42)\n        .with_contracts(&[&lib_contract_instance])\n        .call()\n        .await?;\n\n    assert_eq!(43, response.value);\n    // ANCHOR_END: contract_setup_macro_multi\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_wallet_getter() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TestContract\",\n            project = \"e2e/sway/contracts/contract_test\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TestContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    assert_eq!(contract_instance.account().address(), wallet.address());\n    //`contract_id()` is tested in\n    // async fn test_contract_calling_contract() -> Result<()> {\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_connect_wallet() -> Result<()> {\n    // ANCHOR: contract_setup_macro_manual_wallet\n    let config = WalletsConfig::new(Some(2), Some(1), Some(DEFAULT_COIN_AMOUNT));\n\n    let mut wallets = launch_custom_provider_and_get_wallets(config, None, None).await?;\n    let wallet = wallets.pop().unwrap();\n    let wallet_2 = wallets.pop().unwrap();\n\n    setup_program_test!(\n        Abigen(Contract(\n            name = \"TestContract\",\n            project = \"e2e/sway/contracts/contract_test\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TestContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n    // ANCHOR_END: contract_setup_macro_manual_wallet\n\n    // pay for call with wallet\n    let tx_policies = TxPolicies::default()\n        .with_tip(100)\n        .with_script_gas_limit(1_000_000);\n\n    contract_instance\n        .methods()\n        .initialize_counter(42)\n        .with_tx_policies(tx_policies)\n        .call()\n        .await?;\n\n    // confirm that funds have been deducted\n    let wallet_balance = wallet.get_asset_balance(&Default::default()).await?;\n    assert!(DEFAULT_COIN_AMOUNT as u128 > wallet_balance);\n\n    // pay for call with wallet_2\n    contract_instance\n        .with_account(wallet_2.clone())\n        .methods()\n        .initialize_counter(42)\n        .with_tx_policies(tx_policies)\n        .call()\n        .await?;\n\n    // confirm there are no changes to wallet, wallet_2 has been charged\n    let wallet_balance_second_call = wallet.get_asset_balance(&Default::default()).await?;\n    let wallet_2_balance = wallet_2.get_asset_balance(&Default::default()).await?;\n    assert_eq!(wallet_balance_second_call, wallet_balance);\n    assert!(DEFAULT_COIN_AMOUNT as u128 > wallet_2_balance);\n\n    Ok(())\n}\n\nasync fn setup_output_variable_estimation_test()\n-> Result<(Vec<Wallet>, [Identity; 3], AssetId, ContractId)> {\n    let wallet_config = WalletsConfig::new(Some(3), None, None);\n    let wallets = launch_custom_provider_and_get_wallets(wallet_config, None, None).await?;\n\n    let contract_id = Contract::load_from(\n        \"sway/contracts/token_ops/out/release/token_ops.bin\",\n        LoadConfiguration::default(),\n    )?\n    .deploy_if_not_exists(&wallets[0], TxPolicies::default())\n    .await?\n    .contract_id;\n\n    let mint_asset_id = contract_id.asset_id(&SubAssetId::zeroed());\n    let addresses = wallets\n        .iter()\n        .map(|wallet| wallet.address().into())\n        .collect::<Vec<_>>()\n        .try_into()\n        .unwrap();\n\n    Ok((wallets, addresses, mint_asset_id, contract_id))\n}\n\n#[tokio::test]\nasync fn test_output_variable_estimation() -> Result<()> {\n    abigen!(Contract(\n        name = \"MyContract\",\n        abi = \"e2e/sway/contracts/token_ops/out/release/token_ops-abi.json\"\n    ));\n\n    let (wallets, addresses, mint_asset_id, contract_id) =\n        setup_output_variable_estimation_test().await?;\n\n    let contract_instance = MyContract::new(contract_id, wallets[0].clone());\n    let contract_methods = contract_instance.methods();\n    let amount = 1000;\n\n    {\n        // Should fail due to lack of output variables\n        let response = contract_methods\n            .mint_to_addresses(amount, addresses)\n            .call()\n            .await;\n\n        assert!(matches!(\n            response,\n            Err(Error::Transaction(Reason::Failure { .. }))\n        ));\n    }\n\n    {\n        // Should add 3 output variables automatically\n        let _ = contract_methods\n            .mint_to_addresses(amount, addresses)\n            .with_variable_output_policy(VariableOutputPolicy::EstimateMinimum)\n            .call()\n            .await?;\n\n        for wallet in wallets.iter() {\n            let balance = wallet.get_asset_balance(&mint_asset_id).await?;\n            assert_eq!(balance, amount as u128);\n        }\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_output_variable_estimation_multicall() -> Result<()> {\n    abigen!(Contract(\n        name = \"MyContract\",\n        abi = \"e2e/sway/contracts/token_ops/out/release/token_ops-abi.json\"\n    ));\n\n    let (wallets, addresses, mint_asset_id, contract_id) =\n        setup_output_variable_estimation_test().await?;\n\n    let contract_instance = MyContract::new(contract_id, wallets[0].clone());\n    let contract_methods = contract_instance.methods();\n    const NUM_OF_CALLS: u64 = 3;\n    let amount = 1000;\n    let total_amount = amount * NUM_OF_CALLS;\n\n    let mut multi_call_handler = CallHandler::new_multi_call(wallets[0].clone());\n    for _ in 0..NUM_OF_CALLS {\n        let call_handler = contract_methods.mint_to_addresses(amount, addresses);\n        multi_call_handler = multi_call_handler.add_call(call_handler);\n    }\n\n    wallets[0]\n        .force_transfer_to_contract(\n            contract_id,\n            total_amount,\n            AssetId::zeroed(),\n            TxPolicies::default(),\n        )\n        .await\n        .unwrap();\n\n    let base_layer_address = Bits256([1u8; 32]);\n    let call_handler = contract_methods.send_message(base_layer_address, amount);\n    multi_call_handler = multi_call_handler.add_call(call_handler);\n\n    let _ = multi_call_handler\n        .with_variable_output_policy(VariableOutputPolicy::EstimateMinimum)\n        .call::<((), (), ())>()\n        .await?;\n\n    for wallet in wallets.iter() {\n        let balance = wallet.get_asset_balance(&mint_asset_id).await?;\n        assert_eq!(balance, 3 * amount as u128);\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_contract_instance_get_balances() -> Result<()> {\n    let mut rng = thread_rng();\n    let signer = PrivateKeySigner::random(&mut rng);\n    let (coins, asset_ids) = setup_multiple_assets_coins(signer.address(), 2, 4, 8);\n\n    let random_asset_id = asset_ids[1];\n    let provider = setup_test_provider(coins.clone(), vec![], None, None).await?;\n    let wallet = Wallet::new(signer, provider.clone());\n\n    setup_program_test!(\n        Abigen(Contract(\n            name = \"TestContract\",\n            project = \"e2e/sway/contracts/contract_test\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TestContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n    let contract_id = contract_instance.contract_id();\n\n    // Check the current balance of the contract with id 'contract_id'\n    let contract_balances = contract_instance.get_balances().await?;\n    assert!(contract_balances.is_empty());\n\n    // Transfer an amount to the contract\n    let amount = 8;\n    wallet\n        .force_transfer_to_contract(contract_id, amount, random_asset_id, TxPolicies::default())\n        .await?;\n\n    // Check that the contract now has 1 coin\n    let contract_balances = contract_instance.get_balances().await?;\n    assert_eq!(contract_balances.len(), 1);\n\n    let random_asset_balance = contract_balances.get(&random_asset_id).unwrap();\n    assert_eq!(*random_asset_balance, amount);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn contract_call_futures_implement_send() -> Result<()> {\n    use std::future::Future;\n\n    fn tokio_spawn_imitation<T>(_: T)\n    where\n        T: Future + Send + 'static,\n    {\n    }\n\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TestContract\",\n            project = \"e2e/sway/contracts/contract_test\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TestContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    tokio_spawn_imitation(async move {\n        contract_instance\n            .methods()\n            .initialize_counter(42)\n            .call()\n            .await\n            .unwrap();\n    });\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_contract_set_estimation() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(\n            Contract(\n                name = \"LibContract\",\n                project = \"e2e/sway/contracts/lib_contract\"\n            ),\n            Contract(\n                name = \"LibContractCaller\",\n                project = \"e2e/sway/contracts/lib_contract_caller\"\n            ),\n        ),\n        Deploy(\n            name = \"lib_contract_instance\",\n            contract = \"LibContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n        Deploy(\n            name = \"contract_caller_instance\",\n            contract = \"LibContractCaller\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n    let lib_contract_id = lib_contract_instance.contract_id();\n\n    let res = lib_contract_instance.methods().increment(42).call().await?;\n    assert_eq!(43, res.value);\n\n    {\n        // Should fail due to missing external contracts\n        let res = contract_caller_instance\n            .methods()\n            .increment_from_contract(lib_contract_id, 42)\n            .call()\n            .await;\n\n        assert!(matches!(\n            res,\n            Err(Error::Transaction(Reason::Failure { .. }))\n        ));\n    }\n\n    let res = contract_caller_instance\n        .methods()\n        .increment_from_contract(lib_contract_id, 42)\n        .determine_missing_contracts()\n        .await?\n        .call()\n        .await?;\n\n    assert_eq!(43, res.value);\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_output_variable_contract_id_estimation_multicall() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(\n            Contract(\n                name = \"LibContract\",\n                project = \"e2e/sway/contracts/lib_contract\"\n            ),\n            Contract(\n                name = \"LibContractCaller\",\n                project = \"e2e/sway/contracts/lib_contract_caller\"\n            ),\n            Contract(\n                name = \"TestContract\",\n                project = \"e2e/sway/contracts/contract_test\"\n            ),\n        ),\n        Deploy(\n            name = \"lib_contract_instance\",\n            contract = \"LibContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n        Deploy(\n            name = \"contract_caller_instance\",\n            contract = \"LibContractCaller\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n        Deploy(\n            name = \"contract_test_instance\",\n            contract = \"TestContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    let lib_contract_id = lib_contract_instance.contract_id();\n\n    let contract_methods = contract_caller_instance.methods();\n\n    let mut multi_call_handler =\n        CallHandler::new_multi_call(wallet.clone()).with_tx_policies(Default::default());\n\n    for _ in 0..3 {\n        let call_handler = contract_methods.increment_from_contract(lib_contract_id, 42);\n        multi_call_handler = multi_call_handler.add_call(call_handler);\n    }\n\n    // add call that does not need ContractId\n    let contract_methods = contract_test_instance.methods();\n    let call_handler = contract_methods.get(5, 6);\n\n    multi_call_handler = multi_call_handler.add_call(call_handler);\n\n    let call_response = multi_call_handler\n        .determine_missing_contracts()\n        .await?\n        .call::<(u64, u64, u64, u64)>()\n        .await?;\n\n    assert_eq!(call_response.value, (43, 43, 43, 11));\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_contract_call_with_non_default_max_input() -> Result<()> {\n    use fuels::{\n        tx::{ConsensusParameters, TxParameters},\n        types::coin::Coin,\n    };\n\n    let mut consensus_parameters = ConsensusParameters::default();\n    let tx_params = TxParameters::default()\n        .with_max_inputs(123)\n        .with_max_size(1_000_000);\n    consensus_parameters.set_tx_params(tx_params);\n    let contract_params = ContractParameters::default().with_contract_max_size(1_000_000);\n    consensus_parameters.set_contract_params(contract_params);\n\n    let mut rng = thread_rng();\n    let signer = PrivateKeySigner::random(&mut rng);\n\n    let coins: Vec<Coin> = setup_single_asset_coins(\n        signer.address(),\n        Default::default(),\n        DEFAULT_NUM_COINS,\n        DEFAULT_COIN_AMOUNT,\n    );\n    let chain_config = ChainConfig {\n        consensus_parameters: consensus_parameters.clone(),\n        ..ChainConfig::default()\n    };\n\n    let provider = setup_test_provider(coins, vec![], None, Some(chain_config)).await?;\n    let wallet = Wallet::new(signer, provider.clone());\n    assert_eq!(consensus_parameters, provider.consensus_parameters().await?);\n\n    setup_program_test!(\n        Abigen(Contract(\n            name = \"TestContract\",\n            project = \"e2e/sway/contracts/contract_test\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TestContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    let response = contract_instance.methods().get(5, 6).call().await?;\n\n    assert_eq!(response.value, 11);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_add_custom_assets() -> Result<()> {\n    let initial_amount = 100_000;\n    let asset_base = AssetConfig {\n        id: AssetId::zeroed(),\n        num_coins: 1,\n        coin_amount: initial_amount,\n    };\n\n    let asset_id_1 = AssetId::from([3u8; 32]);\n    let asset_1 = AssetConfig {\n        id: asset_id_1,\n        num_coins: 1,\n        coin_amount: initial_amount,\n    };\n\n    let asset_id_2 = AssetId::from([1u8; 32]);\n    let asset_2 = AssetConfig {\n        id: asset_id_2,\n        num_coins: 1,\n        coin_amount: initial_amount,\n    };\n\n    let assets = vec![asset_base, asset_1, asset_2];\n\n    let num_wallets = 2;\n    let wallet_config = WalletsConfig::new_multiple_assets(num_wallets, assets);\n    let mut wallets = launch_custom_provider_and_get_wallets(wallet_config, None, None).await?;\n    let wallet_1 = wallets.pop().unwrap();\n    let wallet_2 = wallets.pop().unwrap();\n\n    setup_program_test!(\n        Abigen(Contract(\n            name = \"MyContract\",\n            project = \"e2e/sway/contracts/contract_test\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"MyContract\",\n            wallet = \"wallet_1\",\n            random_salt = false,\n        ),\n    );\n\n    let amount_1 = 5000;\n    let amount_2 = 3000;\n    let response = contract_instance\n        .methods()\n        .get(5, 6)\n        .add_custom_asset(asset_id_1, amount_1, Some(wallet_2.address()))\n        .add_custom_asset(asset_id_2, amount_2, Some(wallet_2.address()))\n        .call()\n        .await?;\n\n    assert_eq!(response.value, 11);\n\n    let balance_asset_1 = wallet_1.get_asset_balance(&asset_id_1).await?;\n    let balance_asset_2 = wallet_1.get_asset_balance(&asset_id_2).await?;\n    assert_eq!(balance_asset_1, (initial_amount - amount_1) as u128);\n    assert_eq!(balance_asset_2, (initial_amount - amount_2) as u128);\n\n    let balance_asset_1 = wallet_2.get_asset_balance(&asset_id_1).await?;\n    let balance_asset_2 = wallet_2.get_asset_balance(&asset_id_2).await?;\n    assert_eq!(balance_asset_1, (initial_amount + amount_1) as u128);\n    assert_eq!(balance_asset_2, (initial_amount + amount_2) as u128);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn contract_load_error_messages() {\n    {\n        let binary_path = \"sway/contracts/contract_test/out/release/no_file_on_path.bin\";\n        let expected_error = format!(\"io: file \\\"{binary_path}\\\" does not exist\");\n\n        let error = Contract::load_from(binary_path, LoadConfiguration::default())\n            .expect_err(\"should have failed\");\n\n        assert_eq!(error.to_string(), expected_error);\n    }\n    {\n        let binary_path = \"sway/contracts/contract_test/out/release/contract_test-abi.json\";\n        let expected_error = format!(\"expected \\\"{binary_path}\\\" to have '.bin' extension\");\n\n        let error = Contract::load_from(binary_path, LoadConfiguration::default())\n            .expect_err(\"should have failed\");\n\n        assert_eq!(error.to_string(), expected_error);\n    }\n}\n\n#[tokio::test]\nasync fn test_payable_annotation() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TestContract\",\n            project = \"e2e/sway/contracts/payable_annotation\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TestContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    let contract_methods = contract_instance.methods();\n\n    let response = contract_methods\n        .payable()\n        .call_params(\n            CallParameters::default()\n                .with_amount(100)\n                .with_gas_forwarded(20_000),\n        )?\n        .call()\n        .await?;\n\n    assert_eq!(response.value, 42);\n\n    // ANCHOR: non_payable_params\n    let err = contract_methods\n        .non_payable()\n        .call_params(CallParameters::default().with_amount(100))\n        .expect_err(\"should return error\");\n\n    assert!(matches!(err, Error::Other(s) if s.contains(\"assets forwarded to non-payable method\")));\n    // ANCHOR_END: non_payable_params\n\n    let response = contract_methods\n        .non_payable()\n        .call_params(CallParameters::default().with_gas_forwarded(20_000))?\n        .call()\n        .await?;\n\n    assert_eq!(response.value, 42);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn multi_call_from_calls_with_different_account_types() -> Result<()> {\n    use fuels::prelude::*;\n\n    abigen!(Contract(\n        name = \"MyContract\",\n        abi = \"e2e/sway/contracts/contract_test/out/release/contract_test-abi.json\"\n    ));\n\n    let wallet = launch_provider_and_get_wallet().await?;\n    let predicate = Predicate::from_code(vec![]);\n\n    let contract_methods_wallet = MyContract::new(ContractId::default(), wallet.clone()).methods();\n    let contract_methods_predicate = MyContract::new(ContractId::default(), predicate).methods();\n\n    let call_handler_1 = contract_methods_wallet.initialize_counter(42);\n    let call_handler_2 = contract_methods_predicate.get_array([42; 2]);\n\n    let _multi_call_handler = CallHandler::new_multi_call(wallet)\n        .add_call(call_handler_1)\n        .add_call(call_handler_2);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn low_level_call() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(\n            Contract(\n                name = \"MyCallerContract\",\n                project = \"e2e/sway/contracts/low_level_caller\"\n            ),\n            Contract(\n                name = \"MyTargetContract\",\n                project = \"e2e/sway/contracts/contract_test\"\n            ),\n        ),\n        Deploy(\n            name = \"caller_contract_instance\",\n            contract = \"MyCallerContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n        Deploy(\n            name = \"target_contract_instance\",\n            contract = \"MyTargetContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n    {\n        let function_selector = encode_fn_selector(\"initialize_counter\");\n        let call_data = calldata!(42u64)?;\n        caller_contract_instance\n            .methods()\n            .call_low_level_call(\n                target_contract_instance.id(),\n                Bytes(function_selector),\n                Bytes(call_data),\n            )\n            .determine_missing_contracts()\n            .await?\n            .call()\n            .await?;\n\n        let response = target_contract_instance\n            .methods()\n            .read_counter()\n            .call()\n            .await?;\n        assert_eq!(response.value, 42);\n    }\n    {\n        let function_selector = encode_fn_selector(\"set_value_multiple_complex\");\n        let call_data = calldata!(\n            MyStruct {\n                a: true,\n                b: [1, 2, 3],\n            },\n            SizedAsciiString::<4>::try_from(\"fuel\")?\n        )?;\n\n        caller_contract_instance\n            .methods()\n            .call_low_level_call(\n                target_contract_instance.id(),\n                Bytes(function_selector),\n                Bytes(call_data),\n            )\n            .determine_missing_contracts()\n            .await?\n            .call()\n            .await?;\n\n        let result_uint = target_contract_instance\n            .methods()\n            .read_counter()\n            .call()\n            .await?\n            .value;\n\n        let result_bool = target_contract_instance\n            .methods()\n            .get_bool_value()\n            .call()\n            .await?\n            .value;\n\n        let result_str = target_contract_instance\n            .methods()\n            .get_str_value()\n            .call()\n            .await?\n            .value;\n\n        assert_eq!(result_uint, 2);\n        assert!(result_bool);\n        assert_eq!(result_str, \"fuel\");\n    }\n\n    Ok(())\n}\n\n#[cfg(any(not(feature = \"fuel-core-lib\"), feature = \"rocksdb\"))]\n#[test]\nfn db_rocksdb() {\n    use std::fs;\n\n    use fuels::{\n        accounts::wallet::Wallet,\n        client::{PageDirection, PaginationRequest},\n        prelude::{DEFAULT_COIN_AMOUNT, DbType, Error, ViewOnlyAccount, setup_test_provider},\n    };\n\n    let temp_dir = tempfile::tempdir().expect(\"failed to make tempdir\");\n    let temp_database_path = temp_dir.path().join(\"db\");\n\n    tokio::runtime::Runtime::new()\n        .expect(\"tokio runtime failed\")\n        .block_on(async {\n            let _ = temp_dir;\n            let signer = PrivateKeySigner::new(\n                \"0x4433d156e8c53bf5b50af07aa95a29436f29a94e0ccc5d58df8e57bdc8583c32\"\n                    .parse()\n                    .unwrap(),\n            );\n\n            const NUMBER_OF_ASSETS: u64 = 2;\n            let node_config = NodeConfig {\n                database_type: DbType::RocksDb(Some(temp_database_path.clone())),\n                ..NodeConfig::default()\n            };\n\n            let chain_config = ChainConfig {\n                consensus_parameters: Default::default(),\n                ..ChainConfig::local_testnet()\n            };\n\n            let (coins, _) = setup_multiple_assets_coins(\n                signer.address(),\n                NUMBER_OF_ASSETS,\n                DEFAULT_NUM_COINS,\n                DEFAULT_COIN_AMOUNT,\n            );\n\n            let provider =\n                setup_test_provider(coins.clone(), vec![], Some(node_config), Some(chain_config))\n                    .await?;\n\n            provider.produce_blocks(2, None).await?;\n\n            Ok::<(), Error>(())\n        })\n        .unwrap();\n\n    // The runtime needs to be terminated because the node can currently only be killed when the runtime itself shuts down.\n\n    tokio::runtime::Runtime::new()\n        .expect(\"tokio runtime failed\")\n        .block_on(async {\n            let node_config = NodeConfig {\n                database_type: DbType::RocksDb(Some(temp_database_path.clone())),\n                ..NodeConfig::default()\n            };\n\n            let provider = setup_test_provider(vec![], vec![], Some(node_config), None).await?;\n            // the same wallet that was used when rocksdb was built. When we connect it to the provider, we expect it to have the same amount of assets\n            let signer = PrivateKeySigner::new(\n                \"0x4433d156e8c53bf5b50af07aa95a29436f29a94e0ccc5d58df8e57bdc8583c32\"\n                    .parse()\n                    .unwrap(),\n            );\n            let wallet = Wallet::new(signer, provider.clone());\n\n            let blocks = provider\n                .get_blocks(PaginationRequest {\n                    cursor: None,\n                    results: 10,\n                    direction: PageDirection::Forward,\n                })\n                .await?\n                .results;\n\n            assert_eq!(blocks.len(), 3);\n            assert_eq!(\n                *wallet.get_balances().await?.iter().next().unwrap().1,\n                DEFAULT_COIN_AMOUNT as u128\n            );\n            assert_eq!(\n                *wallet.get_balances().await?.iter().next().unwrap().1,\n                DEFAULT_COIN_AMOUNT as u128\n            );\n            assert_eq!(wallet.get_balances().await?.len(), 2);\n\n            fs::remove_dir_all(\n                temp_database_path\n                    .parent()\n                    .expect(\"db parent folder does not exist\"),\n            )?;\n\n            Ok::<(), Error>(())\n        })\n        .unwrap();\n}\n\n#[tokio::test]\nasync fn can_configure_decoding_of_contract_return() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"MyContract\",\n            project = \"e2e/sway/contracts/needs_custom_decoder\"\n        ),),\n        Deploy(\n            contract = \"MyContract\",\n            name = \"contract_instance\",\n            wallet = \"wallet\",\n            random_salt = false,\n        )\n    );\n\n    let methods = contract_instance.methods();\n    {\n        // Single call: Will not work if max_tokens not big enough\n        methods.i_return_a_1k_el_array().with_decoder_config(DecoderConfig{max_tokens: 100, ..Default::default()}).call().await.expect_err(\n             \"should have failed because there are more tokens than what is supported by default\",\n         );\n    }\n    {\n        // Single call: Works when limit is bumped\n        let result = methods\n            .i_return_a_1k_el_array()\n            .with_decoder_config(DecoderConfig {\n                max_tokens: 1001,\n                ..Default::default()\n            })\n            .call()\n            .await?\n            .value;\n\n        assert_eq!(result, [0; 1000]);\n    }\n    {\n        // Multi call: Will not work if max_tokens not big enough\n        CallHandler::new_multi_call(wallet.clone())\n         .add_call(methods.i_return_a_1k_el_array())\n         .with_decoder_config(DecoderConfig { max_tokens: 100, ..Default::default() })\n         .call::<([u8; 1000],)>().await.expect_err(\n             \"should have failed because there are more tokens than what is supported by default\",\n         );\n    }\n    {\n        // Multi call: Works when configured\n        CallHandler::new_multi_call(wallet.clone())\n            .add_call(methods.i_return_a_1k_el_array())\n            .with_decoder_config(DecoderConfig {\n                max_tokens: 1001,\n                ..Default::default()\n            })\n            .call::<([u8; 1000],)>()\n            .await\n            .unwrap();\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_contract_submit_and_response() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TestContract\",\n            project = \"e2e/sway/contracts/contract_test\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TestContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    let contract_methods = contract_instance.methods();\n\n    let submitted_tx = contract_methods.get(1, 2).submit().await?;\n    tokio::time::sleep(Duration::from_millis(500)).await;\n    let value = submitted_tx.response().await?.value;\n\n    assert_eq!(value, 3);\n\n    let contract_methods = contract_instance.methods();\n    let call_handler_1 = contract_methods.get_single(7);\n    let call_handler_2 = contract_methods.get_single(42);\n\n    let multi_call_handler = CallHandler::new_multi_call(wallet.clone())\n        .add_call(call_handler_1)\n        .add_call(call_handler_2);\n\n    let handle = multi_call_handler.submit().await?;\n    tokio::time::sleep(Duration::from_millis(500)).await;\n    let (val_1, val_2): (u64, u64) = handle.response().await?.value;\n\n    assert_eq!(val_1, 7);\n    assert_eq!(val_2, 42);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_heap_type_multicall() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(\n            Contract(\n                name = \"TestContract\",\n                project = \"e2e/sway/contracts/contract_test\"\n            ),\n            Contract(\n                name = \"VectorOutputContract\",\n                project = \"e2e/sway/types/contracts/vector_output\"\n            )\n        ),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"VectorOutputContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n        Deploy(\n            name = \"contract_instance_2\",\n            contract = \"TestContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    {\n        let call_handler_1 = contract_instance.methods().u8_in_vec(5);\n        let call_handler_2 = contract_instance_2.methods().get_single(7);\n        let call_handler_3 = contract_instance.methods().u8_in_vec(3);\n\n        let multi_call_handler = CallHandler::new_multi_call(wallet.clone())\n            .add_call(call_handler_1)\n            .add_call(call_handler_2)\n            .add_call(call_handler_3);\n\n        let (val_1, val_2, val_3): (Vec<u8>, u64, Vec<u8>) = multi_call_handler.call().await?.value;\n\n        assert_eq!(val_1, vec![0, 1, 2, 3, 4]);\n        assert_eq!(val_2, 7);\n        assert_eq!(val_3, vec![0, 1, 2]);\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn heap_types_correctly_offset_in_create_transactions_w_storage_slots() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Predicate(\n            name = \"MyPredicate\",\n            project = \"e2e/sway/types/predicates/predicate_vector\"\n        ),),\n    );\n\n    let provider = wallet.provider().clone();\n    let data = MyPredicateEncoder::default().encode_data(18, 24, vec![2, 4, 42])?;\n    let predicate = Predicate::load_from(\n        \"sway/types/predicates/predicate_vector/out/release/predicate_vector.bin\",\n    )?\n    .with_data(data)\n    .with_provider(provider);\n\n    wallet\n        .transfer(\n            predicate.address(),\n            10_000,\n            AssetId::zeroed(),\n            TxPolicies::default(),\n        )\n        .await?;\n\n    // if the contract is successfully deployed then the predicate was unlocked. This further means\n    // the offsets were setup correctly since the predicate uses heap types in its arguments.\n    // Storage slots were loaded automatically by default\n    Contract::load_from(\n        \"sway/contracts/storage/out/release/storage.bin\",\n        LoadConfiguration::default(),\n    )?\n    .deploy_if_not_exists(&predicate, TxPolicies::default())\n    .await?;\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_arguments_with_gas_forwarded() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(\n            Contract(\n                name = \"TestContract\",\n                project = \"e2e/sway/contracts/contract_test\"\n            ),\n            Contract(\n                name = \"VectorOutputContract\",\n                project = \"e2e/sway/types/contracts/vectors\"\n            )\n        ),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TestContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n        Deploy(\n            name = \"contract_instance_2\",\n            contract = \"VectorOutputContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    let x = 128;\n    let vec_input = vec![0, 1, 2];\n    {\n        let response = contract_instance\n            .methods()\n            .get_single(x)\n            .call_params(CallParameters::default().with_gas_forwarded(4096))?\n            .call()\n            .await?;\n\n        assert_eq!(response.value, x);\n    }\n    {\n        contract_instance_2\n            .methods()\n            .u32_vec(vec_input.clone())\n            .call_params(CallParameters::default().with_gas_forwarded(4096))?\n            .call()\n            .await?;\n    }\n    {\n        let call_handler_1 = contract_instance.methods().get_single(x);\n        let call_handler_2 = contract_instance_2.methods().u32_vec(vec_input);\n\n        let multi_call_handler = CallHandler::new_multi_call(wallet.clone())\n            .add_call(call_handler_1)\n            .add_call(call_handler_2);\n\n        let (value, _): (u64, ()) = multi_call_handler.call().await?.value;\n\n        assert_eq!(value, x);\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn contract_custom_call_no_signatures_strategy() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TestContract\",\n            project = \"e2e/sway/contracts/contract_test\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TestContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n    let provider = wallet.provider();\n\n    let counter = 42;\n    let call_handler = contract_instance.methods().initialize_counter(counter);\n\n    let mut tb = call_handler.transaction_builder().await?;\n\n    let base_asset_id = *provider.consensus_parameters().await?.base_asset_id();\n\n    let amount = 10;\n    let consensus_parameters = provider.consensus_parameters().await?;\n    let new_base_inputs = wallet\n        .get_asset_inputs_for_amount(base_asset_id, amount, None)\n        .await?;\n    tb.inputs_mut().extend(new_base_inputs);\n    tb.outputs_mut()\n        .push(Output::change(wallet.address(), 0, base_asset_id));\n\n    // ANCHOR: tb_no_signatures_strategy\n    let mut tx = tb\n        .with_build_strategy(ScriptBuildStrategy::NoSignatures)\n        .build(provider)\n        .await?;\n    // ANCHOR: tx_sign_with\n    tx.sign_with(wallet.signer(), consensus_parameters.chain_id())\n        .await?;\n    // ANCHOR_END: tx_sign_with\n    // ANCHOR_END: tb_no_signatures_strategy\n\n    let tx_id = provider.send_transaction(tx).await?;\n    tokio::time::sleep(Duration::from_millis(500)).await;\n\n    let tx_status = provider.tx_status(&tx_id).await?;\n\n    let response = call_handler.get_response(tx_status)?;\n\n    assert_eq!(counter, response.value);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn contract_encoder_config_is_applied() -> Result<()> {\n    setup_program_test!(\n        Abigen(Contract(\n            name = \"TestContract\",\n            project = \"e2e/sway/contracts/contract_test\"\n        )),\n        Wallets(\"wallet\")\n    );\n    let contract_id = Contract::load_from(\n        \"sway/contracts/contract_test/out/release/contract_test.bin\",\n        LoadConfiguration::default(),\n    )?\n    .deploy_if_not_exists(&wallet, TxPolicies::default())\n    .await?\n    .contract_id;\n\n    let instance = TestContract::new(contract_id, wallet.clone());\n\n    {\n        let _encoding_ok = instance\n            .methods()\n            .get(0, 1)\n            .call()\n            .await\n            .expect(\"should not fail as it uses the default encoder config\");\n    }\n    {\n        let encoder_config = EncoderConfig {\n            max_tokens: 1,\n            ..Default::default()\n        };\n        let instance_with_encoder_config = instance.with_encoder_config(encoder_config);\n\n        // uses 2 tokens when 1 is the limit\n        let encoding_error = instance_with_encoder_config\n            .methods()\n            .get(0, 1)\n            .call()\n            .await\n            .expect_err(\"should error\");\n\n        assert!(encoding_error.to_string().contains(\n            \"cannot encode contract call arguments: codec: token limit `1` reached while encoding.\"\n        ));\n\n        let encoding_error = instance_with_encoder_config\n            .methods()\n            .get(0, 1)\n            .simulate(Execution::realistic())\n            .await\n            .expect_err(\"should error\");\n\n        assert!(encoding_error.to_string().contains(\n            \"cannot encode contract call arguments: codec: token limit `1` reached while encoding.\"\n        ));\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_reentrant_calls() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"LibContractCaller\",\n            project = \"e2e/sway/contracts/lib_contract_caller\"\n        ),),\n        Deploy(\n            name = \"contract_caller_instance\",\n            contract = \"LibContractCaller\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    let contract_id = contract_caller_instance.contract_id();\n    let response = contract_caller_instance\n        .methods()\n        .re_entrant(contract_id, true)\n        .call()\n        .await?;\n\n    assert_eq!(42, response.value);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn msg_sender_gas_estimation_issue() {\n    // Gas estimation requires an input of the base asset. If absent, a fake input is\n    // added. However, if a non-base coin is present and the fake input introduces a\n    // second owner, it causes the `msg_sender` sway fn to fail. This leads\n    // to a premature failure in gas estimation, risking transaction failure due to\n    // a low gas limit.\n    let mut rng = thread_rng();\n    let signer = PrivateKeySigner::random(&mut rng);\n    let (coins, ids) =\n        setup_multiple_assets_coins(signer.address(), 2, DEFAULT_NUM_COINS, DEFAULT_COIN_AMOUNT);\n    let provider = setup_test_provider(coins, vec![], None, None)\n        .await\n        .unwrap();\n    let wallet = Wallet::new(signer, provider.clone());\n\n    setup_program_test!(\n        Abigen(Contract(\n            name = \"MyContract\",\n            project = \"e2e/sway/contracts/msg_methods\"\n        )),\n        Deploy(\n            contract = \"MyContract\",\n            name = \"contract_instance\",\n            wallet = \"wallet\",\n            random_salt = false,\n        )\n    );\n\n    let asset_id = ids[0];\n\n    // The fake coin won't be added if we add a base asset, so let's not do that\n    assert!(\n        asset_id\n            != *provider\n                .consensus_parameters()\n                .await\n                .unwrap()\n                .base_asset_id()\n    );\n    let call_params = CallParameters::default()\n        .with_amount(100)\n        .with_asset_id(asset_id);\n\n    contract_instance\n        .methods()\n        .message_sender()\n        .call_params(call_params)\n        .unwrap()\n        .call()\n        .await\n        .unwrap();\n}\n\n#[tokio::test]\nasync fn variable_output_estimation_is_optimized() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"MyContract\",\n            project = \"e2e/sway/contracts/var_outputs\"\n        )),\n        Deploy(\n            contract = \"MyContract\",\n            name = \"contract_instance\",\n            wallet = \"wallet\",\n            random_salt = false,\n        )\n    );\n\n    let contract_methods = contract_instance.methods();\n\n    let coins = 252;\n    let recipient = Identity::Address(wallet.address());\n    let start = Instant::now();\n    let _ = contract_methods\n        .mint(coins, recipient)\n        .with_variable_output_policy(VariableOutputPolicy::EstimateMinimum)\n        .call()\n        .await?;\n\n    // debug builds are slower (20x for `fuel-core-lib`, 4x for a release-fuel-core-binary)\n    // we won't validate in that case so we don't have to maintain two expectations\n    if !cfg!(debug_assertions) {\n        let elapsed = start.elapsed().as_secs();\n        let limit = 2;\n        if elapsed > limit {\n            panic!(\"Estimation took too long ({elapsed}). Limit is {limit}\");\n        }\n    }\n\n    Ok(())\n}\n\nfn config_for_high_price_node() -> (WalletsConfig, NodeConfig, ChainConfig) {\n    let wallet_config = WalletsConfig::new(None, None, None);\n    let fee_parameters = FeeParameters::V1(FeeParametersV1 {\n        gas_price_factor: 92000,\n        gas_per_byte: 63,\n    });\n    let consensus_parameters = ConsensusParameters::V1(ConsensusParametersV1 {\n        fee_params: fee_parameters,\n        ..Default::default()\n    });\n\n    let node_config = NodeConfig {\n        starting_gas_price: 1100,\n        ..NodeConfig::default()\n    };\n\n    let chain_config = ChainConfig {\n        consensus_parameters,\n        ..ChainConfig::default()\n    };\n\n    (wallet_config, node_config, chain_config)\n}\n\nasync fn setup_node_with_high_price() -> Result<Vec<Wallet>> {\n    let (wallet_config, node_config, chain_config) = config_for_high_price_node();\n\n    let wallets = launch_custom_provider_and_get_wallets(\n        wallet_config,\n        Some(node_config),\n        Some(chain_config),\n    )\n    .await?;\n\n    Ok(wallets)\n}\n\n#[cfg(any(not(feature = \"fuel-core-lib\"), feature = \"rocksdb\"))]\nasync fn setup_node_with_high_price_historical_execution()\n-> Result<(Vec<Wallet>, tempfile::TempDir)> {\n    let (wallet_config, mut node_config, chain_config) = config_for_high_price_node();\n\n    let temp_dir = tempfile::tempdir().expect(\"failed to make tempdir\");\n    let temp_database_path = temp_dir.path().join(\"db\");\n\n    node_config.database_type = DbType::RocksDb(Some(temp_database_path));\n    node_config.historical_execution = true;\n\n    let wallets = launch_custom_provider_and_get_wallets(\n        wallet_config,\n        Some(node_config),\n        Some(chain_config),\n    )\n    .await?;\n\n    Ok((wallets, temp_dir))\n}\n\n#[tokio::test]\nasync fn simulations_can_be_made_without_coins() -> Result<()> {\n    abigen!(Contract(\n        name = \"MyContract\",\n        abi = \"e2e/sway/contracts/contract_test/out/release/contract_test-abi.json\"\n    ));\n\n    let wallet = setup_node_with_high_price().await?.pop().unwrap();\n\n    let contract_id = Contract::load_from(\n        \"sway/contracts/contract_test/out/release/contract_test.bin\",\n        LoadConfiguration::default(),\n    )?\n    .deploy_if_not_exists(&wallet, TxPolicies::default())\n    .await?\n    .contract_id;\n\n    let provider = wallet.provider().clone();\n    let no_funds_wallet = Wallet::random(&mut thread_rng(), provider);\n\n    let response = MyContract::new(contract_id, no_funds_wallet)\n        .methods()\n        .get(5, 6)\n        .simulate(Execution::state_read_only())\n        .await?;\n\n    assert_eq!(response.value, 11);\n\n    Ok(())\n}\n\n#[tokio::test]\n#[cfg(any(not(feature = \"fuel-core-lib\"), feature = \"rocksdb\"))]\nasync fn simulations_can_be_made_at_specific_block_height() -> Result<()> {\n    let (mut wallets, _temp_dir) = setup_node_with_high_price_historical_execution().await?;\n    let wallet = wallets.pop().unwrap();\n\n    setup_program_test!(\n        Abigen(Contract(\n            name = \"MyContract\",\n            project = \"e2e/sway/contracts/contract_test\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"MyContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n    let contract_id = contract_instance.contract_id();\n\n    let provider = wallet.provider();\n    let contract_methods = contract_instance.methods();\n\n    contract_methods.initialize_counter(42).call().await?;\n    provider.produce_blocks(5, None).await?;\n    let block_height = provider.latest_block_height().await?;\n\n    provider.produce_blocks(5, None).await?;\n    contract_methods.increment_counter(24).call().await?;\n\n    let no_funds_wallet = Wallet::random(&mut thread_rng(), provider.clone());\n    let no_funds_methods = MyContract::new(contract_id, no_funds_wallet).methods();\n    {\n        let response = no_funds_methods\n            .read_counter()\n            .simulate(Execution::state_read_only())\n            .await?;\n\n        assert_eq!(response.value, 66);\n    }\n    {\n        let response = no_funds_methods\n            .read_counter()\n            .simulate(Execution::state_read_only().at_height(block_height))\n            .await?;\n\n        assert_eq!(response.value, 42);\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn simulations_can_be_made_without_coins_multicall() -> Result<()> {\n    abigen!(Contract(\n        name = \"MyContract\",\n        abi = \"e2e/sway/contracts/contract_test/out/release/contract_test-abi.json\"\n    ));\n\n    let wallet = setup_node_with_high_price().await?.pop().unwrap();\n\n    let contract_id = Contract::load_from(\n        \"sway/contracts/contract_test/out/release/contract_test.bin\",\n        LoadConfiguration::default(),\n    )?\n    .deploy_if_not_exists(&wallet, TxPolicies::default())\n    .await?\n    .contract_id;\n\n    let provider = wallet.provider().clone();\n\n    let no_funds_wallet = Wallet::random(&mut thread_rng(), provider);\n    let contract_instance = MyContract::new(contract_id, no_funds_wallet.clone());\n\n    let contract_methods = contract_instance.methods();\n\n    let call_handler_1 = contract_methods.get(1, 2);\n    let call_handler_2 = contract_methods.get(3, 4);\n\n    let mut multi_call_handler = CallHandler::new_multi_call(no_funds_wallet)\n        .add_call(call_handler_1)\n        .add_call(call_handler_2);\n\n    let value: (u64, u64) = multi_call_handler\n        .simulate(Execution::state_read_only())\n        .await?\n        .value;\n\n    assert_eq!(value, (3, 7));\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn contract_call_with_non_zero_base_asset_id_and_tip() -> Result<()> {\n    use fuels::{prelude::*, tx::ConsensusParameters};\n\n    abigen!(Contract(\n        name = \"MyContract\",\n        abi = \"e2e/sway/contracts/contract_test/out/release/contract_test-abi.json\"\n    ));\n\n    let asset_id = AssetId::new([1; 32]);\n\n    let mut consensus_parameters = ConsensusParameters::default();\n    consensus_parameters.set_base_asset_id(asset_id);\n\n    let config = ChainConfig {\n        consensus_parameters,\n        ..Default::default()\n    };\n\n    let asset_base = AssetConfig {\n        id: asset_id,\n        num_coins: 1,\n        coin_amount: 10_000,\n    };\n\n    let wallet_config = WalletsConfig::new_multiple_assets(1, vec![asset_base]);\n    let wallets = launch_custom_provider_and_get_wallets(wallet_config, None, Some(config)).await?;\n    let wallet = wallets.first().expect(\"has wallet\");\n\n    let contract_id = Contract::load_from(\n        \"sway/contracts/contract_test/out/release/contract_test.bin\",\n        LoadConfiguration::default(),\n    )?\n    .deploy_if_not_exists(wallet, TxPolicies::default())\n    .await?\n    .contract_id;\n\n    let contract_instance = MyContract::new(contract_id, wallet.clone());\n\n    let response = contract_instance\n        .methods()\n        .initialize_counter(42)\n        .with_tx_policies(TxPolicies::default().with_tip(10))\n        .call()\n        .await?;\n\n    assert_eq!(42, response.value);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn max_fee_estimation_respects_tolerance() -> Result<()> {\n    use fuels::prelude::*;\n\n    let mut rng = rand::thread_rng();\n    let call_signer = PrivateKeySigner::random(&mut rng);\n\n    let call_coins = setup_single_asset_coins(call_signer.address(), AssetId::BASE, 1000, 1);\n\n    let deploy_signer = PrivateKeySigner::random(&mut rng);\n    let deploy_coins =\n        setup_single_asset_coins(deploy_signer.address(), AssetId::BASE, 1, 1_000_000);\n\n    let provider =\n        setup_test_provider([call_coins, deploy_coins].concat(), vec![], None, None).await?;\n\n    let call_wallet = Wallet::new(call_signer, provider.clone());\n    let deploy_wallet = Wallet::new(deploy_signer, provider.clone());\n\n    setup_program_test!(\n        Abigen(Contract(\n            name = \"MyContract\",\n            project = \"e2e/sway/contracts/contract_test\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            wallet = \"deploy_wallet\",\n            contract = \"MyContract\",\n            random_salt = false,\n        )\n    );\n    let contract_instance = contract_instance.with_account(call_wallet.clone());\n\n    let max_fee_from_tx = |tolerance: f32| {\n        let contract_instance = contract_instance.clone();\n        let provider = provider.clone();\n        async move {\n            let builder = contract_instance\n                .methods()\n                .initialize_counter(42)\n                .transaction_builder()\n                .await\n                .unwrap();\n\n            assert_eq!(\n                builder.max_fee_estimation_tolerance, DEFAULT_MAX_FEE_ESTIMATION_TOLERANCE,\n                \"Expected pre-set tolerance\"\n            );\n\n            builder\n                .with_max_fee_estimation_tolerance(tolerance)\n                .build(&provider)\n                .await\n                .unwrap()\n                .max_fee()\n                .unwrap()\n        }\n    };\n\n    let max_fee_from_builder = |tolerance: f32| {\n        let contract_instance = contract_instance.clone();\n        let provider = provider.clone();\n        async move {\n            contract_instance\n                .methods()\n                .initialize_counter(42)\n                .transaction_builder()\n                .await\n                .unwrap()\n                .with_max_fee_estimation_tolerance(tolerance)\n                .estimate_max_fee(&provider)\n                .await\n                .unwrap()\n        }\n    };\n\n    let base_amount_in_inputs = |tolerance: f32| {\n        let contract_instance = contract_instance.clone();\n        let call_wallet = &call_wallet;\n        async move {\n            let mut tb = contract_instance\n                .methods()\n                .initialize_counter(42)\n                .transaction_builder()\n                .await\n                .unwrap()\n                .with_max_fee_estimation_tolerance(tolerance);\n\n            call_wallet.adjust_for_fee(&mut tb, 0).await.unwrap();\n            tb.inputs\n                .iter()\n                .filter_map(|input: &Input| match input {\n                    Input::ResourceSigned { resource }\n                        if resource.coin_asset_id().unwrap() == AssetId::BASE =>\n                    {\n                        Some(resource.amount())\n                    }\n                    _ => None,\n                })\n                .sum::<u64>()\n        }\n    };\n\n    let no_increase_max_fee = max_fee_from_tx(0.0).await;\n    let increased_max_fee = max_fee_from_tx(2.00).await;\n\n    assert_eq!(\n        increased_max_fee as f64 / no_increase_max_fee as f64,\n        1.00 + 2.00\n    );\n\n    let no_increase_max_fee = max_fee_from_builder(0.0).await;\n    let increased_max_fee = max_fee_from_builder(2.00).await;\n    assert_eq!(\n        increased_max_fee as f64 / no_increase_max_fee as f64,\n        1.00 + 2.00\n    );\n\n    let normal_base_asset = base_amount_in_inputs(0.0).await;\n    let more_base_asset_due_to_bigger_tolerance = base_amount_in_inputs(5.00).await;\n    assert!(more_base_asset_due_to_bigger_tolerance > normal_base_asset);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn blob_contract_deployment() -> Result<()> {\n    abigen!(Contract(\n        name = \"MyContract\",\n        abi = \"e2e/sway/contracts/huge_contract/out/release/huge_contract-abi.json\"\n    ));\n\n    let contract_binary = \"sway/contracts/huge_contract/out/release/huge_contract.bin\";\n    let contract_size = std::fs::metadata(contract_binary)\n        .expect(\"contract file not found\")\n        .len();\n\n    assert!(\n        contract_size > 150_000,\n        \"the testnet size limit was around 100kB, we want a contract bigger than that to reflect prod (current: {contract_size}B)\"\n    );\n\n    let wallets =\n        launch_custom_provider_and_get_wallets(WalletsConfig::new(Some(2), None, None), None, None)\n            .await?;\n\n    let provider = wallets[0].provider().clone();\n\n    let consensus_parameters = provider.consensus_parameters().await?;\n\n    let contract_max_size = consensus_parameters.contract_params().contract_max_size();\n    assert!(\n        contract_size > contract_max_size,\n        \"this test should ideally be run with a contract bigger than the max contract size ({contract_max_size}B) so that we know deployment couldn't have happened without blobs\"\n    );\n\n    let contract = Contract::load_from(contract_binary, LoadConfiguration::default())?;\n\n    let contract_id = contract\n        .convert_to_loader(100_000)?\n        .deploy_if_not_exists(&wallets[0], TxPolicies::default())\n        .await?\n        .contract_id;\n\n    let contract_instance = MyContract::new(contract_id, wallets[0].clone());\n\n    let response = contract_instance.methods().something().call().await?.value;\n\n    assert_eq!(response, 1001);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn regular_contract_can_be_deployed() -> Result<()> {\n    // given\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"MyContract\",\n            project = \"e2e/sway/contracts/contract_test\"\n        )),\n    );\n\n    let contract_binary = \"sway/contracts/contract_test/out/release/contract_test.bin\";\n\n    // when\n    let contract_id = Contract::load_from(contract_binary, LoadConfiguration::default())?\n        .deploy_if_not_exists(&wallet, TxPolicies::default())\n        .await?\n        .contract_id;\n\n    // then\n    let contract_instance = MyContract::new(contract_id, wallet);\n\n    let response = contract_instance\n        .methods()\n        .read_counter()\n        .call()\n        .await?\n        .value;\n\n    assert_eq!(response, 0);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn unuploaded_loader_can_be_deployed_directly() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"MyContract\",\n            project = \"e2e/sway/contracts/huge_contract\"\n        )),\n    );\n\n    let contract_binary = \"sway/contracts/huge_contract/out/release/huge_contract.bin\";\n\n    let contract_id = Contract::load_from(contract_binary, LoadConfiguration::default())?\n        .convert_to_loader(1024)?\n        .deploy_if_not_exists(&wallet, TxPolicies::default())\n        .await?\n        .contract_id;\n\n    let contract_instance = MyContract::new(contract_id, wallet);\n\n    let response = contract_instance.methods().something().call().await?.value;\n\n    assert_eq!(response, 1001);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn unuploaded_loader_can_upload_blobs_separately_then_deploy() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"MyContract\",\n            project = \"e2e/sway/contracts/huge_contract\"\n        )),\n    );\n\n    let contract_binary = \"sway/contracts/huge_contract/out/release/huge_contract.bin\";\n\n    let contract = Contract::load_from(contract_binary, LoadConfiguration::default())?\n        .convert_to_loader(1024)?\n        .upload_blobs(&wallet, TxPolicies::default())\n        .await?;\n\n    let blob_ids = contract.blob_ids();\n\n    // if this were an example for the user we'd just call `deploy` on the contract above\n    // this way we are testing that the blobs were really deployed above, otherwise the following\n    // would fail\n\n    let contract_id = Contract::loader_from_blob_ids(\n        blob_ids.to_vec(),\n        contract.salt(),\n        contract.storage_slots().to_vec(),\n    )?\n    .deploy_if_not_exists(&wallet, TxPolicies::default())\n    .await?\n    .contract_id;\n\n    let contract_instance = MyContract::new(contract_id, wallet);\n    let response = contract_instance.methods().something().call().await?.value;\n    assert_eq!(response, 1001);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn loader_blob_already_uploaded_not_an_issue() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"MyContract\",\n            project = \"e2e/sway/contracts/huge_contract\"\n        )),\n    );\n\n    let contract_binary = \"sway/contracts/huge_contract/out/release/huge_contract.bin\";\n    let contract = Contract::load_from(contract_binary, LoadConfiguration::default())?\n        .convert_to_loader(1024)?;\n\n    // this will upload blobs\n    contract\n        .clone()\n        .upload_blobs(&wallet, TxPolicies::default())\n        .await?;\n\n    // this will try to upload the blobs but skip upon encountering an error\n    let contract_id = contract\n        .deploy_if_not_exists(&wallet, TxPolicies::default())\n        .await?\n        .contract_id;\n\n    let contract_instance = MyContract::new(contract_id, wallet);\n    let response = contract_instance.methods().something().call().await?.value;\n    assert_eq!(response, 1001);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn loader_works_via_proxy() -> Result<()> {\n    let wallet = launch_provider_and_get_wallet().await?;\n\n    abigen!(\n        Contract(\n            name = \"MyContract\",\n            abi = \"e2e/sway/contracts/huge_contract/out/release/huge_contract-abi.json\"\n        ),\n        Contract(\n            name = \"MyProxy\",\n            abi = \"e2e/sway/contracts/proxy/out/release/proxy-abi.json\"\n        )\n    );\n\n    let contract_binary = \"sway/contracts/huge_contract/out/release/huge_contract.bin\";\n\n    let contract = Contract::load_from(contract_binary, LoadConfiguration::default())?;\n\n    let contract_id = contract\n        .convert_to_loader(100)?\n        .deploy_if_not_exists(&wallet, TxPolicies::default())\n        .await?\n        .contract_id;\n\n    let contract_binary = \"sway/contracts/proxy/out/release/proxy.bin\";\n\n    let proxy_id = Contract::load_from(contract_binary, LoadConfiguration::default())?\n        .deploy_if_not_exists(&wallet, TxPolicies::default())\n        .await?\n        .contract_id;\n\n    let proxy = MyProxy::new(proxy_id, wallet.clone());\n    proxy\n        .methods()\n        .set_target_contract(contract_id)\n        .call()\n        .await?;\n\n    let response = proxy\n        .methods()\n        .something()\n        .with_contract_ids(&[contract_id])\n        .call()\n        .await?\n        .value;\n\n    assert_eq!(response, 1001);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn loader_storage_works_via_proxy() -> Result<()> {\n    let wallet = launch_provider_and_get_wallet().await?;\n\n    abigen!(\n        Contract(\n            name = \"MyContract\",\n            abi = \"e2e/sway/contracts/huge_contract/out/release/huge_contract-abi.json\"\n        ),\n        Contract(\n            name = \"MyProxy\",\n            abi = \"e2e/sway/contracts/proxy/out/release/proxy-abi.json\"\n        )\n    );\n\n    let contract_binary = \"sway/contracts/huge_contract/out/release/huge_contract.bin\";\n\n    let contract = Contract::load_from(contract_binary, LoadConfiguration::default())?;\n    let contract_storage_slots = contract.storage_slots().to_vec();\n\n    let contract_id = contract\n        .convert_to_loader(100)?\n        .deploy_if_not_exists(&wallet, TxPolicies::default())\n        .await?\n        .contract_id;\n\n    let contract_binary = \"sway/contracts/proxy/out/release/proxy.bin\";\n    let proxy_contract = Contract::load_from(contract_binary, LoadConfiguration::default())?;\n\n    let combined_storage_slots = [&contract_storage_slots, proxy_contract.storage_slots()].concat();\n\n    let proxy_id = proxy_contract\n        .with_storage_slots(combined_storage_slots)\n        .deploy_if_not_exists(&wallet, TxPolicies::default())\n        .await?\n        .contract_id;\n\n    let proxy = MyProxy::new(proxy_id, wallet.clone());\n    proxy\n        .methods()\n        .set_target_contract(contract_id)\n        .call()\n        .await?;\n\n    let response = proxy\n        .methods()\n        .read_some_u64()\n        .with_contract_ids(&[contract_id])\n        .call()\n        .await?\n        .value;\n\n    assert_eq!(response, 42);\n\n    let _res = proxy\n        .methods()\n        .write_some_u64(36)\n        .with_contract_ids(&[contract_id])\n        .call()\n        .await?;\n\n    let response = proxy\n        .methods()\n        .read_some_u64()\n        .with_contract_ids(&[contract_id])\n        .call()\n        .await?\n        .value;\n\n    assert_eq!(response, 36);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn adjust_for_fee_errors() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"MyContract\",\n            project = \"e2e/sway/contracts/contract_test\"\n        )),\n    );\n\n    let contract_binary = \"sway/contracts/contract_test/out/release/contract_test.bin\";\n\n    let err = Contract::load_from(contract_binary, LoadConfiguration::default())?\n        .deploy(&wallet, TxPolicies::default().with_tip(10_000_000_000_000))\n        .await\n        .expect_err(\"should return error\");\n\n    assert!(\n        matches!(err, Error::Provider(s) if s.contains(\"failed to adjust inputs to cover for missing \\\n                base asset: failed to get base asset \\\n                (0000000000000000000000000000000000000000000000000000000000000000) inputs with amount:\"))\n    );\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn tx_input_output() -> Result<()> {\n    let [wallet_1, wallet_2] = launch_custom_provider_and_get_wallets(\n        WalletsConfig::new(Some(2), Some(10), Some(1000)),\n        None,\n        None,\n    )\n    .await?\n    .try_into()\n    .unwrap();\n\n    abigen!(Contract(\n        name = \"TxContract\",\n        abi = \"e2e/sway/contracts/tx_input_output/out/release/tx_input_output-abi.json\"\n    ));\n    let contract_binary = \"sway/contracts/tx_input_output/out/release/tx_input_output.bin\";\n\n    // Set `wallet_1` as the custom input owner\n    let configurables = TxContractConfigurables::default().with_OWNER(wallet_1.address())?;\n\n    let contract = Contract::load_from(\n        contract_binary,\n        LoadConfiguration::default().with_configurables(configurables),\n    )?;\n\n    let contract_id = contract\n        .deploy_if_not_exists(&wallet_2, TxPolicies::default())\n        .await?\n        .contract_id;\n\n    let contract_instance = TxContract::new(contract_id, wallet_2.clone());\n    let asset_id = AssetId::zeroed();\n\n    {\n        let custom_input = wallet_1\n            .get_asset_inputs_for_amount(asset_id, 10, None)\n            .await?\n            .pop()\n            .unwrap();\n\n        // Input at first position is a coin owned by wallet_1\n        let _ = contract_instance\n            .methods()\n            .check_input(0)\n            .with_inputs(vec![custom_input])\n            .add_signer(wallet_1.signer().clone())\n            .call()\n            .await?;\n\n        let custom_output = Output::change(wallet_1.address(), 0, asset_id);\n\n        // Output at first position is change to wallet_1\n        let _ = contract_instance\n            .methods()\n            .check_output_is_change(0)\n            .with_outputs(vec![custom_output])\n            .call()\n            .await?;\n    }\n    {\n        // Input at first position is not a coin owned by wallet_1\n        let err = contract_instance\n            .methods()\n            .check_input(0)\n            .call()\n            .await\n            .unwrap_err();\n\n        assert!(err.to_string().contains(\"input is not a coin\"));\n\n        // Output at first position is not change\n        let err = contract_instance\n            .methods()\n            .check_output_is_change(0)\n            .call()\n            .await\n            .unwrap_err();\n\n        assert!(err.to_string().contains(\"output is not change\"));\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn multicall_tx_input_output() -> Result<()> {\n    let [wallet_1, wallet_2, wallet_3] = launch_custom_provider_and_get_wallets(\n        WalletsConfig::new(Some(3), Some(10), Some(1000)),\n        None,\n        None,\n    )\n    .await?\n    .try_into()\n    .unwrap();\n\n    abigen!(Contract(\n        name = \"TxContract\",\n        abi = \"e2e/sway/contracts/tx_input_output/out/release/tx_input_output-abi.json\"\n    ));\n    let contract_binary = \"sway/contracts/tx_input_output/out/release/tx_input_output.bin\";\n\n    let get_contract_instance = |owner: Address| {\n        let wallet_for_fees = wallet_3.clone();\n\n        async move {\n            let configurables = TxContractConfigurables::default().with_OWNER(owner)?;\n\n            let contract = Contract::load_from(\n                contract_binary,\n                LoadConfiguration::default().with_configurables(configurables),\n            )?;\n\n            let contract_id = contract\n                .deploy_if_not_exists(&wallet_for_fees, TxPolicies::default())\n                .await?\n                .contract_id;\n\n            fuels::types::errors::Result::<_>::Ok(TxContract::new(contract_id, wallet_for_fees))\n        }\n    };\n\n    // Set `wallet_1` as owner\n    let contract_instance_1 = get_contract_instance(wallet_1.address()).await?;\n    // Set `wallet_2` as owner\n    let contract_instance_2 = get_contract_instance(wallet_2.address()).await?;\n    let asset_id = AssetId::zeroed();\n\n    {\n        let custom_input = wallet_1\n            .get_asset_inputs_for_amount(asset_id, 10, None)\n            .await?\n            .pop()\n            .unwrap();\n\n        // Input at first position is a coin owned by wallet_1\n        let ch1 = contract_instance_1\n            .methods()\n            .check_input(0)\n            .with_inputs(vec![custom_input])\n            .add_signer(wallet_1.signer().clone());\n\n        let custom_input = wallet_2\n            .get_asset_inputs_for_amount(asset_id, 10, None)\n            .await?\n            .pop()\n            .unwrap();\n\n        // As inputs follow the order off calls added to the multicall,\n        // we need to check the second input in this call\n        let ch2 = contract_instance_2\n            .methods()\n            .check_input(1)\n            .with_inputs(vec![custom_input])\n            .add_signer(wallet_2.signer().clone());\n\n        let multi_call_handler = CallHandler::new_multi_call(wallet_3.clone())\n            .add_call(ch1)\n            .add_call(ch2);\n\n        let _: ((), ()) = multi_call_handler.call().await?.value;\n    }\n    {\n        let custom_input = wallet_1\n            .get_asset_inputs_for_amount(asset_id, 10, None)\n            .await?\n            .pop()\n            .unwrap();\n\n        // Input at first position is a coin owned by wallet_1\n        let ch1 = contract_instance_1\n            .methods()\n            .check_input(0)\n            .with_inputs(vec![custom_input])\n            .add_signer(wallet_1.signer().clone());\n\n        // This call will read the wrong input and return an error\n        let ch2 = contract_instance_2.methods().check_input(0);\n\n        let multi_call_handler = CallHandler::new_multi_call(wallet_3.clone())\n            .add_call(ch1)\n            .add_call(ch2);\n\n        let err = multi_call_handler.call::<((), ())>().await.unwrap_err();\n\n        assert!(err.to_string().contains(\"wrong owner\"));\n    }\n    {\n        let custom_output = Output::change(wallet_1.address(), 0, asset_id);\n\n        // Output at first position is change to wallet_1\n        let ch1 = contract_instance_1\n            .methods()\n            .check_output_is_change(0)\n            .with_outputs(vec![custom_output]);\n\n        // This call will read the wrong output and return an error\n        let ch2 = contract_instance_2.methods().check_output_is_change(0);\n\n        let multi_call_handler = CallHandler::new_multi_call(wallet_3.clone())\n            .add_call(ch1)\n            .add_call(ch2);\n\n        let err = multi_call_handler.call::<((), ())>().await.unwrap_err();\n\n        assert!(err.to_string().contains(\"wrong change address\"));\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_returned_method_descriptors_are_valid() -> Result<()> {\n    abigen!(Contract(\n        name = \"MyContract\",\n        abi = \"e2e/sway/contracts/token_ops/out/release/token_ops-abi.json\"\n    ));\n\n    assert_eq!(\n        MyContract::METHODS.burn_coins().fn_selector(),\n        encode_fn_selector(\"burn_coins\")\n    );\n    assert_eq!(\n        MyContract::METHODS.get_balance().fn_selector(),\n        encode_fn_selector(\"get_balance\")\n    );\n    assert_eq!(\n        MyContract::METHODS.get_msg_amount().fn_selector(),\n        encode_fn_selector(\"get_msg_amount\")\n    );\n    assert_eq!(\n        MyContract::METHODS.mint_coins().fn_selector(),\n        encode_fn_selector(\"mint_coins\")\n    );\n    assert_eq!(\n        MyContract::METHODS.mint_to_addresses().fn_selector(),\n        encode_fn_selector(\"mint_to_addresses\")\n    );\n    assert_eq!(\n        MyContract::METHODS.send_message().fn_selector(),\n        encode_fn_selector(\"send_message\")\n    );\n    assert_eq!(\n        MyContract::METHODS.transfer().fn_selector(),\n        encode_fn_selector(\"transfer\")\n    );\n\n    assert_eq!(MyContract::METHODS.iter().len(), 7);\n\n    Ok(())\n}\n"
  },
  {
    "path": "e2e/tests/debug_utils.rs",
    "content": "use fuels::{\n    core::{\n        codec::{ABIEncoder, ABIFormatter},\n        traits::Tokenizable,\n    },\n    prelude::*,\n    programs::{debug::ScriptType, executable::Executable},\n};\n\n#[tokio::test]\nasync fn can_debug_single_call_tx() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"MyContract\",\n            project = \"e2e/sway/types/contracts/nested_structs\"\n        ))\n    );\n    let contract_id = Contract::load_from(\n        \"sway/types/contracts/nested_structs/out/release/nested_structs.bin\",\n        Default::default(),\n    )?\n    .contract_id();\n\n    let call_handler = MyContract::new(contract_id, wallet)\n        .methods()\n        .check_struct_integrity(AllStruct {\n            some_struct: SomeStruct {\n                field: 2,\n                field_2: true,\n            },\n        });\n\n    let abi = std::fs::read_to_string(\n        \"./sway/types/contracts/nested_structs/out/release/nested_structs-abi.json\",\n    )\n    .unwrap();\n    let decoder = ABIFormatter::from_json_abi(&abi)?;\n\n    // without gas forwarding\n    {\n        let tb = call_handler\n            .clone()\n            .call_params(CallParameters::default().with_amount(10))\n            .unwrap()\n            .transaction_builder()\n            .await\n            .unwrap();\n\n        let script = tb.script;\n        let script_data = tb.script_data;\n\n        let ScriptType::ContractCall(call_descriptions) =\n            ScriptType::detect(&script, &script_data)?\n        else {\n            panic!(\"expected a contract call\")\n        };\n\n        assert_eq!(call_descriptions.len(), 1);\n        let call_description = &call_descriptions[0];\n\n        assert_eq!(call_description.contract_id, contract_id);\n        assert_eq!(call_description.amount, 10);\n        assert_eq!(call_description.asset_id, AssetId::default());\n        assert_eq!(\n            call_description.decode_fn_selector().unwrap(),\n            \"check_struct_integrity\"\n        );\n        assert!(call_description.gas_forwarded.is_none());\n\n        assert_eq!(\n            decoder.decode_fn_args(\n                &call_description.decode_fn_selector().unwrap(),\n                call_description.encoded_args.as_slice()\n            )?,\n            vec![\"AllStruct { some_struct: SomeStruct { field: 2, field_2: true } }\"]\n        );\n    }\n\n    // with gas forwarding\n    {\n        let tb = call_handler\n            .clone()\n            .call_params(\n                CallParameters::default()\n                    .with_amount(10)\n                    .with_gas_forwarded(20),\n            )\n            .unwrap()\n            .transaction_builder()\n            .await\n            .unwrap();\n\n        let script = tb.script;\n        let script_data = tb.script_data;\n\n        let ScriptType::ContractCall(call_descriptions) =\n            ScriptType::detect(&script, &script_data)?\n        else {\n            panic!(\"expected a contract call\")\n        };\n\n        assert_eq!(call_descriptions.len(), 1);\n        let call_description = &call_descriptions[0];\n\n        assert_eq!(call_description.contract_id, contract_id);\n        assert_eq!(call_description.amount, 10);\n        assert_eq!(call_description.asset_id, AssetId::default());\n        assert_eq!(\n            call_description.decode_fn_selector().unwrap(),\n            \"check_struct_integrity\"\n        );\n        assert_eq!(call_description.gas_forwarded, Some(20));\n\n        assert_eq!(\n            decoder.decode_fn_args(\n                &call_description.decode_fn_selector().unwrap(),\n                call_description.encoded_args.as_slice()\n            )?,\n            vec![\"AllStruct { some_struct: SomeStruct { field: 2, field_2: true } }\"]\n        );\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn can_debug_multi_call_tx() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"MyContract\",\n            project = \"e2e/sway/types/contracts/nested_structs\"\n        ))\n    );\n    let contract_id = Contract::load_from(\n        \"sway/types/contracts/nested_structs/out/release/nested_structs.bin\",\n        Default::default(),\n    )?\n    .contract_id();\n\n    let call1 = MyContract::new(contract_id, wallet.clone())\n        .methods()\n        .check_struct_integrity(AllStruct {\n            some_struct: SomeStruct {\n                field: 2,\n                field_2: true,\n            },\n        });\n\n    let call2 = MyContract::new(contract_id, wallet.clone())\n        .methods()\n        .i_am_called_differently(\n            AllStruct {\n                some_struct: SomeStruct {\n                    field: 2,\n                    field_2: true,\n                },\n            },\n            MemoryAddress {\n                contract_id,\n                function_selector: 123,\n                function_data: 456,\n            },\n        );\n\n    let abi = std::fs::read_to_string(\n        \"./sway/types/contracts/nested_structs/out/release/nested_structs-abi.json\",\n    )\n    .unwrap();\n    let decoder = ABIFormatter::from_json_abi(&abi)?;\n\n    // without gas forwarding\n    {\n        let first_call = call1\n            .clone()\n            .call_params(CallParameters::default().with_amount(10))\n            .unwrap();\n\n        let second_call = call2\n            .clone()\n            .call_params(CallParameters::default().with_amount(20))\n            .unwrap();\n\n        let tb = CallHandler::new_multi_call(wallet.clone())\n            .add_call(first_call)\n            .add_call(second_call)\n            .transaction_builder()\n            .await\n            .unwrap();\n\n        let script = tb.script;\n        let script_data = tb.script_data;\n\n        let ScriptType::ContractCall(call_descriptions) =\n            ScriptType::detect(&script, &script_data)?\n        else {\n            panic!(\"expected a contract call\")\n        };\n\n        assert_eq!(call_descriptions.len(), 2);\n\n        let call_description = &call_descriptions[0];\n\n        assert_eq!(call_description.contract_id, contract_id);\n        assert_eq!(call_description.amount, 10);\n        assert_eq!(call_description.asset_id, AssetId::default());\n        assert_eq!(\n            call_description.decode_fn_selector().unwrap(),\n            \"check_struct_integrity\"\n        );\n        assert!(call_description.gas_forwarded.is_none());\n\n        assert_eq!(\n            decoder.decode_fn_args(\n                &call_description.decode_fn_selector().unwrap(),\n                call_description.encoded_args.as_slice()\n            )?,\n            vec![\"AllStruct { some_struct: SomeStruct { field: 2, field_2: true } }\"]\n        );\n\n        let call_description = &call_descriptions[1];\n        let fn_selector = call_description.decode_fn_selector().unwrap();\n\n        assert_eq!(call_description.contract_id, contract_id);\n        assert_eq!(call_description.amount, 20);\n        assert_eq!(call_description.asset_id, AssetId::default());\n        assert_eq!(fn_selector, \"i_am_called_differently\");\n        assert!(call_description.gas_forwarded.is_none());\n\n        assert_eq!(\n            decoder.decode_fn_args(&fn_selector, call_description.encoded_args.as_slice())?,\n            vec![\n                \"AllStruct { some_struct: SomeStruct { field: 2, field_2: true } }\".to_string(),\n                format!(\n                    \"MemoryAddress {{ contract_id: std::contract_id::ContractId {{ bits: Bits256({:?}) }}, function_selector: 123, function_data: 456 }}\",\n                    contract_id.as_slice()\n                )\n            ]\n        );\n    }\n\n    // with gas forwarding\n    {\n        let first_call = call1\n            .clone()\n            .call_params(\n                CallParameters::default()\n                    .with_amount(10)\n                    .with_gas_forwarded(15),\n            )\n            .unwrap();\n\n        let second_call = call2\n            .clone()\n            .call_params(\n                CallParameters::default()\n                    .with_amount(20)\n                    .with_gas_forwarded(25),\n            )\n            .unwrap();\n\n        let tb = CallHandler::new_multi_call(wallet.clone())\n            .add_call(first_call)\n            .add_call(second_call)\n            .transaction_builder()\n            .await\n            .unwrap();\n\n        let script = tb.script;\n        let script_data = tb.script_data;\n\n        let ScriptType::ContractCall(call_descriptions) =\n            ScriptType::detect(&script, &script_data)?\n        else {\n            panic!(\"expected a contract call\")\n        };\n\n        assert_eq!(call_descriptions.len(), 2);\n\n        let call_description = &call_descriptions[0];\n\n        assert_eq!(call_description.contract_id, contract_id);\n        assert_eq!(call_description.amount, 10);\n        assert_eq!(call_description.asset_id, AssetId::default());\n        assert_eq!(\n            call_description.decode_fn_selector().unwrap(),\n            \"check_struct_integrity\"\n        );\n        assert_eq!(call_description.gas_forwarded, Some(15));\n\n        assert_eq!(\n            decoder.decode_fn_args(\n                &call_description.decode_fn_selector().unwrap(),\n                call_description.encoded_args.as_slice()\n            )?,\n            vec![\"AllStruct { some_struct: SomeStruct { field: 2, field_2: true } }\"]\n        );\n\n        let call_description = &call_descriptions[1];\n\n        assert_eq!(call_description.contract_id, contract_id);\n        assert_eq!(call_description.amount, 20);\n        assert_eq!(call_description.asset_id, AssetId::default());\n        assert_eq!(\n            call_description.decode_fn_selector().unwrap(),\n            \"i_am_called_differently\"\n        );\n        assert_eq!(call_description.gas_forwarded, Some(25));\n\n        assert_eq!(\n            decoder.decode_fn_args(\n                &call_description.decode_fn_selector().unwrap(),\n                call_description.encoded_args.as_slice()\n            )?,\n            vec![\n                \"AllStruct { some_struct: SomeStruct { field: 2, field_2: true } }\".to_string(),\n                format!(\n                    \"MemoryAddress {{ contract_id: std::contract_id::ContractId {{ bits: Bits256({:?}) }}, function_selector: 123, function_data: 456 }}\",\n                    contract_id.as_slice()\n                )\n            ]\n        );\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn can_debug_sway_script() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Script(\n            name = \"MyScript\",\n            project = \"e2e/sway/scripts/script_struct\"\n        )),\n        LoadScript(\n            name = \"script_instance\",\n            script = \"MyScript\",\n            wallet = \"wallet\"\n        )\n    );\n\n    let tb = script_instance\n        .main(MyStruct {\n            number: 10,\n            boolean: false,\n        })\n        .transaction_builder()\n        .await\n        .unwrap();\n\n    let abi =\n        std::fs::read_to_string(\"./sway/scripts/script_struct/out/release/script_struct-abi.json\")?;\n\n    let decoder = ABIFormatter::from_json_abi(abi)?;\n\n    let ScriptType::Other(desc) = ScriptType::detect(&tb.script, &tb.script_data).unwrap() else {\n        panic!(\"expected a script\")\n    };\n\n    assert_eq!(\n        decoder.decode_fn_args(\"main\", desc.data.as_slice())?,\n        vec![\"MyStruct { number: 10, boolean: false }\"]\n    );\n\n    assert_eq!(\n        decoder\n            .decode_configurables(desc.data_section().unwrap())\n            .unwrap(),\n        vec![\n            (\"A_NUMBER\".to_owned(), \"11\".to_owned()),\n            (\n                \"MY_STRUCT\".to_owned(),\n                \"MyStruct { number: 10, boolean: true }\".to_owned()\n            ),\n        ]\n    );\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn debugs_sway_script_with_no_configurables() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Script(\n            name = \"MyScript\",\n            project = \"e2e/sway/scripts/basic_script\"\n        )),\n        LoadScript(\n            name = \"script_instance\",\n            script = \"MyScript\",\n            wallet = \"wallet\"\n        )\n    );\n\n    let tb = script_instance\n        .main(10, 11)\n        .transaction_builder()\n        .await\n        .unwrap();\n\n    let ScriptType::Other(desc) = ScriptType::detect(&tb.script, &tb.script_data).unwrap() else {\n        panic!(\"expected a script\")\n    };\n\n    assert!(desc.data_section().is_none());\n\n    Ok(())\n}\nfn generate_modern_sway_binary(len: usize) -> Vec<u8> {\n    assert!(\n        len > 24,\n        \"needs at least 24B to fit in the indicator_of_modern_binary, data & configurables offsets\"\n    );\n\n    let mut custom_script = vec![0; len];\n    let indicator_of_modern_binary = fuel_asm::op::jmpf(0x00, 0x04);\n\n    custom_script[4..8].copy_from_slice(&indicator_of_modern_binary.to_bytes());\n    custom_script\n}\n\n#[tokio::test]\nasync fn data_section_offset_not_set_if_out_of_bounds() -> Result<()> {\n    let mut custom_script = generate_modern_sway_binary(100);\n    custom_script[16..24].copy_from_slice(&u64::MAX.to_be_bytes());\n\n    let ScriptType::Other(desc) = ScriptType::detect(&custom_script, &[]).unwrap() else {\n        panic!(\"expected a script\")\n    };\n\n    assert!(desc.data_section_offset.is_none());\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn can_detect_a_loader_script_w_data_section() -> Result<()> {\n    setup_program_test!(Abigen(Script(\n        name = \"MyScript\",\n        project = \"e2e/sway/scripts/script_struct\"\n    )));\n\n    let script_data = ABIEncoder::default()\n        .encode(&[MyStruct {\n            number: 10,\n            boolean: false,\n        }\n        .into_token()])\n        .unwrap();\n\n    let executable =\n        Executable::load_from(\"sway/scripts/script_struct/out/release/script_struct.bin\")\n            .unwrap()\n            .convert_to_loader()\n            .unwrap();\n\n    let expected_blob_id = executable.blob().id();\n    let script = executable.code();\n\n    let ScriptType::Loader { script, blob_id } = ScriptType::detect(&script, &script_data).unwrap()\n    else {\n        panic!(\"expected a loader script\")\n    };\n\n    assert_eq!(blob_id, expected_blob_id);\n\n    let decoder = ABIFormatter::from_json_abi(std::fs::read_to_string(\n        \"./sway/scripts/script_struct/out/release/script_struct-abi.json\",\n    )?)?;\n\n    assert_eq!(\n        decoder.decode_fn_args(\"main\", script.data.as_slice())?,\n        vec![\"MyStruct { number: 10, boolean: false }\"]\n    );\n\n    assert_eq!(\n        decoder\n            .decode_configurables(script.data_section().unwrap())\n            .unwrap(),\n        vec![\n            (\"A_NUMBER\".to_owned(), \"11\".to_owned()),\n            (\n                \"MY_STRUCT\".to_owned(),\n                \"MyStruct { number: 10, boolean: true }\".to_owned()\n            ),\n        ]\n    );\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn can_detect_a_loader_script_wo_data_section() -> Result<()> {\n    setup_program_test!(Abigen(Script(\n        name = \"MyScript\",\n        project = \"e2e/sway/scripts/empty\"\n    )));\n\n    let executable = Executable::load_from(\"sway/scripts/empty/out/release/empty.bin\")\n        .unwrap()\n        .convert_to_loader()\n        .unwrap();\n\n    let expected_blob_id = executable.blob().id();\n    let script = executable.code();\n\n    let ScriptType::Loader { blob_id, .. } = ScriptType::detect(&script, &[]).unwrap() else {\n        panic!(\"expected a loader script\")\n    };\n\n    assert_eq!(blob_id, expected_blob_id);\n\n    Ok(())\n}\n"
  },
  {
    "path": "e2e/tests/from_token.rs",
    "content": "use fuels::{core::traits::Tokenizable, prelude::*, types::Token};\n\n#[tokio::test]\nasync fn create_struct_from_decoded_tokens() -> Result<()> {\n    abigen!(Contract(\n        name = \"SimpleContract\",\n        abi = \"e2e/sway/types/contracts/nested_structs/out/release/nested_structs-abi.json\"\n    ));\n\n    let u32_token = Token::U32(10);\n    let bool_token = Token::Bool(true);\n    let struct_from_tokens = SomeStruct::from_token(Token::Struct(vec![u32_token, bool_token]))?;\n\n    assert_eq!(10, struct_from_tokens.field);\n    assert!(struct_from_tokens.field_2);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn create_nested_struct_from_decoded_tokens() -> Result<()> {\n    abigen!(Contract(\n        name = \"SimpleContract\",\n        abi = \"e2e/sway/types/contracts/nested_structs/out/release/nested_structs-abi.json\"\n    ));\n\n    let u32_token = Token::U32(10);\n    let bool_token = Token::Bool(true);\n    let inner_struct_token = Token::Struct(vec![u32_token, bool_token]);\n\n    let nested_struct_from_tokens = AllStruct::from_token(Token::Struct(vec![inner_struct_token]))?;\n\n    assert_eq!(10, nested_struct_from_tokens.some_struct.field);\n    assert!(nested_struct_from_tokens.some_struct.field_2);\n\n    Ok(())\n}\n"
  },
  {
    "path": "e2e/tests/imports.rs",
    "content": "#[cfg(test)]\nmod tests {\n    #[test]\n    fn provides_output_type() {\n        // test exists because we've excluded fuel_tx::Output twice\n        #[allow(unused_imports)]\n        use fuels::types::output::Output;\n    }\n}\n"
  },
  {
    "path": "e2e/tests/logs.rs",
    "content": "use fuel_tx::SubAssetId;\nuse fuels::{\n    core::codec::DecoderConfig,\n    prelude::*,\n    tx::ContractIdExt,\n    types::{AsciiString, Bits256, SizedAsciiString, errors::transaction::Reason},\n};\n\n#[tokio::test]\nasync fn parse_logged_variables() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"LogContract\",\n            project = \"e2e/sway/logs/contract_logs\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"LogContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    // ANCHOR: produce_logs\n    let contract_methods = contract_instance.methods();\n    let response = contract_methods.produce_logs_variables().call().await?;\n\n    let log_u64 = response.decode_logs_with_type::<u64>()?;\n    let log_bits256 = response.decode_logs_with_type::<Bits256>()?;\n    let log_string = response.decode_logs_with_type::<SizedAsciiString<4>>()?;\n    let log_array = response.decode_logs_with_type::<[u8; 3]>()?;\n\n    let expected_bits256 = Bits256([\n        239, 134, 175, 169, 105, 108, 240, 220, 99, 133, 226, 196, 7, 166, 225, 89, 161, 16, 60,\n        239, 183, 226, 174, 6, 54, 251, 51, 211, 203, 42, 158, 74,\n    ]);\n\n    assert_eq!(log_u64, vec![64]);\n    assert_eq!(log_bits256, vec![expected_bits256]);\n    assert_eq!(log_string, vec![\"Fuel\"]);\n    assert_eq!(log_array, vec![[1, 2, 3]]);\n    // ANCHOR_END: produce_logs\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn parse_logs_values() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"LogContract\",\n            project = \"e2e/sway/logs/contract_logs\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"LogContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    let contract_methods = contract_instance.methods();\n    let response = contract_methods.produce_logs_values().call().await?;\n\n    let log_u64 = response.decode_logs_with_type::<u64>()?;\n    let log_u32 = response.decode_logs_with_type::<u32>()?;\n    let log_u16 = response.decode_logs_with_type::<u16>()?;\n    let log_u8 = response.decode_logs_with_type::<u8>()?;\n    // try to retrieve non existent log\n    let log_nonexistent = response.decode_logs_with_type::<bool>()?;\n\n    assert_eq!(log_u64, vec![64]);\n    assert_eq!(log_u32, vec![32]);\n    assert_eq!(log_u16, vec![16]);\n    assert_eq!(log_u8, vec![8]);\n    assert!(log_nonexistent.is_empty());\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn parse_logs_custom_types() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"LogContract\",\n            project = \"e2e/sway/logs/contract_logs\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"LogContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    let contract_methods = contract_instance.methods();\n    let response = contract_methods.produce_logs_custom_types().call().await?;\n\n    let log_test_struct = response.decode_logs_with_type::<TestStruct>()?;\n    let log_test_enum = response.decode_logs_with_type::<TestEnum>()?;\n    let log_tuple = response.decode_logs_with_type::<(TestStruct, TestEnum)>()?;\n\n    let expected_bits256 = Bits256([\n        239, 134, 175, 169, 105, 108, 240, 220, 99, 133, 226, 196, 7, 166, 225, 89, 161, 16, 60,\n        239, 183, 226, 174, 6, 54, 251, 51, 211, 203, 42, 158, 74,\n    ]);\n    let expected_struct = TestStruct {\n        field_1: true,\n        field_2: expected_bits256,\n        field_3: 64,\n    };\n    let expected_enum = TestEnum::VariantTwo;\n\n    assert_eq!(log_test_struct, vec![expected_struct.clone()]);\n    assert_eq!(log_test_enum, vec![expected_enum.clone()]);\n    assert_eq!(log_tuple, vec![(expected_struct, expected_enum)]);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn parse_logs_generic_types() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"LogContract\",\n            project = \"e2e/sway/logs/contract_logs\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"LogContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    let contract_methods = contract_instance.methods();\n    let response = contract_methods.produce_logs_generic_types().call().await?;\n\n    let log_struct = response.decode_logs_with_type::<StructWithGeneric<[_; 3]>>()?;\n    let log_enum = response.decode_logs_with_type::<EnumWithGeneric<[_; 3]>>()?;\n    let log_struct_nested =\n        response.decode_logs_with_type::<StructWithNestedGeneric<StructWithGeneric<[_; 3]>>>()?;\n    let log_struct_deeply_nested = response.decode_logs_with_type::<StructDeeplyNestedGeneric<\n        StructWithNestedGeneric<StructWithGeneric<[_; 3]>>,\n    >>()?;\n\n    let l = [1u8, 2u8, 3u8];\n    let expected_struct = StructWithGeneric {\n        field_1: l,\n        field_2: 64,\n    };\n    let expected_enum = EnumWithGeneric::VariantOne(l);\n    let expected_nested_struct = StructWithNestedGeneric {\n        field_1: expected_struct.clone(),\n        field_2: 64,\n    };\n    let expected_deeply_nested_struct = StructDeeplyNestedGeneric {\n        field_1: expected_nested_struct.clone(),\n        field_2: 64,\n    };\n\n    assert_eq!(log_struct, vec![expected_struct]);\n    assert_eq!(log_enum, vec![expected_enum]);\n    assert_eq!(log_struct_nested, vec![expected_nested_struct]);\n    assert_eq!(\n        log_struct_deeply_nested,\n        vec![expected_deeply_nested_struct]\n    );\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn decode_logs() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"LogContract\",\n            project = \"e2e/sway/logs/contract_logs\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"LogContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    // ANCHOR: decode_logs\n    let contract_methods = contract_instance.methods();\n    let response = contract_methods.produce_multiple_logs().call().await?;\n    let logs = response.decode_logs();\n    // ANCHOR_END: decode_logs\n\n    let expected_bits256 = Bits256([\n        239, 134, 175, 169, 105, 108, 240, 220, 99, 133, 226, 196, 7, 166, 225, 89, 161, 16, 60,\n        239, 183, 226, 174, 6, 54, 251, 51, 211, 203, 42, 158, 74,\n    ]);\n    let expected_struct = TestStruct {\n        field_1: true,\n        field_2: expected_bits256,\n        field_3: 64,\n    };\n    let expected_enum = TestEnum::VariantTwo;\n    let expected_generic_struct = StructWithGeneric {\n        field_1: expected_struct.clone(),\n        field_2: 64,\n    };\n    let expected_logs: Vec<String> = vec![\n        format!(\"{:?}\", 64u64),\n        format!(\"{:?}\", 32u32),\n        format!(\"{:?}\", 16u16),\n        format!(\"{:?}\", 8u8),\n        format!(\"{:?}\", 64u64),\n        format!(\"{expected_bits256:?}\"),\n        format!(\"{:?}\", SizedAsciiString::<4>::new(\"Fuel\".to_string())?),\n        format!(\"{:?}\", [1, 2, 3]),\n        format!(\"{expected_struct:?}\"),\n        format!(\"{expected_enum:?}\"),\n        format!(\"{expected_generic_struct:?}\"),\n    ];\n\n    assert_eq!(expected_logs, logs.filter_succeeded());\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn decode_logs_with_no_logs() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TestContract\",\n            project = \"e2e/sway/contracts/contract_test\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TestContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    let contract_methods = contract_instance.methods();\n    let logs = contract_methods\n        .initialize_counter(42)\n        .call()\n        .await?\n        .decode_logs();\n\n    assert!(logs.filter_succeeded().is_empty());\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn multi_call_log_single_contract() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"LogContract\",\n            project = \"e2e/sway/logs/contract_logs\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"LogContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    let contract_methods = contract_instance.methods();\n\n    let call_handler_1 = contract_methods.produce_logs_values();\n    let call_handler_2 = contract_methods.produce_logs_variables();\n\n    let multi_call_handler = CallHandler::new_multi_call(wallet.clone())\n        .add_call(call_handler_1)\n        .add_call(call_handler_2);\n\n    let expected_logs: Vec<String> = vec![\n        format!(\"{:?}\", 64u64),\n        format!(\"{:?}\", 32u32),\n        format!(\"{:?}\", 16u16),\n        format!(\"{:?}\", 8u8),\n        format!(\"{:?}\", 64u64),\n        format!(\n            \"{:?}\",\n            Bits256([\n                239, 134, 175, 169, 105, 108, 240, 220, 99, 133, 226, 196, 7, 166, 225, 89, 161,\n                16, 60, 239, 183, 226, 174, 6, 54, 251, 51, 211, 203, 42, 158, 74,\n            ])\n        ),\n        format!(\"{:?}\", SizedAsciiString::<4>::new(\"Fuel\".to_string())?),\n        format!(\"{:?}\", [1, 2, 3]),\n    ];\n\n    let logs = multi_call_handler.call::<((), ())>().await?.decode_logs();\n\n    assert_eq!(logs.filter_succeeded(), expected_logs);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn multi_call_log_multiple_contracts() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"LogContract\",\n            project = \"e2e/sway/logs/contract_logs\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"LogContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n        Deploy(\n            name = \"contract_instance2\",\n            contract = \"LogContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    let call_handler_1 = contract_instance.methods().produce_logs_values();\n    let call_handler_2 = contract_instance2.methods().produce_logs_variables();\n\n    let multi_call_handler = CallHandler::new_multi_call(wallet.clone())\n        .add_call(call_handler_1)\n        .add_call(call_handler_2);\n\n    let expected_logs: Vec<String> = vec![\n        format!(\"{:?}\", 64u64),\n        format!(\"{:?}\", 32u32),\n        format!(\"{:?}\", 16u16),\n        format!(\"{:?}\", 8u8),\n        format!(\"{:?}\", 64u64),\n        format!(\n            \"{:?}\",\n            Bits256([\n                239, 134, 175, 169, 105, 108, 240, 220, 99, 133, 226, 196, 7, 166, 225, 89, 161,\n                16, 60, 239, 183, 226, 174, 6, 54, 251, 51, 211, 203, 42, 158, 74,\n            ])\n        ),\n        format!(\"{:?}\", SizedAsciiString::<4>::new(\"Fuel\".to_string())?),\n        format!(\"{:?}\", [1, 2, 3]),\n    ];\n\n    let logs = multi_call_handler.call::<((), ())>().await?.decode_logs();\n\n    assert_eq!(logs.filter_succeeded(), expected_logs);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn multi_call_contract_with_contract_logs() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(\n            Contract(name = \"MyContract\", project = \"e2e/sway/logs/contract_logs\"),\n            Contract(\n                name = \"ContractCaller\",\n                project = \"e2e/sway/logs/contract_with_contract_logs\"\n            )\n        ),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"MyContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n        Deploy(\n            name = \"contract_caller_instance\",\n            contract = \"ContractCaller\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n        Deploy(\n            name = \"contract_caller_instance2\",\n            contract = \"ContractCaller\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    let call_handler_1 = contract_caller_instance\n        .methods()\n        .logs_from_external_contract(contract_instance.id())\n        .with_contracts(&[&contract_instance]);\n\n    let call_handler_2 = contract_caller_instance2\n        .methods()\n        .logs_from_external_contract(contract_instance.id())\n        .with_contracts(&[&contract_instance]);\n\n    let multi_call_handler = CallHandler::new_multi_call(wallet.clone())\n        .add_call(call_handler_1)\n        .add_call(call_handler_2);\n\n    let expected_logs: Vec<String> = vec![\n        format!(\"{:?}\", 64),\n        format!(\"{:?}\", 32),\n        format!(\"{:?}\", 16),\n        format!(\"{:?}\", 8),\n        format!(\"{:?}\", 64),\n        format!(\"{:?}\", 32),\n        format!(\"{:?}\", 16),\n        format!(\"{:?}\", 8),\n    ];\n\n    let logs = multi_call_handler.call::<((), ())>().await?.decode_logs();\n\n    assert_eq!(logs.filter_succeeded(), expected_logs);\n\n    Ok(())\n}\n\nfn assert_revert_containing_msg(msg: &str, error: Error) {\n    let Error::Transaction(Reason::Failure { reason, .. }) = error else {\n        panic!(\"error does not have the transaction failure variant\");\n    };\n\n    assert!(\n        reason.contains(msg),\n        \"message: \\\"{msg}\\\" not contained in reason: \\\"{reason}\\\"\"\n    );\n}\n\n#[tokio::test]\nasync fn revert_logs() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"RevertLogsContract\",\n            project = \"e2e/sway/logs/contract_revert_logs\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"RevertLogsContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    macro_rules! reverts_with_msg {\n        ($method:ident, call, $msg:expr) => {\n            let error = contract_instance\n                .methods()\n                .$method()\n                .call()\n                .await\n                .expect_err(\"should return a revert error\");\n\n            assert_revert_containing_msg($msg, error);\n        };\n        ($method:ident, simulate, $msg:expr) => {\n            let error = contract_instance\n                .methods()\n                .$method()\n                .simulate(Execution::realistic())\n                .await\n                .expect_err(\"should return a revert error\");\n\n            assert_revert_containing_msg($msg, error);\n        };\n    }\n\n    {\n        reverts_with_msg!(require_primitive, call, \"42\");\n        reverts_with_msg!(require_primitive, simulate, \"42\");\n\n        reverts_with_msg!(require_string, call, \"fuel\");\n        reverts_with_msg!(require_string, simulate, \"fuel\");\n\n        reverts_with_msg!(require_custom_generic, call, \"StructDeeplyNestedGeneric\");\n        reverts_with_msg!(\n            require_custom_generic,\n            simulate,\n            \"StructDeeplyNestedGeneric\"\n        );\n\n        reverts_with_msg!(require_with_additional_logs, call, \"64\");\n        reverts_with_msg!(require_with_additional_logs, simulate, \"64\");\n    }\n    {\n        reverts_with_msg!(rev_w_log_primitive, call, \"42\");\n        reverts_with_msg!(rev_w_log_primitive, simulate, \"42\");\n\n        reverts_with_msg!(rev_w_log_string, call, \"fuel\");\n        reverts_with_msg!(rev_w_log_string, simulate, \"fuel\");\n\n        reverts_with_msg!(rev_w_log_custom_generic, call, \"StructDeeplyNestedGeneric\");\n        reverts_with_msg!(\n            rev_w_log_custom_generic,\n            simulate,\n            \"StructDeeplyNestedGeneric\"\n        );\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn multi_call_revert_logs_single_contract() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"RevertLogsContract\",\n            project = \"e2e/sway/logs/contract_revert_logs\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"RevertLogsContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    let contract_methods = contract_instance.methods();\n\n    // The output of the error depends on the order of the contract\n    // handlers as the script returns the first revert it finds.\n    {\n        let call_handler_1 = contract_methods.require_string();\n        let call_handler_2 = contract_methods.rev_w_log_custom_generic();\n\n        let mut multi_call_handler = CallHandler::new_multi_call(wallet.clone())\n            .add_call(call_handler_1)\n            .add_call(call_handler_2);\n\n        let error = multi_call_handler\n            .simulate::<((), ())>(Execution::realistic())\n            .await\n            .expect_err(\"should return a revert error\");\n\n        assert_revert_containing_msg(\"fuel\", error);\n\n        let error = multi_call_handler\n            .call::<((), ())>()\n            .await\n            .expect_err(\"should return a revert error\");\n\n        assert_revert_containing_msg(\"fuel\", error);\n    }\n    {\n        let call_handler_1 = contract_methods.require_custom_generic();\n        let call_handler_2 = contract_methods.rev_w_log_string();\n\n        let mut multi_call_handler = CallHandler::new_multi_call(wallet.clone())\n            .add_call(call_handler_1)\n            .add_call(call_handler_2);\n\n        let error = multi_call_handler\n            .simulate::<((), ())>(Execution::realistic())\n            .await\n            .expect_err(\"should return a revert error\");\n\n        assert_revert_containing_msg(\"StructDeeplyNestedGeneric\", error);\n\n        let error = multi_call_handler\n            .call::<((), ())>()\n            .await\n            .expect_err(\"should return a revert error\");\n\n        assert_revert_containing_msg(\"StructDeeplyNestedGeneric\", error);\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn multi_call_revert_logs_multi_contract() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"RevertLogsContract\",\n            project = \"e2e/sway/logs/contract_revert_logs\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"RevertLogsContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n        Deploy(\n            name = \"contract_instance2\",\n            contract = \"RevertLogsContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    let contract_methods = contract_instance.methods();\n    let contract_methods2 = contract_instance2.methods();\n\n    // The output of the error depends on the order of the contract\n    // handlers as the script returns the first revert it finds.\n    {\n        let call_handler_1 = contract_methods.require_string();\n        let call_handler_2 = contract_methods2.rev_w_log_custom_generic();\n\n        let mut multi_call_handler = CallHandler::new_multi_call(wallet.clone())\n            .add_call(call_handler_1)\n            .add_call(call_handler_2);\n\n        let error = multi_call_handler\n            .simulate::<((), ())>(Execution::realistic())\n            .await\n            .expect_err(\"should return a revert error\");\n\n        assert_revert_containing_msg(\"fuel\", error);\n\n        let error = multi_call_handler\n            .call::<((), ())>()\n            .await\n            .expect_err(\"should return a revert error\");\n\n        assert_revert_containing_msg(\"fuel\", error);\n    }\n    {\n        let call_handler_1 = contract_methods2.require_custom_generic();\n        let call_handler_2 = contract_methods.rev_w_log_string();\n\n        let mut multi_call_handler = CallHandler::new_multi_call(wallet.clone())\n            .add_call(call_handler_1)\n            .add_call(call_handler_2);\n\n        let error = multi_call_handler\n            .simulate::<((), ())>(Execution::realistic())\n            .await\n            .expect_err(\"should return a revert error\");\n\n        assert_revert_containing_msg(\"StructDeeplyNestedGeneric\", error);\n\n        let error = multi_call_handler\n            .call::<((), ())>()\n            .await\n            .expect_err(\"should return a revert error\");\n\n        assert_revert_containing_msg(\"StructDeeplyNestedGeneric\", error);\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\n#[allow(unused_variables)]\nasync fn script_decode_logs() -> Result<()> {\n    // ANCHOR: script_logs\n    abigen!(Script(\n        name = \"LogScript\",\n        abi = \"e2e/sway/logs/script_logs/out/release/script_logs-abi.json\"\n    ));\n\n    let wallet = launch_provider_and_get_wallet().await?;\n    let bin_path = \"sway/logs/script_logs/out/release/script_logs.bin\";\n    let instance = LogScript::new(wallet.clone(), bin_path);\n\n    let response = instance.main().call().await?;\n\n    let logs = response.decode_logs();\n    let log_u64 = response.decode_logs_with_type::<u64>()?;\n    // ANCHOR_END: script_logs\n\n    let l = [1u8, 2u8, 3u8];\n    let expected_bits256 = Bits256([\n        239, 134, 175, 169, 105, 108, 240, 220, 99, 133, 226, 196, 7, 166, 225, 89, 161, 16, 60,\n        239, 183, 226, 174, 6, 54, 251, 51, 211, 203, 42, 158, 74,\n    ]);\n    let expected_struct = TestStruct {\n        field_1: true,\n        field_2: expected_bits256,\n        field_3: 64,\n    };\n    let expected_enum = TestEnum::VariantTwo;\n    let expected_tuple = (expected_struct.clone(), expected_enum.clone());\n    let expected_generic_struct = StructWithGeneric {\n        field_1: expected_struct.clone(),\n        field_2: 64,\n    };\n\n    let expected_generic_enum = EnumWithGeneric::VariantOne(l);\n    let expected_nested_struct = StructWithNestedGeneric {\n        field_1: expected_generic_struct.clone(),\n        field_2: 64,\n    };\n    let expected_deeply_nested_struct = StructDeeplyNestedGeneric {\n        field_1: expected_nested_struct.clone(),\n        field_2: 64,\n    };\n    let expected_logs: Vec<String> = vec![\n        format!(\"{:?}\", 128u64),\n        format!(\"{:?}\", 32u32),\n        format!(\"{:?}\", 16u16),\n        format!(\"{:?}\", 8u8),\n        format!(\"{:?}\", 64u64),\n        format!(\"{expected_bits256:?}\"),\n        format!(\"{:?}\", SizedAsciiString::<4>::new(\"Fuel\".to_string())?),\n        format!(\"{:?}\", [1, 2, 3]),\n        format!(\"{expected_struct:?}\"),\n        format!(\"{expected_enum:?}\"),\n        format!(\"{expected_tuple:?}\"),\n        format!(\"{expected_generic_struct:?}\"),\n        format!(\"{expected_generic_enum:?}\"),\n        format!(\"{expected_nested_struct:?}\"),\n        format!(\"{expected_deeply_nested_struct:?}\"),\n    ];\n\n    assert_eq!(logs.filter_succeeded(), expected_logs);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn contract_with_contract_logs() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(\n            Contract(name = \"MyContract\", project = \"e2e/sway/logs/contract_logs\",),\n            Contract(\n                name = \"ContractCaller\",\n                project = \"e2e/sway/logs/contract_with_contract_logs\",\n            )\n        ),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"MyContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n        Deploy(\n            name = \"contract_caller_instance\",\n            contract = \"ContractCaller\",\n            wallet = \"wallet\",\n            random_salt = false,\n        )\n    );\n\n    let expected_logs: Vec<String> = vec![\n        format!(\"{:?}\", 64),\n        format!(\"{:?}\", 32),\n        format!(\"{:?}\", 16),\n        format!(\"{:?}\", 8),\n    ];\n\n    let logs = contract_caller_instance\n        .methods()\n        .logs_from_external_contract(contract_instance.id())\n        .with_contracts(&[&contract_instance])\n        .call()\n        .await?\n        .decode_logs();\n\n    assert_eq!(expected_logs, logs.filter_succeeded());\n\n    Ok(())\n}\n\n#[tokio::test]\n#[allow(unused_variables)]\nasync fn script_logs_with_contract_logs() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(\n            Contract(name = \"MyContract\", project = \"e2e/sway/logs/contract_logs\",),\n            Script(\n                name = \"LogScript\",\n                project = \"e2e/sway/logs/script_with_contract_logs\"\n            )\n        ),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"MyContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n        LoadScript(\n            name = \"script_instance\",\n            script = \"LogScript\",\n            wallet = \"wallet\"\n        )\n    );\n\n    let expected_num_contract_logs = 4;\n\n    let expected_script_logs: Vec<String> = vec![\n        // Contract logs\n        format!(\"{:?}\", 64),\n        format!(\"{:?}\", 32),\n        format!(\"{:?}\", 16),\n        format!(\"{:?}\", 8),\n        // Script logs\n        format!(\"{:?}\", true),\n        format!(\"{:?}\", 42),\n        format!(\"{:?}\", SizedAsciiString::<4>::new(\"Fuel\".to_string())?),\n        format!(\"{:?}\", [1, 2, 3]),\n    ];\n\n    // ANCHOR: instance_to_contract_id\n    let contract_id: ContractId = contract_instance.contract_id();\n    // ANCHOR_END: instance_to_contract_id\n\n    // ANCHOR: external_contract_ids\n    let response = script_instance\n        .main(contract_id, MatchEnum::Logs)\n        .with_contract_ids(&[contract_id])\n        .call()\n        .await?;\n    // ANCHOR_END: external_contract_ids\n\n    // ANCHOR: external_contract\n    let response = script_instance\n        .main(contract_id, MatchEnum::Logs)\n        .with_contracts(&[&contract_instance])\n        .call()\n        .await?;\n    // ANCHOR_END: external_contract\n\n    {\n        let num_contract_logs = response\n            .tx_status\n            .receipts\n            .iter()\n            .filter(|receipt| matches!(receipt, Receipt::LogData { id, .. } | Receipt::Log { id, .. } if *id == contract_id))\n            .count();\n\n        assert_eq!(num_contract_logs, expected_num_contract_logs);\n    }\n    {\n        let logs = response.decode_logs();\n\n        assert_eq!(logs.filter_succeeded(), expected_script_logs);\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn script_decode_logs_with_type() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Script(\n            name = \"LogScript\",\n            project = \"e2e/sway/logs/script_logs\"\n        )),\n        LoadScript(\n            name = \"script_instance\",\n            script = \"LogScript\",\n            wallet = \"wallet\"\n        )\n    );\n\n    let response = script_instance.main().call().await?;\n\n    let l = [1u8, 2u8, 3u8];\n    let expected_bits256 = Bits256([\n        239, 134, 175, 169, 105, 108, 240, 220, 99, 133, 226, 196, 7, 166, 225, 89, 161, 16, 60,\n        239, 183, 226, 174, 6, 54, 251, 51, 211, 203, 42, 158, 74,\n    ]);\n    let expected_struct = TestStruct {\n        field_1: true,\n        field_2: expected_bits256,\n        field_3: 64,\n    };\n    let expected_enum = TestEnum::VariantTwo;\n    let expected_generic_struct = StructWithGeneric {\n        field_1: expected_struct.clone(),\n        field_2: 64,\n    };\n\n    let expected_generic_enum = EnumWithGeneric::VariantOne(l);\n    let expected_nested_struct = StructWithNestedGeneric {\n        field_1: expected_generic_struct.clone(),\n        field_2: 64,\n    };\n    let expected_deeply_nested_struct = StructDeeplyNestedGeneric {\n        field_1: expected_nested_struct.clone(),\n        field_2: 64,\n    };\n\n    let log_u64 = response.decode_logs_with_type::<u64>()?;\n    let log_u32 = response.decode_logs_with_type::<u32>()?;\n    let log_u16 = response.decode_logs_with_type::<u16>()?;\n    let log_u8 = response.decode_logs_with_type::<u8>()?;\n    let log_struct = response.decode_logs_with_type::<TestStruct>()?;\n    let log_enum = response.decode_logs_with_type::<TestEnum>()?;\n    let log_generic_struct = response.decode_logs_with_type::<StructWithGeneric<TestStruct>>()?;\n    let log_generic_enum = response.decode_logs_with_type::<EnumWithGeneric<[_; 3]>>()?;\n    let log_nested_struct = response\n        .decode_logs_with_type::<StructWithNestedGeneric<StructWithGeneric<TestStruct>>>()?;\n    let log_deeply_nested_struct = response.decode_logs_with_type::<StructDeeplyNestedGeneric<\n        StructWithNestedGeneric<StructWithGeneric<TestStruct>>,\n    >>()?;\n    // try to retrieve non existent log\n    let log_nonexistent = response.decode_logs_with_type::<bool>()?;\n\n    assert_eq!(log_u64, vec![128, 64]);\n    assert_eq!(log_u32, vec![32]);\n    assert_eq!(log_u16, vec![16]);\n    assert_eq!(log_u8, vec![8]);\n    assert_eq!(log_struct, vec![expected_struct]);\n    assert_eq!(log_enum, vec![expected_enum]);\n    assert_eq!(log_generic_struct, vec![expected_generic_struct]);\n    assert_eq!(log_generic_enum, vec![expected_generic_enum]);\n    assert_eq!(log_nested_struct, vec![expected_nested_struct]);\n    assert_eq!(\n        log_deeply_nested_struct,\n        vec![expected_deeply_nested_struct]\n    );\n    assert!(log_nonexistent.is_empty());\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn script_require_log() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Script(\n            name = \"LogScript\",\n            project = \"e2e/sway/logs/script_revert_logs\"\n        )),\n        LoadScript(\n            name = \"script_instance\",\n            script = \"LogScript\",\n            wallet = \"wallet\"\n        )\n    );\n\n    macro_rules! reverts_with_msg {\n        ($arg:expr, call, $msg:expr) => {\n            let error = script_instance\n                .main($arg)\n                .call()\n                .await\n                .expect_err(\"should return a revert error\");\n            assert_revert_containing_msg($msg, error);\n        };\n        ($arg:expr, simulate, $msg:expr) => {\n            let error = script_instance\n                .main($arg)\n                .simulate(Execution::realistic())\n                .await\n                .expect_err(\"should return a revert error\");\n            assert_revert_containing_msg($msg, error);\n        };\n    }\n\n    {\n        reverts_with_msg!(MatchEnum::RequirePrimitive, call, \"42\");\n        reverts_with_msg!(MatchEnum::RequirePrimitive, simulate, \"42\");\n\n        reverts_with_msg!(MatchEnum::RequireString, call, \"fuel\");\n        reverts_with_msg!(MatchEnum::RequireString, simulate, \"fuel\");\n\n        reverts_with_msg!(\n            MatchEnum::RequireCustomGeneric,\n            call,\n            \"StructDeeplyNestedGeneric\"\n        );\n        reverts_with_msg!(\n            MatchEnum::RequireCustomGeneric,\n            simulate,\n            \"StructDeeplyNestedGeneric\"\n        );\n\n        reverts_with_msg!(MatchEnum::RequireWithAdditionalLogs, call, \"64\");\n        reverts_with_msg!(MatchEnum::RequireWithAdditionalLogs, simulate, \"64\");\n    }\n    {\n        reverts_with_msg!(MatchEnum::RevWLogPrimitive, call, \"42\");\n        reverts_with_msg!(MatchEnum::RevWLogPrimitive, simulate, \"42\");\n\n        reverts_with_msg!(MatchEnum::RevWLogString, call, \"fuel\");\n        reverts_with_msg!(MatchEnum::RevWLogString, simulate, \"fuel\");\n\n        reverts_with_msg!(\n            MatchEnum::RevWLogCustomGeneric,\n            call,\n            \"StructDeeplyNestedGeneric\"\n        );\n        reverts_with_msg!(\n            MatchEnum::RevWLogCustomGeneric,\n            simulate,\n            \"StructDeeplyNestedGeneric\"\n        );\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn contract_require_from_contract() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(\n            Contract(\n                name = \"MyContract\",\n                project = \"e2e/sway/contracts/lib_contract\",\n            ),\n            Contract(\n                name = \"ContractCaller\",\n                project = \"e2e/sway/contracts/lib_contract_caller\",\n            )\n        ),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"MyContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n        Deploy(\n            name = \"contract_caller_instance\",\n            contract = \"ContractCaller\",\n            wallet = \"wallet\",\n            random_salt = false,\n        )\n    );\n\n    let error = contract_caller_instance\n        .methods()\n        .require_from_contract(contract_instance.id())\n        .with_contracts(&[&contract_instance])\n        .call()\n        .await\n        .expect_err(\"should return a revert error\");\n\n    assert_revert_containing_msg(\"require from contract\", error);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn multi_call_contract_require_from_contract() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(\n            Contract(\n                name = \"MyContract\",\n                project = \"e2e/sway/contracts/lib_contract\",\n            ),\n            Contract(\n                name = \"ContractLogs\",\n                project = \"e2e/sway/logs/contract_logs\",\n            ),\n            Contract(\n                name = \"ContractCaller\",\n                project = \"e2e/sway/contracts/lib_contract_caller\",\n            )\n        ),\n        Deploy(\n            name = \"lib_contract_instance\",\n            contract = \"MyContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"ContractLogs\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n        Deploy(\n            name = \"contract_caller_instance\",\n            contract = \"ContractCaller\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    let call_handler_1 = contract_instance.methods().produce_logs_values();\n\n    let call_handler_2 = contract_caller_instance\n        .methods()\n        .require_from_contract(lib_contract_instance.id())\n        .with_contracts(&[&lib_contract_instance]);\n\n    let multi_call_handler = CallHandler::new_multi_call(wallet.clone())\n        .add_call(call_handler_1)\n        .add_call(call_handler_2);\n\n    let error = multi_call_handler\n        .call::<((), ())>()\n        .await\n        .expect_err(\"should return a revert error\");\n\n    assert_revert_containing_msg(\"require from contract\", error);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn script_require_from_contract() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(\n            Contract(\n                name = \"MyContract\",\n                project = \"e2e/sway/contracts/lib_contract\",\n            ),\n            Script(\n                name = \"LogScript\",\n                project = \"e2e/sway/scripts/require_from_contract\"\n            )\n        ),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"MyContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n        LoadScript(\n            name = \"script_instance\",\n            script = \"LogScript\",\n            wallet = \"wallet\"\n        )\n    );\n\n    let error = script_instance\n        .main(contract_instance.id())\n        .with_contracts(&[&contract_instance])\n        .call()\n        .await\n        .expect_err(\"should return a revert error\");\n\n    assert_revert_containing_msg(\"require from contract\", error);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn loader_script_require_from_loader_contract() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(\n            Contract(\n                name = \"MyContract\",\n                project = \"e2e/sway/contracts/lib_contract\",\n            ),\n            Script(\n                name = \"LogScript\",\n                project = \"e2e/sway/scripts/require_from_contract\"\n            )\n        ),\n        LoadScript(\n            name = \"script_instance\",\n            script = \"LogScript\",\n            wallet = \"wallet\"\n        )\n    );\n\n    let contract_binary = \"sway/contracts/lib_contract/out/release/lib_contract.bin\";\n    let contract = Contract::load_from(contract_binary, LoadConfiguration::default())?;\n    let contract_id = contract\n        .convert_to_loader(100_000)?\n        .deploy_if_not_exists(&wallet, TxPolicies::default())\n        .await?\n        .contract_id;\n    let contract_instance = MyContract::new(contract_id, wallet);\n\n    let mut script_instance = script_instance;\n    script_instance.convert_into_loader().await?;\n\n    let error = script_instance\n        .main(contract_instance.id())\n        .with_contracts(&[&contract_instance])\n        .call()\n        .await\n        .expect_err(\"should return a revert error\");\n\n    assert_revert_containing_msg(\"require from contract\", error);\n\n    Ok(())\n}\n\nfn assert_assert_eq_containing_msg<T: std::fmt::Debug>(left: T, right: T, error: Error) {\n    let msg = format!(\n        \"assertion failed: `(left == right)`\\n left: `\\\"{left:?}\\\"`\\n right: `\\\"{right:?}\\\"`\"\n    );\n    assert_revert_containing_msg(&msg, error)\n}\n\nfn assert_assert_ne_containing_msg<T: std::fmt::Debug>(left: T, right: T, error: Error) {\n    let msg = format!(\n        \"assertion failed: `(left != right)`\\n left: `\\\"{left:?}\\\"`\\n right: `\\\"{right:?}\\\"`\"\n    );\n    assert_revert_containing_msg(&msg, error)\n}\n\n#[tokio::test]\nasync fn contract_asserts_log() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"LogContract\",\n            project = \"e2e/sway/contracts/asserts\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"LogContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    macro_rules! reverts_with_msg {\n        (($($arg: expr,)*), $method:ident, call, $msg:expr) => {\n            let error = contract_instance\n                .methods()\n                .$method($($arg,)*)\n                .call()\n                .await\n                .expect_err(\"should return a revert error\");\n            assert_revert_containing_msg($msg, error);\n        };\n        (($($arg: expr,)*), $method:ident, simulate, $msg:expr) => {\n            let error = contract_instance\n                .methods()\n                .$method($($arg,)*)\n                .simulate(Execution::realistic())\n                .await\n                .expect_err(\"should return a revert error\");\n            assert_revert_containing_msg($msg, error);\n        };\n    }\n    {\n        reverts_with_msg!((32, 64,), assert_primitive, call, \"assertion failed\");\n        reverts_with_msg!((32, 64,), assert_primitive, simulate, \"assertion failed\");\n    }\n\n    macro_rules! reverts_with_assert_eq_msg {\n        (($($arg: expr,)*), $method:ident, $execution: ident, $msg:expr) => {\n            let error = contract_instance\n                .methods()\n                .$method($($arg,)*)\n                .call()\n                .await\n                .expect_err(\"should return a revert error\");\n            assert_assert_eq_containing_msg($($arg,)* error);\n        }\n    }\n\n    {\n        reverts_with_assert_eq_msg!((32, 64,), assert_eq_primitive, call, \"assertion failed\");\n        reverts_with_assert_eq_msg!((32, 64,), assert_eq_primitive, simulate, \"assertion failed\");\n    }\n    {\n        let test_struct = TestStruct {\n            field_1: true,\n            field_2: 64,\n        };\n\n        let test_struct2 = TestStruct {\n            field_1: false,\n            field_2: 32,\n        };\n\n        reverts_with_assert_eq_msg!(\n            (test_struct.clone(), test_struct2.clone(),),\n            assert_eq_struct,\n            call,\n            \"assertion failed\"\n        );\n\n        reverts_with_assert_eq_msg!(\n            (test_struct.clone(), test_struct2.clone(),),\n            assert_eq_struct,\n            simulate,\n            \"assertion failed\"\n        );\n    }\n    {\n        let test_enum = TestEnum::VariantOne;\n        let test_enum2 = TestEnum::VariantTwo;\n        reverts_with_assert_eq_msg!(\n            (test_enum.clone(), test_enum2.clone(),),\n            assert_eq_enum,\n            call,\n            \"assertion failed\"\n        );\n\n        reverts_with_assert_eq_msg!(\n            (test_enum.clone(), test_enum2.clone(),),\n            assert_eq_enum,\n            simulate,\n            \"assertion failed\"\n        );\n    }\n\n    macro_rules! reverts_with_assert_ne_msg {\n        (($($arg: expr,)*), $method:ident, $execution: ident, $msg:expr) => {\n            let error = contract_instance\n                .methods()\n                .$method($($arg,)*)\n                .call()\n                .await\n                .expect_err(\"should return a revert error\");\n            assert_assert_ne_containing_msg($($arg,)* error);\n        }\n    }\n\n    {\n        reverts_with_assert_ne_msg!((32, 32,), assert_ne_primitive, call, \"assertion failed\");\n        reverts_with_assert_ne_msg!((32, 32,), assert_ne_primitive, simulate, \"assertion failed\");\n    }\n    {\n        let test_struct = TestStruct {\n            field_1: true,\n            field_2: 64,\n        };\n\n        reverts_with_assert_ne_msg!(\n            (test_struct.clone(), test_struct.clone(),),\n            assert_ne_struct,\n            call,\n            \"assertion failed\"\n        );\n\n        reverts_with_assert_ne_msg!(\n            (test_struct.clone(), test_struct.clone(),),\n            assert_ne_struct,\n            simulate,\n            \"assertion failed\"\n        );\n    }\n    {\n        let test_enum = TestEnum::VariantOne;\n        reverts_with_assert_ne_msg!(\n            (test_enum.clone(), test_enum.clone(),),\n            assert_ne_enum,\n            call,\n            \"assertion failed\"\n        );\n\n        reverts_with_assert_ne_msg!(\n            (test_enum.clone(), test_enum.clone(),),\n            assert_ne_enum,\n            simulate,\n            \"assertion failed\"\n        );\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn script_asserts_log() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Script(\n            name = \"LogScript\",\n            project = \"e2e/sway/scripts/script_asserts\"\n        )),\n        LoadScript(\n            name = \"script_instance\",\n            script = \"LogScript\",\n            wallet = \"wallet\"\n        )\n    );\n    macro_rules! reverts_with_msg {\n        ($arg:expr, call, $msg:expr) => {\n            let error = script_instance\n                .main($arg)\n                .call()\n                .await\n                .expect_err(\"should return a revert error\");\n            assert_revert_containing_msg($msg, error);\n        };\n        ($arg:expr, simulate, $msg:expr) => {\n            let error = script_instance\n                .main($arg)\n                .simulate(Execution::realistic())\n                .await\n                .expect_err(\"should return a revert error\");\n            assert_revert_containing_msg($msg, error);\n        };\n    }\n\n    macro_rules! reverts_with_assert_eq_ne_msg {\n        ($arg:expr, call, $msg:expr) => {\n            let error = script_instance\n                .main($arg)\n                .call()\n                .await\n                .expect_err(\"should return a revert error\");\n            assert_revert_containing_msg($msg, error);\n        };\n        ($arg:expr, simulate, $msg:expr) => {\n            let error = script_instance\n                .main($arg)\n                .simulate(Execution::realistic())\n                .await\n                .expect_err(\"should return a revert error\");\n            assert_revert_containing_msg($msg, error);\n        };\n    }\n    {\n        reverts_with_msg!(\n            MatchEnum::AssertPrimitive((32, 64)),\n            call,\n            \"assertion failed\"\n        );\n        reverts_with_msg!(\n            MatchEnum::AssertPrimitive((32, 64)),\n            simulate,\n            \"assertion failed\"\n        );\n    }\n    {\n        reverts_with_assert_eq_ne_msg!(\n            MatchEnum::AssertEqPrimitive((32, 64)),\n            call,\n            \"assertion failed: `(left == right)`\"\n        );\n        reverts_with_assert_eq_ne_msg!(\n            MatchEnum::AssertEqPrimitive((32, 64)),\n            simulate,\n            \"assertion failed: `(left == right)`\"\n        );\n    }\n    {\n        let test_struct = TestStruct {\n            field_1: true,\n            field_2: 64,\n        };\n\n        let test_struct2 = TestStruct {\n            field_1: false,\n            field_2: 32,\n        };\n        reverts_with_assert_eq_ne_msg!(\n            MatchEnum::AssertEqStruct((test_struct.clone(), test_struct2.clone(),)),\n            call,\n            \"assertion failed: `(left == right)`\"\n        );\n        reverts_with_assert_eq_ne_msg!(\n            MatchEnum::AssertEqStruct((test_struct.clone(), test_struct2.clone(),)),\n            simulate,\n            \"assertion failed: `(left == right)`\"\n        );\n    }\n    {\n        let test_enum = TestEnum::VariantOne;\n        let test_enum2 = TestEnum::VariantTwo;\n\n        reverts_with_assert_eq_ne_msg!(\n            MatchEnum::AssertEqEnum((test_enum.clone(), test_enum2.clone(),)),\n            call,\n            \"assertion failed: `(left == right)`\"\n        );\n        reverts_with_assert_eq_ne_msg!(\n            MatchEnum::AssertEqEnum((test_enum.clone(), test_enum2.clone(),)),\n            simulate,\n            \"assertion failed: `(left == right)`\"\n        );\n    }\n\n    {\n        reverts_with_assert_eq_ne_msg!(\n            MatchEnum::AssertNePrimitive((32, 32)),\n            call,\n            \"assertion failed: `(left != right)`\"\n        );\n        reverts_with_assert_eq_ne_msg!(\n            MatchEnum::AssertNePrimitive((32, 32)),\n            simulate,\n            \"assertion failed: `(left != right)`\"\n        );\n    }\n    {\n        let test_struct = TestStruct {\n            field_1: true,\n            field_2: 64,\n        };\n        reverts_with_assert_eq_ne_msg!(\n            MatchEnum::AssertNeStruct((test_struct.clone(), test_struct.clone(),)),\n            call,\n            \"assertion failed: `(left != right)`\"\n        );\n        reverts_with_assert_eq_ne_msg!(\n            MatchEnum::AssertNeStruct((test_struct.clone(), test_struct.clone(),)),\n            simulate,\n            \"assertion failed: `(left != right)`\"\n        );\n    }\n    {\n        let test_enum = TestEnum::VariantOne;\n\n        reverts_with_assert_eq_ne_msg!(\n            MatchEnum::AssertNeEnum((test_enum.clone(), test_enum.clone(),)),\n            call,\n            \"assertion failed: `(left != right)`\"\n        );\n        reverts_with_assert_eq_ne_msg!(\n            MatchEnum::AssertNeEnum((test_enum.clone(), test_enum.clone(),)),\n            simulate,\n            \"assertion failed: `(left != right)`\"\n        );\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn contract_token_ops_error_messages() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TestContract\",\n            project = \"e2e/sway/contracts/token_ops\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TestContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n    let contract_methods = contract_instance.methods();\n\n    {\n        let contract_id = contract_instance.contract_id();\n        let asset_id = contract_id.asset_id(&SubAssetId::zeroed());\n        let address = wallet.address();\n\n        let error = contract_methods\n            .transfer(1_000_000, asset_id, address.into())\n            .simulate(Execution::realistic())\n            .await\n            .expect_err(\"should return a revert error\");\n        assert_revert_containing_msg(\"failed transfer to address\", error);\n\n        let error = contract_methods\n            .transfer(1_000_000, asset_id, address.into())\n            .call()\n            .await\n            .expect_err(\"should return a revert error\");\n\n        assert_revert_containing_msg(\"failed transfer to address\", error);\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn log_results() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"MyContract\",\n            project = \"e2e/sway/logs/contract_logs\"\n        ),),\n        Deploy(\n            contract = \"MyContract\",\n            name = \"contract_instance\",\n            wallet = \"wallet\",\n            random_salt = false,\n        )\n    );\n\n    let response = contract_instance\n        .methods()\n        .produce_bad_logs()\n        .call()\n        .await?;\n\n    let log = response.decode_logs();\n\n    let expected_err = format!(\n        \"codec: missing log formatter for log_id: `LogId({:?}, \\\"128\\\")`, data: `{:?}`. \\\n         Consider adding external contracts using `with_contracts()`\",\n        contract_instance.id(),\n        [0u8; 8]\n    );\n\n    let succeeded = log.filter_succeeded();\n    let failed = log.filter_failed();\n    assert_eq!(succeeded, vec![\"123\".to_string()]);\n    assert_eq!(failed.first().unwrap().to_string(), expected_err);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn can_configure_decoder_for_contract_log_decoding() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"MyContract\",\n            project = \"e2e/sway/contracts/needs_custom_decoder\"\n        ),),\n        Deploy(\n            contract = \"MyContract\",\n            name = \"contract_instance\",\n            wallet = \"wallet\",\n            random_salt = false,\n        )\n    );\n\n    let methods = contract_instance.methods();\n    {\n        // Single call: decoding with too low max_tokens fails\n        let response = methods\n            .i_log_a_1k_el_array()\n            .with_decoder_config(DecoderConfig {\n                max_tokens: 100,\n                ..Default::default()\n            })\n            .call()\n            .await?;\n\n        response.decode_logs_with_type::<[u8; 1000]>().expect_err(\n            \"Should have failed since there are more tokens than what is supported by default.\",\n        );\n\n        let logs = response.decode_logs();\n        assert!(\n            !logs.filter_failed().is_empty(),\n            \"Should have had failed to decode logs since there are more tokens than what is supported by default\"\n        );\n    }\n    {\n        // Single call: increasing limits makes the test pass\n        let response = methods\n            .i_log_a_1k_el_array()\n            .with_decoder_config(DecoderConfig {\n                max_tokens: 1001,\n                ..Default::default()\n            })\n            .call()\n            .await?;\n\n        let logs = response.decode_logs_with_type::<[u8; 1000]>()?;\n        assert_eq!(logs, vec![[0u8; 1000]]);\n\n        let logs = response.decode_logs();\n        assert!(!logs.filter_succeeded().is_empty());\n    }\n    {\n        // Multi call: decoding with too low max_tokens will fail\n        let response = CallHandler::new_multi_call(wallet.clone())\n            .add_call(methods.i_log_a_1k_el_array())\n            .with_decoder_config(DecoderConfig {\n                max_tokens: 100,\n                ..Default::default()\n            })\n            .call::<((),)>()\n            .await?;\n\n        response.decode_logs_with_type::<[u8; 1000]>().expect_err(\n            \"should have failed since there are more tokens than what is supported by default\",\n        );\n\n        let logs = response.decode_logs();\n        assert!(\n            !logs.filter_failed().is_empty(),\n            \"should have had failed to decode logs since there are more tokens than what is supported by default\"\n        );\n    }\n    {\n        // Multi call: increasing limits makes the test pass\n        let response = CallHandler::new_multi_call(wallet.clone())\n            .add_call(methods.i_log_a_1k_el_array())\n            .with_decoder_config(DecoderConfig {\n                max_tokens: 1001,\n                ..Default::default()\n            })\n            .call::<((),)>()\n            .await?;\n\n        let logs = response.decode_logs_with_type::<[u8; 1000]>()?;\n        assert_eq!(logs, vec![[0u8; 1000]]);\n\n        let logs = response.decode_logs();\n        assert!(!logs.filter_succeeded().is_empty());\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn can_configure_decoder_for_script_log_decoding() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Script(\n            name = \"LogScript\",\n            project = \"e2e/sway/scripts/script_needs_custom_decoder\"\n        )),\n        LoadScript(\n            name = \"script_instance\",\n            script = \"LogScript\",\n            wallet = \"wallet\"\n        )\n    );\n\n    {\n        // Cannot decode the produced log with too low max_tokens\n        let response = script_instance\n            .main(true)\n            .with_decoder_config(DecoderConfig {\n                max_tokens: 100,\n                ..Default::default()\n            })\n            .call()\n            .await?;\n\n        response\n            .decode_logs_with_type::<[u8; 1000]>()\n            .expect_err(\"Cannot decode the log with default decoder config\");\n\n        let logs = response.decode_logs();\n        assert!(!logs.filter_failed().is_empty())\n    }\n    {\n        // When the token limit is bumped log decoding succeeds\n        let response = script_instance\n            .main(true)\n            .with_decoder_config(DecoderConfig {\n                max_tokens: 1001,\n                ..Default::default()\n            })\n            .call()\n            .await?;\n\n        let logs = response.decode_logs_with_type::<[u8; 1000]>()?;\n        assert_eq!(logs, vec![[0u8; 1000]]);\n\n        let logs = response.decode_logs();\n        assert!(!logs.filter_succeeded().is_empty())\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn contract_heap_log() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"MyContract\",\n            project = \"e2e/sway/logs/contract_logs\"\n        ),),\n        Deploy(\n            contract = \"MyContract\",\n            name = \"contract_instance\",\n            wallet = \"wallet\",\n            random_salt = false,\n        )\n    );\n    let contract_methods = contract_instance.methods();\n\n    {\n        let response = contract_methods.produce_string_slice_log().call().await?;\n        let logs = response.decode_logs_with_type::<AsciiString>()?;\n\n        assert_eq!(\"fuel\".to_string(), logs.first().unwrap().to_string());\n    }\n    {\n        let response = contract_methods.produce_string_log().call().await?;\n        let logs = response.decode_logs_with_type::<String>()?;\n\n        assert_eq!(vec![\"fuel\".to_string()], logs);\n    }\n    {\n        let response = contract_methods.produce_bytes_log().call().await?;\n        let logs = response.decode_logs_with_type::<Bytes>()?;\n\n        assert_eq!(vec![Bytes(\"fuel\".as_bytes().to_vec())], logs);\n    }\n    {\n        let response = contract_methods.produce_raw_slice_log().call().await?;\n        let logs = response.decode_logs_with_type::<RawSlice>()?;\n\n        assert_eq!(vec![RawSlice(\"fuel\".as_bytes().to_vec())], logs);\n    }\n    {\n        let v = [1u16, 2, 3].to_vec();\n        let some_enum = EnumWithGeneric::VariantOne(v);\n        let other_enum = EnumWithGeneric::VariantTwo;\n        let v1 = vec![some_enum.clone(), other_enum, some_enum];\n        let expected_vec = vec![vec![v1.clone(), v1]];\n\n        let response = contract_methods.produce_vec_log().call().await?;\n        let logs = response.decode_logs_with_type::<Vec<Vec<Vec<EnumWithGeneric<Vec<u16>>>>>>()?;\n\n        assert_eq!(vec![expected_vec], logs);\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn script_heap_log() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Script(\n            name = \"LogScript\",\n            project = \"e2e/sway/logs/script_heap_logs\"\n        )),\n        LoadScript(\n            name = \"script_instance\",\n            script = \"LogScript\",\n            wallet = \"wallet\"\n        )\n    );\n    let response = script_instance.main().call().await?;\n\n    {\n        let logs = response.decode_logs_with_type::<AsciiString>()?;\n\n        assert_eq!(\"fuel\".to_string(), logs.first().unwrap().to_string());\n    }\n    {\n        let logs = response.decode_logs_with_type::<String>()?;\n\n        assert_eq!(vec![\"fuel\".to_string()], logs);\n    }\n    {\n        let logs = response.decode_logs_with_type::<Bytes>()?;\n\n        assert_eq!(vec![Bytes(\"fuel\".as_bytes().to_vec())], logs);\n    }\n    {\n        let logs = response.decode_logs_with_type::<RawSlice>()?;\n\n        assert_eq!(vec![RawSlice(\"fuel\".as_bytes().to_vec())], logs);\n    }\n    {\n        let v = [1u16, 2, 3].to_vec();\n        let some_enum = EnumWithGeneric::VariantOne(v);\n        let other_enum = EnumWithGeneric::VariantTwo;\n        let v1 = vec![some_enum.clone(), other_enum, some_enum];\n        let expected_vec = vec![vec![v1.clone(), v1]];\n\n        let logs = response.decode_logs_with_type::<Vec<Vec<Vec<EnumWithGeneric<Vec<u16>>>>>>()?;\n\n        assert_eq!(vec![expected_vec], logs);\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn contract_panic() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"LogContract\",\n            project = \"e2e/sway/logs/contract_logs\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"LogContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    macro_rules! reverts_with_msg {\n        ($method:ident, call, $msg:expr) => {\n            let error = contract_instance\n                .methods()\n                .$method()\n                .call()\n                .await\n                .expect_err(\"should return a revert error\");\n\n            assert_revert_containing_msg($msg, error);\n        };\n        ($method:ident, simulate, $msg:expr) => {\n            let error = contract_instance\n                .methods()\n                .$method()\n                .simulate(Execution::realistic())\n                .await\n                .expect_err(\"should return a revert error\");\n\n            assert_revert_containing_msg($msg, error);\n        };\n    }\n\n    {\n        reverts_with_msg!(produce_panic, call, \"some panic message\");\n        reverts_with_msg!(produce_panic, simulate, \"some panic message\");\n    }\n    {\n        reverts_with_msg!(\n            produce_panic_with_error,\n            call,\n            \"some complex error B: B { id: 42, val: 36 }\"\n        );\n        reverts_with_msg!(\n            produce_panic_with_error,\n            simulate,\n            \"some complex error B: B { id: 42, val: 36 }\"\n        );\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn contract_with_contract_panic() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(\n            Contract(name = \"MyContract\", project = \"e2e/sway/logs/contract_logs\",),\n            Contract(\n                name = \"ContractCaller\",\n                project = \"e2e/sway/logs/contract_with_contract_logs\",\n            )\n        ),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"MyContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n        Deploy(\n            name = \"contract_caller_instance\",\n            contract = \"ContractCaller\",\n            wallet = \"wallet\",\n            random_salt = false,\n        )\n    );\n\n    macro_rules! reverts_with_msg {\n        ($method:ident, call, $msg:expr) => {\n            let error = contract_caller_instance\n                .methods()\n                .$method(contract_instance.id())\n                .with_contracts(&[&contract_instance])\n                .call()\n                .await\n                .expect_err(\"should return a revert error\");\n\n            assert_revert_containing_msg($msg, error);\n        };\n        ($method:ident, simulate, $msg:expr) => {\n            let error = contract_caller_instance\n                .methods()\n                .$method(contract_instance.id())\n                .with_contracts(&[&contract_instance])\n                .simulate(Execution::realistic())\n                .await\n                .expect_err(\"should return a revert error\");\n\n            assert_revert_containing_msg($msg, error);\n        };\n    }\n\n    {\n        reverts_with_msg!(panic_from_external_contract, call, \"some panic message\");\n        reverts_with_msg!(panic_from_external_contract, simulate, \"some panic message\");\n    }\n    {\n        reverts_with_msg!(\n            panic_error_from_external_contract,\n            call,\n            \"some complex error B: B { id: 42, val: 36 }\"\n        );\n        reverts_with_msg!(\n            panic_error_from_external_contract,\n            simulate,\n            \"some complex error B: B { id: 42, val: 36 }\"\n        );\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn script_panic() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Script(\n            name = \"LogScript\",\n            project = \"e2e/sway/logs/script_revert_logs\"\n        )),\n        LoadScript(\n            name = \"script_instance\",\n            script = \"LogScript\",\n            wallet = \"wallet\"\n        )\n    );\n\n    macro_rules! reverts_with_msg {\n        ($arg:expr, call, $msg:expr) => {\n            let error = script_instance\n                .main($arg)\n                .call()\n                .await\n                .expect_err(\"should return a revert error\");\n            assert_revert_containing_msg($msg, error);\n        };\n        ($arg:expr, simulate, $msg:expr) => {\n            let error = script_instance\n                .main($arg)\n                .simulate(Execution::realistic())\n                .await\n                .expect_err(\"should return a revert error\");\n            assert_revert_containing_msg($msg, error);\n        };\n    }\n\n    {\n        reverts_with_msg!(MatchEnum::Panic, call, \"some panic message\");\n        reverts_with_msg!(MatchEnum::Panic, simulate, \"some panic message\");\n    }\n    {\n        reverts_with_msg!(\n            MatchEnum::PanicError,\n            call,\n            \"some complex error B: B { id: 42, val: 36 }\"\n        );\n        reverts_with_msg!(\n            MatchEnum::PanicError,\n            simulate,\n            \"some complex error B: B { id: 42, val: 36 }\"\n        );\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\n#[allow(unused_variables)]\nasync fn script_with_contract_panic() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(\n            Contract(name = \"MyContract\", project = \"e2e/sway/logs/contract_logs\",),\n            Script(\n                name = \"LogScript\",\n                project = \"e2e/sway/logs/script_with_contract_logs\"\n            )\n        ),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"MyContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n        LoadScript(\n            name = \"script_instance\",\n            script = \"LogScript\",\n            wallet = \"wallet\"\n        )\n    );\n\n    macro_rules! reverts_with_msg {\n        ($arg1:expr, $arg2:expr, call, $msg:expr) => {\n            let error = script_instance\n                .main($arg1, $arg2)\n                .with_contracts(&[&contract_instance])\n                .call()\n                .await\n                .expect_err(\"should return a revert error\");\n            assert_revert_containing_msg($msg, error);\n        };\n        ($arg1:expr, $arg2:expr, simulate, $msg:expr) => {\n            let error = script_instance\n                .main($arg1, $arg2)\n                .with_contracts(&[&contract_instance])\n                .simulate(Execution::realistic())\n                .await\n                .expect_err(\"should return a revert error\");\n            assert_revert_containing_msg($msg, error);\n        };\n    }\n    let contract_id = contract_instance.id();\n\n    {\n        reverts_with_msg!(contract_id, MatchEnum::Panic, call, \"some panic message\");\n        reverts_with_msg!(\n            contract_id,\n            MatchEnum::Panic,\n            simulate,\n            \"some panic message\"\n        );\n    }\n    {\n        reverts_with_msg!(\n            contract_id,\n            MatchEnum::PanicError,\n            call,\n            \"some complex error B: B { id: 42, val: 36 }\"\n        );\n        reverts_with_msg!(\n            contract_id,\n            MatchEnum::PanicError,\n            simulate,\n            \"some complex error B: B { id: 42, val: 36 }\"\n        );\n    }\n\n    Ok(())\n}\n"
  },
  {
    "path": "e2e/tests/predicates.rs",
    "content": "use std::default::Default;\n\nuse fuels::{\n    accounts::signers::private_key::PrivateKeySigner,\n    core::{\n        codec::{ABIEncoder, EncoderConfig},\n        traits::Tokenizable,\n    },\n    prelude::*,\n    programs::executable::Executable,\n    types::{coin::Coin, coin_type::CoinType, input::Input, message::Message, output::Output},\n};\nuse rand::thread_rng;\n\nasync fn assert_address_balance(\n    address: &Address,\n    provider: &Provider,\n    asset_id: &AssetId,\n    amount: u64,\n) {\n    let balance = provider\n        .get_asset_balance(address, asset_id)\n        .await\n        .expect(\"Could not retrieve balance\");\n    assert_eq!(balance, amount as u128);\n}\n\nfn get_test_coins_and_messages(\n    address: Address,\n    num_coins: u64,\n    num_messages: u64,\n    amount: u64,\n    start_nonce: u64,\n) -> (Vec<Coin>, Vec<Message>, AssetId) {\n    let asset_id = AssetId::zeroed();\n    let coins = setup_single_asset_coins(address, asset_id, num_coins, amount);\n    let messages = (0..num_messages)\n        .map(|i| {\n            setup_single_message(\n                Address::default(),\n                address,\n                amount,\n                (start_nonce + i).into(),\n                vec![],\n            )\n        })\n        .collect();\n\n    (coins, messages, asset_id)\n}\n\nfn get_test_message_w_data(address: Address, amount: u64, nonce: u64) -> Message {\n    setup_single_message(\n        Address::default(),\n        address,\n        amount,\n        nonce.into(),\n        vec![1, 2, 3],\n    )\n}\n\n// Setup function used to assign coins and messages to a predicate address\n// and create a `receiver` wallet\nasync fn setup_predicate_test(\n    predicate_address: Address,\n    num_coins: u64,\n    num_messages: u64,\n    amount: u64,\n) -> Result<(Provider, u64, Wallet, u64, AssetId, Wallet)> {\n    let receiver_num_coins = 1;\n    let receiver_amount = 1;\n    let receiver_balance = receiver_num_coins * receiver_amount;\n\n    let predicate_balance = (num_coins + num_messages) * amount;\n    let mut rng = thread_rng();\n    let receiver_signer = PrivateKeySigner::random(&mut rng);\n    let extra_wallet_signer = PrivateKeySigner::random(&mut rng);\n\n    let (mut coins, messages, asset_id) =\n        get_test_coins_and_messages(predicate_address, num_coins, num_messages, amount, 0);\n\n    coins.extend(setup_single_asset_coins(\n        receiver_signer.address(),\n        asset_id,\n        receiver_num_coins,\n        receiver_amount,\n    ));\n    coins.extend(setup_single_asset_coins(\n        extra_wallet_signer.address(),\n        AssetId::zeroed(),\n        10_000,\n        10_000,\n    ));\n\n    coins.extend(setup_single_asset_coins(\n        predicate_address,\n        AssetId::from([1u8; 32]),\n        num_coins,\n        amount,\n    ));\n\n    let provider = setup_test_provider(coins, messages, None, None).await?;\n    let receiver_wallet = Wallet::new(receiver_signer.clone(), provider.clone());\n    let extra_wallet = Wallet::new(extra_wallet_signer.clone(), provider.clone());\n\n    Ok((\n        provider,\n        predicate_balance,\n        receiver_wallet,\n        receiver_balance,\n        asset_id,\n        extra_wallet,\n    ))\n}\n\n#[tokio::test]\nasync fn transfer_coins_and_messages_to_predicate() -> Result<()> {\n    let num_coins = 16;\n    let num_messages = 32;\n    let amount = 64;\n    let balance_to_send = 42;\n\n    let signer = PrivateKeySigner::random(&mut thread_rng());\n\n    let (coins, messages, asset_id) =\n        get_test_coins_and_messages(signer.address(), num_coins, num_messages, amount, 0);\n\n    let provider = setup_test_provider(coins, messages, None, None).await?;\n\n    let wallet = Wallet::new(signer, provider.clone());\n\n    let predicate =\n        Predicate::load_from(\"sway/predicates/basic_predicate/out/release/basic_predicate.bin\")?\n            .with_provider(provider.clone());\n\n    wallet\n        .transfer(\n            predicate.address(),\n            balance_to_send,\n            asset_id,\n            TxPolicies::default(),\n        )\n        .await?;\n\n    // The predicate has received the funds\n    assert_address_balance(&predicate.address(), &provider, &asset_id, balance_to_send).await;\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn spend_predicate_coins_messages_basic() -> Result<()> {\n    abigen!(Predicate(\n        name = \"MyPredicate\",\n        abi = \"e2e/sway/predicates/basic_predicate/out/release/basic_predicate-abi.json\"\n    ));\n\n    let predicate_data = MyPredicateEncoder::default().encode_data(4097, 4097)?;\n\n    let mut predicate: Predicate =\n        Predicate::load_from(\"sway/predicates/basic_predicate/out/release/basic_predicate.bin\")?\n            .with_data(predicate_data);\n\n    let num_coins = 4;\n    let num_messages = 8;\n    let amount = 16;\n    let (provider, predicate_balance, receiver, receiver_balance, asset_id, _) =\n        setup_predicate_test(predicate.address(), num_coins, num_messages, amount).await?;\n\n    predicate.set_provider(provider.clone());\n\n    let amount_to_send = 128;\n    let fee = predicate\n        .transfer(\n            receiver.address(),\n            amount_to_send,\n            asset_id,\n            TxPolicies::default(),\n        )\n        .await?\n        .tx_status\n        .total_fee;\n\n    // The predicate has spent the funds\n    let predicate_current_balance = predicate_balance - amount_to_send - fee;\n    assert_address_balance(\n        &predicate.address(),\n        &provider,\n        &asset_id,\n        predicate_current_balance,\n    )\n    .await;\n\n    // Funds were transferred\n    assert_address_balance(\n        &receiver.address(),\n        &provider,\n        &asset_id,\n        receiver_balance + amount_to_send,\n    )\n    .await;\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn pay_with_predicate() -> Result<()> {\n    abigen!(\n        Contract(\n            name = \"MyContract\",\n            abi = \"e2e/sway/contracts/contract_test/out/release/contract_test-abi.json\"\n        ),\n        Predicate(\n            name = \"MyPredicate\",\n            abi = \"e2e/sway/types/predicates/u64/out/release/u64-abi.json\"\n        )\n    );\n\n    let predicate_data = MyPredicateEncoder::default().encode_data(32768)?;\n\n    let mut predicate: Predicate =\n        Predicate::load_from(\"sway/types/predicates/u64/out/release/u64.bin\")?\n            .with_data(predicate_data);\n\n    let num_coins = 4;\n    let num_messages = 8;\n    let amount = 16;\n    let (provider, predicate_balance, _receiver, _receiver_balance, _asset_id, _) =\n        setup_predicate_test(predicate.address(), num_coins, num_messages, amount).await?;\n\n    predicate.set_provider(provider.clone());\n\n    let deploy_response = Contract::load_from(\n        \"sway/contracts/contract_test/out/release/contract_test.bin\",\n        LoadConfiguration::default(),\n    )?\n    .deploy_if_not_exists(&predicate, TxPolicies::default())\n    .await?;\n\n    let contract_methods =\n        MyContract::new(deploy_response.contract_id, predicate.clone()).methods();\n\n    let consensus_parameters = provider.consensus_parameters().await?;\n    let deploy_fee = deploy_response.tx_status.unwrap().total_fee;\n    assert_eq!(\n        predicate\n            .get_asset_balance(consensus_parameters.base_asset_id())\n            .await?,\n        (predicate_balance - deploy_fee) as u128\n    );\n\n    let response = contract_methods\n        .initialize_counter(42) // Build the ABI call\n        .call()\n        .await?;\n\n    assert_eq!(42, response.value);\n    assert_eq!(\n        predicate\n            .get_asset_balance(consensus_parameters.base_asset_id())\n            .await?,\n        (predicate_balance - deploy_fee - response.tx_status.total_fee) as u128\n    );\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn pay_with_predicate_vector_data() -> Result<()> {\n    abigen!(\n        Contract(\n            name = \"MyContract\",\n            abi = \"e2e/sway/contracts/contract_test/out/release/contract_test-abi.json\"\n        ),\n        Predicate(\n            name = \"MyPredicate\",\n            abi =\n                \"e2e/sway/types/predicates/predicate_vector/out/release/predicate_vector-abi.json\"\n        )\n    );\n\n    let predicate_data = MyPredicateEncoder::default().encode_data(12, 30, vec![2, 4, 42])?;\n\n    let mut predicate: Predicate = Predicate::load_from(\n        \"sway/types/predicates/predicate_vector/out/release/predicate_vector.bin\",\n    )?\n    .with_data(predicate_data);\n\n    let num_coins = 4;\n    let num_messages = 8;\n    let amount = 16;\n    let (provider, predicate_balance, _receiver, _receiver_balance, _asset_id, _) =\n        setup_predicate_test(predicate.address(), num_coins, num_messages, amount).await?;\n\n    predicate.set_provider(provider.clone());\n\n    let deploy_response = Contract::load_from(\n        \"sway/contracts/contract_test/out/release/contract_test.bin\",\n        LoadConfiguration::default(),\n    )?\n    .deploy_if_not_exists(&predicate, TxPolicies::default())\n    .await?;\n\n    let contract_methods =\n        MyContract::new(deploy_response.contract_id, predicate.clone()).methods();\n\n    let consensus_parameters = provider.consensus_parameters().await?;\n    let deploy_fee = deploy_response.tx_status.unwrap().total_fee;\n    assert_eq!(\n        predicate\n            .get_asset_balance(consensus_parameters.base_asset_id())\n            .await?,\n        (predicate_balance - deploy_fee) as u128\n    );\n\n    let response = contract_methods.initialize_counter(42).call().await?;\n\n    assert_eq!(42, response.value);\n    assert_eq!(\n        predicate\n            .get_asset_balance(consensus_parameters.base_asset_id())\n            .await?,\n        (predicate_balance - deploy_fee - response.tx_status.total_fee) as u128\n    );\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn predicate_contract_transfer() -> Result<()> {\n    abigen!(Predicate(\n        name = \"MyPredicate\",\n        abi = \"e2e/sway/types/predicates/predicate_vector/out/release/predicate_vector-abi.json\"\n    ));\n\n    let predicate_data = MyPredicateEncoder::default().encode_data(2, 40, vec![2, 4, 42])?;\n\n    let mut predicate: Predicate = Predicate::load_from(\n        \"sway/types/predicates/predicate_vector/out/release/predicate_vector.bin\",\n    )?\n    .with_data(predicate_data);\n\n    let num_coins = 4;\n    let num_messages = 8;\n    let amount = 300;\n    let (provider, _predicate_balance, _receiver, _receiver_balance, _asset_id, _) =\n        setup_predicate_test(predicate.address(), num_coins, num_messages, amount).await?;\n\n    predicate.set_provider(provider.clone());\n\n    let contract_id = Contract::load_from(\n        \"sway/contracts/contract_test/out/release/contract_test.bin\",\n        LoadConfiguration::default(),\n    )?\n    .deploy_if_not_exists(&predicate, TxPolicies::default())\n    .await?\n    .contract_id;\n\n    let contract_balances = provider.get_contract_balances(&contract_id).await?;\n    assert!(contract_balances.is_empty());\n\n    let amount = 300;\n    predicate\n        .force_transfer_to_contract(\n            contract_id,\n            amount,\n            AssetId::zeroed(),\n            TxPolicies::default(),\n        )\n        .await?;\n\n    let contract_balances = predicate\n        .try_provider()?\n        .get_contract_balances(&contract_id)\n        .await?;\n    assert_eq!(contract_balances.len(), 1);\n\n    let random_asset_balance = contract_balances.get(&AssetId::zeroed()).unwrap();\n    assert_eq!(*random_asset_balance, 300);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn predicate_transfer_to_base_layer() -> Result<()> {\n    use std::str::FromStr;\n\n    abigen!(Predicate(\n        name = \"MyPredicate\",\n        abi = \"e2e/sway/types/predicates/predicate_vector/out/release/predicate_vector-abi.json\"\n    ));\n\n    let predicate_data = MyPredicateEncoder::default().encode_data(22, 20, vec![2, 4, 42])?;\n\n    let mut predicate: Predicate = Predicate::load_from(\n        \"sway/types/predicates/predicate_vector/out/release/predicate_vector.bin\",\n    )?\n    .with_data(predicate_data);\n\n    let num_coins = 4;\n    let num_messages = 8;\n    let amount = 300;\n    let (provider, _predicate_balance, _receiver, _receiver_balance, _asset_id, _) =\n        setup_predicate_test(predicate.address(), num_coins, num_messages, amount).await?;\n\n    predicate.set_provider(provider.clone());\n\n    let amount = 1000;\n    let base_layer_address =\n        Address::from_str(\"0x4710162c2e3a95a6faff05139150017c9e38e5e280432d546fae345d6ce6d8fe\")?;\n\n    let withdraw_response = predicate\n        .withdraw_to_base_layer(base_layer_address, amount, TxPolicies::default())\n        .await?;\n\n    // Create the next commit block to be able generate the proof\n    provider.produce_blocks(1, None).await?;\n\n    let proof = predicate\n        .try_provider()?\n        .get_message_proof(\n            &withdraw_response.tx_id,\n            &withdraw_response.nonce,\n            None,\n            Some(2),\n        )\n        .await?;\n\n    assert_eq!(proof.amount, amount);\n    assert_eq!(proof.recipient, base_layer_address);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn predicate_transfer_with_signed_resources() -> Result<()> {\n    abigen!(Predicate(\n        name = \"MyPredicate\",\n        abi = \"e2e/sway/types/predicates/predicate_vector/out/release/predicate_vector-abi.json\"\n    ));\n\n    let predicate_data = MyPredicateEncoder::default().encode_data(2, 40, vec![2, 4, 42])?;\n\n    let mut predicate: Predicate = Predicate::load_from(\n        \"sway/types/predicates/predicate_vector/out/release/predicate_vector.bin\",\n    )?\n    .with_data(predicate_data);\n\n    let predicate_num_coins = 4;\n    let predicate_num_messages = 3;\n    let predicate_amount = 1000;\n    let predicate_balance = (predicate_num_coins + predicate_num_messages) * predicate_amount;\n\n    let signer = PrivateKeySigner::random(&mut thread_rng());\n    let wallet_num_coins = 4;\n    let wallet_num_messages = 3;\n    let wallet_amount = 1000;\n    let wallet_balance = (wallet_num_coins + wallet_num_messages) * wallet_amount;\n\n    let (mut coins, mut messages, asset_id) = get_test_coins_and_messages(\n        predicate.address(),\n        predicate_num_coins,\n        predicate_num_messages,\n        predicate_amount,\n        0,\n    );\n    let (wallet_coins, wallet_messages, _) = get_test_coins_and_messages(\n        signer.address(),\n        wallet_num_coins,\n        wallet_num_messages,\n        wallet_amount,\n        predicate_num_messages,\n    );\n\n    coins.extend(wallet_coins);\n    messages.extend(wallet_messages);\n\n    let provider = setup_test_provider(coins, messages, None, None).await?;\n    let wallet = Wallet::new(signer.clone(), provider.clone());\n    predicate.set_provider(provider.clone());\n\n    let mut inputs = wallet\n        .get_asset_inputs_for_amount(asset_id, wallet_balance.into(), None)\n        .await?;\n    let predicate_inputs = predicate\n        .get_asset_inputs_for_amount(asset_id, predicate_balance.into(), None)\n        .await?;\n    inputs.extend(predicate_inputs);\n\n    let outputs = vec![Output::change(predicate.address(), 0, asset_id)];\n\n    let mut tb = ScriptTransactionBuilder::prepare_transfer(inputs, outputs, Default::default());\n    tb.add_signer(signer)?;\n\n    let tx = tb.build(&provider).await?;\n\n    let tx_status = provider.send_transaction_and_await_commit(tx).await?;\n\n    assert_address_balance(\n        &predicate.address(),\n        &provider,\n        &asset_id,\n        predicate_balance + wallet_balance - tx_status.total_fee(),\n    )\n    .await;\n\n    Ok(())\n}\n\n#[tokio::test]\n#[allow(unused_variables)]\nasync fn contract_tx_and_call_params_with_predicate() -> Result<()> {\n    use fuels::prelude::*;\n\n    abigen!(\n        Contract(\n            name = \"MyContract\",\n            abi = \"e2e/sway/contracts/contract_test/out/release/contract_test-abi.json\"\n        ),\n        Predicate(\n            name = \"MyPredicate\",\n            abi =\n                \"e2e/sway/types/predicates/predicate_vector/out/release/predicate_vector-abi.json\"\n        )\n    );\n\n    let predicate_data = MyPredicateEncoder::default().encode_data(22, 20, vec![2, 4, 42])?;\n\n    let mut predicate: Predicate = Predicate::load_from(\n        \"sway/types/predicates/predicate_vector/out/release/predicate_vector.bin\",\n    )?\n    .with_data(predicate_data);\n\n    let num_coins = 1;\n    let num_messages = 1;\n    let amount = 1000;\n    let (provider, predicate_balance, _receiver, _receiver_balance, _asset_id, _) =\n        setup_predicate_test(predicate.address(), num_coins, num_messages, amount).await?;\n\n    predicate.set_provider(provider.clone());\n\n    let deploy_response = Contract::load_from(\n        \"./sway/contracts/contract_test/out/release/contract_test.bin\",\n        LoadConfiguration::default(),\n    )?\n    .deploy_if_not_exists(&predicate, TxPolicies::default())\n    .await?;\n\n    let contract_methods =\n        MyContract::new(deploy_response.contract_id, predicate.clone()).methods();\n\n    let tx_policies = TxPolicies::default().with_tip(100);\n\n    let call_params_amount = 100;\n    let call_params = CallParameters::default()\n        .with_amount(call_params_amount)\n        .with_asset_id(AssetId::zeroed());\n\n    {\n        let call_response = contract_methods\n            .get_msg_amount()\n            .with_tx_policies(tx_policies)\n            .call_params(call_params.clone())?\n            .call()\n            .await?;\n\n        let deploy_fee = deploy_response.tx_status.unwrap().total_fee;\n        let call_fee = call_response.tx_status.total_fee;\n        assert_eq!(\n            predicate.get_asset_balance(&AssetId::zeroed()).await?,\n            (predicate_balance - deploy_fee - call_params_amount - call_fee) as u128\n        );\n    }\n    {\n        let custom_asset = AssetId::from([1u8; 32]);\n\n        let response = contract_methods\n            .get_msg_amount()\n            .call_params(call_params)?\n            .add_custom_asset(custom_asset, 100, Some(Address::default()))\n            .call()\n            .await?;\n\n        assert_eq!(predicate.get_asset_balance(&custom_asset).await?, 900);\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\n#[allow(unused_variables)]\nasync fn diff_asset_predicate_payment() -> Result<()> {\n    use fuels::prelude::*;\n\n    abigen!(\n        Contract(\n            name = \"MyContract\",\n            abi = \"e2e/sway/contracts/contract_test/out/release/contract_test-abi.json\"\n        ),\n        Predicate(\n            name = \"MyPredicate\",\n            abi =\n                \"e2e/sway/types/predicates/predicate_vector/out/release/predicate_vector-abi.json\"\n        )\n    );\n\n    let predicate_data = MyPredicateEncoder::default().encode_data(28, 14, vec![2, 4, 42])?;\n\n    let mut predicate: Predicate = Predicate::load_from(\n        \"sway/types/predicates/predicate_vector/out/release/predicate_vector.bin\",\n    )?\n    .with_data(predicate_data);\n\n    let num_coins = 1;\n    let num_messages = 1;\n    let amount = 1_000_000_000;\n    let (provider, _predicate_balance, _receiver, _receiver_balance, _asset_id, _) =\n        setup_predicate_test(predicate.address(), num_coins, num_messages, amount).await?;\n\n    predicate.set_provider(provider.clone());\n\n    let contract_id = Contract::load_from(\n        \"./sway/contracts/contract_test/out/release/contract_test.bin\",\n        LoadConfiguration::default(),\n    )?\n    .deploy_if_not_exists(&predicate, TxPolicies::default())\n    .await?\n    .contract_id;\n\n    let contract_methods = MyContract::new(contract_id, predicate.clone()).methods();\n\n    let call_params = CallParameters::default()\n        .with_amount(1_000_000)\n        .with_asset_id(AssetId::from([1u8; 32]));\n\n    let response = contract_methods\n        .get_msg_amount()\n        .call_params(call_params)?\n        .call()\n        .await?;\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn predicate_default_configurables() -> Result<()> {\n    abigen!(Predicate(\n        name = \"MyPredicate\",\n        abi = \"e2e/sway/predicates/predicate_configurables/out/release/predicate_configurables-abi.json\"\n    ));\n\n    let new_struct = StructWithGeneric {\n        field_1: 8u8,\n        field_2: 16,\n    };\n    let new_enum = EnumWithGeneric::VariantOne(true);\n\n    let predicate_data = MyPredicateEncoder::default().encode_data(\n        true,\n        8,\n        (8, true),\n        [253, 254, 255],\n        new_struct,\n        new_enum,\n    )?;\n\n    let mut predicate: Predicate = Predicate::load_from(\n        \"sway/predicates/predicate_configurables/out/release/predicate_configurables.bin\",\n    )?\n    .with_data(predicate_data);\n\n    let num_coins = 4;\n    let num_messages = 8;\n    let amount = 16;\n    let (provider, predicate_balance, receiver, receiver_balance, asset_id, _) =\n        setup_predicate_test(predicate.address(), num_coins, num_messages, amount).await?;\n\n    predicate.set_provider(provider.clone());\n\n    let amount_to_send = predicate_balance - 1;\n    predicate\n        .transfer(\n            receiver.address(),\n            amount_to_send,\n            asset_id,\n            TxPolicies::default(),\n        )\n        .await?;\n\n    // The predicate has spent the funds\n    assert_address_balance(&predicate.address(), &provider, &asset_id, 0).await;\n\n    // Funds were transferred\n    assert_address_balance(\n        &receiver.address(),\n        &provider,\n        &asset_id,\n        receiver_balance + amount_to_send,\n    )\n    .await;\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn predicate_configurables() -> Result<()> {\n    // ANCHOR: predicate_configurables\n    abigen!(Predicate(\n        name = \"MyPredicate\",\n        abi = \"e2e/sway/predicates/predicate_configurables/out/release/predicate_configurables-abi.json\"\n    ));\n\n    let new_tuple = (16, false);\n    let new_array = [123, 124, 125];\n    let new_struct = StructWithGeneric {\n        field_1: 32u8,\n        field_2: 64,\n    };\n    let new_enum = EnumWithGeneric::VariantTwo;\n\n    let configurables = MyPredicateConfigurables::default()\n        .with_U8(8)?\n        .with_TUPLE(new_tuple)?\n        .with_ARRAY(new_array)?\n        .with_STRUCT(new_struct.clone())?\n        .with_ENUM(new_enum.clone())?;\n\n    let predicate_data = MyPredicateEncoder::default()\n        .encode_data(true, 8u8, new_tuple, new_array, new_struct, new_enum)?;\n\n    let mut predicate: Predicate = Predicate::load_from(\n        \"sway/predicates/predicate_configurables/out/release/predicate_configurables.bin\",\n    )?\n    .with_data(predicate_data)\n    .with_configurables(configurables);\n    // ANCHOR_END: predicate_configurables\n\n    let num_coins = 4;\n    let num_messages = 8;\n    let amount = 16;\n    let (provider, predicate_balance, receiver, receiver_balance, asset_id, _) =\n        setup_predicate_test(predicate.address(), num_coins, num_messages, amount).await?;\n\n    predicate.set_provider(provider.clone());\n\n    let amount_to_send = predicate_balance - 1;\n    let fee = predicate\n        .transfer(\n            receiver.address(),\n            amount_to_send,\n            asset_id,\n            TxPolicies::default(),\n        )\n        .await?\n        .tx_status\n        .total_fee;\n\n    // The predicate has spent the funds\n    assert_address_balance(&predicate.address(), &provider, &asset_id, 0).await;\n\n    // Funds were transferred\n    assert_address_balance(\n        &receiver.address(),\n        &provider,\n        &asset_id,\n        receiver_balance + predicate_balance - fee,\n    )\n    .await;\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn predicate_adjust_fee_persists_message_w_data() -> Result<()> {\n    abigen!(Predicate(\n        name = \"MyPredicate\",\n        abi = \"e2e/sway/predicates/basic_predicate/out/release/basic_predicate-abi.json\"\n    ));\n\n    let predicate_data = MyPredicateEncoder::default().encode_data(4097, 4097)?;\n\n    let mut predicate: Predicate =\n        Predicate::load_from(\"sway/predicates/basic_predicate/out/release/basic_predicate.bin\")?\n            .with_data(predicate_data);\n\n    let amount = 1000;\n    let coins = setup_single_asset_coins(predicate.address(), AssetId::zeroed(), 1, amount);\n    let message = get_test_message_w_data(predicate.address(), amount, Default::default());\n    let message_input = Input::resource_predicate(\n        CoinType::Message(message.clone()),\n        predicate.code().to_vec(),\n        predicate.data().to_vec(),\n    );\n\n    let provider = setup_test_provider(coins, vec![message.clone()], None, None).await?;\n    predicate.set_provider(provider.clone());\n\n    let mut tb = ScriptTransactionBuilder::prepare_transfer(\n        vec![message_input.clone()],\n        vec![],\n        TxPolicies::default(),\n    );\n    predicate.adjust_for_fee(&mut tb, 0).await?;\n\n    let tx = tb.build(&provider).await?;\n\n    assert_eq!(tx.inputs().len(), 2);\n    assert_eq!(tx.inputs()[0].message_id().unwrap(), message.message_id());\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn predicate_transfer_non_base_asset() -> Result<()> {\n    abigen!(Predicate(\n        name = \"MyPredicate\",\n        abi = \"e2e/sway/predicates/basic_predicate/out/release/basic_predicate-abi.json\"\n    ));\n\n    let predicate_data = MyPredicateEncoder::default().encode_data(32, 32)?;\n\n    let mut predicate: Predicate =\n        Predicate::load_from(\"sway/predicates/basic_predicate/out/release/basic_predicate.bin\")?\n            .with_data(predicate_data);\n\n    let signer = PrivateKeySigner::random(&mut thread_rng());\n\n    let amount = 5;\n    let non_base_asset_id = AssetId::new([1; 32]);\n\n    // wallet has base and predicate non base asset\n    let mut coins = setup_single_asset_coins(signer.address(), AssetId::zeroed(), 1, amount);\n    coins.extend(setup_single_asset_coins(\n        predicate.address(),\n        non_base_asset_id,\n        1,\n        amount,\n    ));\n\n    let provider = setup_test_provider(coins, vec![], None, None).await?;\n    predicate.set_provider(provider.clone());\n    let wallet = Wallet::new(signer.clone(), provider.clone());\n\n    let inputs = predicate\n        .get_asset_inputs_for_amount(non_base_asset_id, amount.into(), None)\n        .await?;\n    let consensus_parameters = provider.consensus_parameters().await?;\n    let outputs = vec![\n        Output::change(wallet.address(), 0, non_base_asset_id),\n        Output::change(wallet.address(), 0, *consensus_parameters.base_asset_id()),\n    ];\n\n    let mut tb = ScriptTransactionBuilder::prepare_transfer(\n        inputs,\n        outputs,\n        TxPolicies::default().with_tip(1),\n    );\n\n    tb.add_signer(signer)?;\n    wallet.adjust_for_fee(&mut tb, 0).await?;\n\n    let tx = tb.build(&provider).await?;\n\n    provider\n        .send_transaction_and_await_commit(tx)\n        .await?\n        .check(None)?;\n\n    let wallet_balance = wallet.get_asset_balance(&non_base_asset_id).await?;\n\n    assert_eq!(wallet_balance, amount as u128);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn predicate_can_access_manually_added_witnesses() -> Result<()> {\n    abigen!(Predicate(\n        name = \"MyPredicate\",\n        abi = \"e2e/sway/predicates/predicate_witnesses/out/release/predicate_witnesses-abi.json\"\n    ));\n\n    let predicate_data = MyPredicateEncoder::default().encode_data(0, 1)?;\n\n    let mut predicate: Predicate = Predicate::load_from(\n        \"sway/predicates/predicate_witnesses/out/release/predicate_witnesses.bin\",\n    )?\n    .with_data(predicate_data);\n\n    let num_coins = 4;\n    let num_messages = 0;\n    let amount = 16;\n    let (provider, predicate_balance, receiver, receiver_balance, asset_id, _) =\n        setup_predicate_test(predicate.address(), num_coins, num_messages, amount).await?;\n\n    predicate.set_provider(provider.clone());\n\n    let amount_to_send = 12u64;\n    let inputs = predicate\n        .get_asset_inputs_for_amount(asset_id, amount_to_send.into(), None)\n        .await?;\n    let outputs =\n        predicate.get_asset_outputs_for_amount(receiver.address(), asset_id, amount_to_send);\n\n    let mut tx = ScriptTransactionBuilder::prepare_transfer(\n        inputs,\n        outputs,\n        TxPolicies::default().with_witness_limit(32),\n    )\n    .build(&provider)\n    .await?;\n\n    let witness = ABIEncoder::default().encode(&[64u64.into_token()])?; // u64 because this is VM memory\n    let witness2 = ABIEncoder::default().encode(&[4096u64.into_token()])?;\n\n    tx.append_witness(witness.into())?;\n    tx.append_witness(witness2.into())?;\n\n    let tx_status = provider.send_transaction_and_await_commit(tx).await?;\n\n    let fee = tx_status.total_fee();\n    // The predicate has spent the funds\n    assert_address_balance(\n        &predicate.address(),\n        &provider,\n        &asset_id,\n        predicate_balance - amount_to_send - fee,\n    )\n    .await;\n\n    // Funds were transferred\n    assert_address_balance(\n        &receiver.address(),\n        &provider,\n        &asset_id,\n        receiver_balance + amount_to_send,\n    )\n    .await;\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn tx_id_not_changed_after_adding_witnesses() -> Result<()> {\n    abigen!(Predicate(\n        name = \"MyPredicate\",\n        abi = \"e2e/sway/predicates/predicate_witnesses/out/release/predicate_witnesses-abi.json\"\n    ));\n\n    let predicate_data = MyPredicateEncoder::default().encode_data(0, 1)?;\n\n    let mut predicate: Predicate = Predicate::load_from(\n        \"sway/predicates/predicate_witnesses/out/release/predicate_witnesses.bin\",\n    )?\n    .with_data(predicate_data);\n\n    let num_coins = 4;\n    let num_messages = 0;\n    let amount = 16;\n    let (provider, _predicate_balance, receiver, _receiver_balance, asset_id, _) =\n        setup_predicate_test(predicate.address(), num_coins, num_messages, amount).await?;\n\n    predicate.set_provider(provider.clone());\n\n    let amount_to_send = 12u64;\n    let inputs = predicate\n        .get_asset_inputs_for_amount(asset_id, amount_to_send.into(), None)\n        .await?;\n    let outputs =\n        predicate.get_asset_outputs_for_amount(receiver.address(), asset_id, amount_to_send);\n\n    let mut tx = ScriptTransactionBuilder::prepare_transfer(\n        inputs,\n        outputs,\n        TxPolicies::default().with_witness_limit(32),\n    )\n    .build(&provider)\n    .await?;\n\n    let consensus_parameters = provider.consensus_parameters().await?;\n    let chain_id = consensus_parameters.chain_id();\n    let tx_id = tx.id(chain_id);\n\n    let witness = ABIEncoder::default().encode(&[64u64.into_token()])?; // u64 because this is VM memory\n    let witness2 = ABIEncoder::default().encode(&[4096u64.into_token()])?;\n\n    tx.append_witness(witness.into())?;\n    tx.append_witness(witness2.into())?;\n    let tx_id_after_witnesses = tx.id(chain_id);\n\n    let tx_id_from_provider = provider.send_transaction(tx).await?;\n\n    assert_eq!(tx_id, tx_id_after_witnesses);\n    assert_eq!(tx_id, tx_id_from_provider);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn predicate_encoder_config_is_applied() -> Result<()> {\n    abigen!(Predicate(\n        name = \"MyPredicate\",\n        abi = \"e2e/sway/predicates/basic_predicate/out/release/basic_predicate-abi.json\"\n    ));\n    {\n        let _encoding_ok = MyPredicateEncoder::default()\n            .encode_data(4097, 4097)\n            .expect(\"should not fail as it uses the default encoder config\");\n    }\n    {\n        let encoder_config = EncoderConfig {\n            max_tokens: 1,\n            ..Default::default()\n        };\n        let encoding_error = MyPredicateEncoder::new(encoder_config)\n            .encode_data(4097, 4097)\n            .expect_err(\"should fail\");\n\n        assert!(\n            encoding_error\n                .to_string()\n                .contains(\"token limit `1` reached while encoding\")\n        );\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn predicate_transfers_non_base_asset() -> Result<()> {\n    abigen!(Predicate(\n        name = \"MyPredicate\",\n        abi = \"e2e/sway/predicates/basic_predicate/out/release/basic_predicate-abi.json\"\n    ));\n\n    let predicate_data = MyPredicateEncoder::default().encode_data(4097, 4097)?;\n    let mut predicate: Predicate =\n        Predicate::load_from(\"sway/predicates/basic_predicate/out/release/basic_predicate.bin\")?\n            .with_data(predicate_data);\n\n    let num_coins = 4;\n    let num_message = 6;\n    let amount = 20;\n    let (provider, _, receiver, _, _, _) =\n        setup_predicate_test(predicate.address(), num_coins, num_message, amount).await?;\n    predicate.set_provider(provider);\n    let other_asset_id = AssetId::from([1u8; 32]);\n\n    let send_amount = num_coins * amount;\n    predicate\n        .transfer(\n            receiver.address(),\n            send_amount,\n            other_asset_id,\n            TxPolicies::default(),\n        )\n        .await?;\n\n    assert_eq!(predicate.get_asset_balance(&other_asset_id).await?, 0,);\n\n    assert_eq!(\n        receiver.get_asset_balance(&other_asset_id).await?,\n        send_amount as u128,\n    );\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn predicate_with_invalid_data_fails() -> Result<()> {\n    abigen!(Predicate(\n        name = \"MyPredicate\",\n        abi = \"e2e/sway/predicates/basic_predicate/out/release/basic_predicate-abi.json\"\n    ));\n\n    let predicate_data = MyPredicateEncoder::default().encode_data(0, 100)?;\n    let mut predicate: Predicate =\n        Predicate::load_from(\"sway/predicates/basic_predicate/out/release/basic_predicate.bin\")?\n            .with_data(predicate_data);\n\n    let num_coins = 4;\n    let num_message = 6;\n    let amount = 20;\n    let (provider, _, receiver, _, _, _) =\n        setup_predicate_test(predicate.address(), num_coins, num_message, amount).await?;\n    predicate.set_provider(provider);\n    let other_asset_id = AssetId::from([1u8; 32]);\n\n    let send_amount = num_coins * amount;\n    let error_string = predicate\n        .transfer(\n            receiver.address(),\n            send_amount,\n            other_asset_id,\n            TxPolicies::default(),\n        )\n        .await\n        .unwrap_err()\n        .to_string();\n\n    assert!(error_string.contains(\n        \"PredicateVerificationFailed(Panic { index: 0, reason: PredicateReturnedNonOne })\"\n    ));\n    assert_eq!(receiver.get_asset_balance(&other_asset_id).await?, 0);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn predicate_blobs() -> Result<()> {\n    abigen!(Predicate(\n        name = \"MyPredicate\",\n        abi = \"e2e/sway/predicates/predicate_blobs/out/release/predicate_blobs-abi.json\"\n    ));\n\n    // ANCHOR: preparing_the_predicate\n    let configurables = MyPredicateConfigurables::default().with_SECRET_NUMBER(10001)?;\n\n    let predicate_data = MyPredicateEncoder::default().encode_data(1, 19)?;\n\n    let executable =\n        Executable::load_from(\"sway/predicates/predicate_blobs/out/release/predicate_blobs.bin\")?;\n\n    let loader = executable\n        .convert_to_loader()?\n        .with_configurables(configurables);\n\n    let mut predicate: Predicate = Predicate::from_code(loader.code()).with_data(predicate_data);\n    // ANCHOR_END: preparing_the_predicate\n\n    let num_coins = 4;\n    let num_messages = 8;\n    let amount = 16;\n    let (provider, predicate_balance, receiver, receiver_balance, asset_id, extra_wallet) =\n        setup_predicate_test(predicate.address(), num_coins, num_messages, amount).await?;\n\n    // we don't want to pay with the recipient wallet so that we don't affect the assertion we're\n    // gonna make later on\n    // ANCHOR: uploading_the_blob\n    loader.upload_blob(extra_wallet).await?;\n    predicate.set_provider(provider.clone());\n\n    let amount_to_send = 42;\n    let response = predicate\n        .transfer(\n            receiver.address(),\n            amount_to_send,\n            asset_id,\n            TxPolicies::default(),\n        )\n        .await?;\n    // ANCHOR_END: uploading_the_blob\n\n    // The predicate has spent the funds\n    let transaction_fee = response.tx_status.total_fee;\n    assert_address_balance(\n        &predicate.address(),\n        &provider,\n        &asset_id,\n        predicate_balance - amount_to_send - transaction_fee,\n    )\n    .await;\n\n    // Funds were transferred\n    assert_address_balance(\n        &receiver.address(),\n        &provider,\n        &asset_id,\n        receiver_balance + amount_to_send,\n    )\n    .await;\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn predicate_configurables_in_blobs() -> Result<()> {\n    abigen!(Predicate(\n        name = \"MyPredicate\",\n        abi = \"e2e/sway/predicates/predicate_configurables/out/release/predicate_configurables-abi.json\"\n    ));\n\n    let new_tuple = (16, false);\n    let new_array = [123, 124, 125];\n    let new_struct = StructWithGeneric {\n        field_1: 32u8,\n        field_2: 64,\n    };\n    let new_enum = EnumWithGeneric::VariantTwo;\n\n    let configurables = MyPredicateConfigurables::default()\n        .with_U8(8)?\n        .with_TUPLE(new_tuple)?\n        .with_ARRAY(new_array)?\n        .with_STRUCT(new_struct.clone())?\n        .with_ENUM(new_enum.clone())?;\n\n    let predicate_data = MyPredicateEncoder::default()\n        .encode_data(true, 8u8, new_tuple, new_array, new_struct, new_enum)?;\n\n    let executable = Executable::load_from(\n        \"sway/predicates/predicate_configurables/out/release/predicate_configurables.bin\",\n    )?;\n\n    let loader = executable\n        .convert_to_loader()?\n        .with_configurables(configurables);\n\n    let mut predicate: Predicate = Predicate::from_code(loader.code()).with_data(predicate_data);\n\n    let num_coins = 4;\n    let num_messages = 8;\n    let amount = 16;\n    let (provider, predicate_balance, receiver, receiver_balance, asset_id, extra_wallet) =\n        setup_predicate_test(predicate.address(), num_coins, num_messages, amount).await?;\n\n    predicate.set_provider(provider.clone());\n\n    loader\n        .upload_blob(extra_wallet)\n        .await?\n        .expect(\"has tx_status\");\n\n    let amount_to_send = predicate_balance - 1;\n    predicate\n        .transfer(\n            receiver.address(),\n            amount_to_send,\n            asset_id,\n            TxPolicies::default(),\n        )\n        .await?;\n\n    // The predicate has spent the funds\n    assert_address_balance(&predicate.address(), &provider, &asset_id, 0).await;\n\n    // Funds were transferred\n    assert_address_balance(\n        &receiver.address(),\n        &provider,\n        &asset_id,\n        receiver_balance + amount_to_send,\n    )\n    .await;\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn predicate_transfer_respects_maturity_and_expiration() -> Result<()> {\n    abigen!(Predicate(\n        name = \"MyPredicate\",\n        abi = \"e2e/sway/predicates/basic_predicate/out/release/basic_predicate-abi.json\"\n    ));\n\n    let predicate_data = MyPredicateEncoder::default().encode_data(4097, 4097)?;\n\n    let mut predicate: Predicate =\n        Predicate::load_from(\"sway/predicates/basic_predicate/out/release/basic_predicate.bin\")?\n            .with_data(predicate_data);\n\n    let num_coins = 4;\n    let num_messages = 8;\n    let amount = 16;\n    let (provider, predicate_balance, receiver, receiver_balance, asset_id, _) =\n        setup_predicate_test(predicate.address(), num_coins, num_messages, amount).await?;\n\n    predicate.set_provider(provider.clone());\n\n    let maturity = 10;\n    let expiration = 20;\n    let tx_policies = TxPolicies::default()\n        .with_maturity(maturity)\n        .with_expiration(expiration);\n    let amount_to_send = 10;\n\n    {\n        let err = predicate\n            .transfer(receiver.address(), amount_to_send, asset_id, tx_policies)\n            .await\n            .expect_err(\"maturity not reached\");\n\n        assert!(err.to_string().contains(\"TransactionMaturity\"));\n    }\n    let transaction_fee = {\n        provider.produce_blocks(15, None).await?;\n        predicate\n            .transfer(receiver.address(), amount_to_send, asset_id, tx_policies)\n            .await\n            .expect(\"should succeed. Block height between `maturity` and `expiration`\")\n            .tx_status\n            .total_fee\n    };\n    {\n        provider.produce_blocks(15, None).await?;\n        let err = predicate\n            .transfer(receiver.address(), amount_to_send, asset_id, tx_policies)\n            .await\n            .expect_err(\"expiration reached\");\n\n        assert!(err.to_string().contains(\"TransactionExpiration\"));\n    }\n\n    // The predicate has spent the funds\n    assert_address_balance(\n        &predicate.address(),\n        &provider,\n        &asset_id,\n        predicate_balance - amount_to_send - transaction_fee,\n    )\n    .await;\n\n    // Funds were transferred\n    assert_address_balance(\n        &receiver.address(),\n        &provider,\n        &asset_id,\n        receiver_balance + amount_to_send,\n    )\n    .await;\n\n    Ok(())\n}\n\nasync fn transfer_to_predicate(\n    from: &impl Account,\n    address: &Address,\n    amount: u64,\n    asset_id: AssetId,\n) {\n    from.transfer(*address, amount, asset_id, TxPolicies::default())\n        .await\n        .unwrap();\n\n    assert_address_balance(address, from.try_provider().unwrap(), &asset_id, amount).await;\n}\n\n#[tokio::test]\nasync fn predicate_tx_input_output() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet_1\", \"wallet_2\"),\n        Abigen(\n            Contract(\n                name = \"TestContract\",\n                project = \"e2e/sway/contracts/contract_test\"\n            ),\n            Predicate(\n                name = \"MyPredicate\",\n                project = \"e2e/sway/predicates/predicate_tx_input_output\"\n            ),\n        ),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TestContract\",\n            wallet = \"wallet_1\",\n            random_salt = false,\n        ),\n    );\n\n    let provider = wallet_1.try_provider()?;\n\n    // Predicate expects `wallet_2` as owner\n    let configurables = MyPredicateConfigurables::default().with_OWNER(wallet_2.address())?;\n\n    // Predicate will check first input and first output\n    let predicate_data = MyPredicateEncoder::default().encode_data(0, 0)?;\n\n    let mut predicate: Predicate = Predicate::load_from(\n        \"sway/predicates/predicate_tx_input_output/out/release/predicate_tx_input_output.bin\",\n    )?\n    .with_data(predicate_data)\n    .with_configurables(configurables);\n    predicate.set_provider(provider.clone());\n\n    let asset_id = AssetId::zeroed();\n    {\n        transfer_to_predicate(&wallet_2, &predicate.address(), 42, asset_id).await;\n\n        // Call contract method with custom `wallet_2` input at first place, predicate at second\n        // and custom change to `wallet_2`\n        let wallet_input = wallet_2\n            .get_asset_inputs_for_amount(asset_id, 10, None)\n            .await?\n            .pop()\n            .unwrap();\n\n        let predicate_input = predicate\n            .get_asset_inputs_for_amount(asset_id, 10, None)\n            .await?\n            .pop()\n            .unwrap();\n\n        let custom_inputs = vec![wallet_input, predicate_input];\n\n        let custom_output = vec![Output::change(wallet_2.address(), 0, asset_id)];\n\n        let value = contract_instance\n            .methods()\n            .initialize_counter(36)\n            .with_inputs(custom_inputs)\n            .add_signer(wallet_2.signer().clone())\n            .with_outputs(custom_output)\n            .call()\n            .await?\n            .value;\n\n        assert_eq!(value, 36);\n    }\n    {\n        transfer_to_predicate(&wallet_2, &predicate.address(), 42, asset_id).await;\n\n        // Add coin with wrong owner (`wallet_1`)\n        let wallet_input = wallet_1\n            .get_asset_inputs_for_amount(asset_id, 10, None)\n            .await?\n            .pop()\n            .unwrap();\n\n        let predicate_input = predicate\n            .get_asset_inputs_for_amount(asset_id, 10, None)\n            .await?\n            .pop()\n            .unwrap();\n\n        let custom_inputs = vec![wallet_input, predicate_input];\n\n        let err = contract_instance\n            .methods()\n            .initialize_counter(36)\n            .with_inputs(custom_inputs)\n            .call()\n            .await\n            .unwrap_err();\n\n        assert!(err.to_string().contains(\"PredicateVerificationFailed\"));\n    }\n\n    Ok(())\n}\n"
  },
  {
    "path": "e2e/tests/providers.rs",
    "content": "use std::{ops::Add, path::Path};\n\nuse chrono::{DateTime, Duration, TimeZone, Utc};\nuse fuel_asm::RegId;\nuse fuel_tx::SubAssetId;\nuse fuels::{\n    accounts::{\n        Account,\n        signers::{fake::FakeSigner, private_key::PrivateKeySigner},\n    },\n    client::{PageDirection, PaginationRequest},\n    prelude::*,\n    tx::{ContractIdExt, Receipt, Witness},\n    types::{\n        coin_type::CoinType,\n        message::Message,\n        transaction_builders::{BuildableTransaction, ScriptTransactionBuilder},\n        tx_status::{Failure, Success, TxStatus},\n    },\n};\nuse futures::StreamExt;\nuse rand::thread_rng;\n\n#[tokio::test]\nasync fn test_provider_launch_and_connect() -> Result<()> {\n    abigen!(Contract(\n        name = \"MyContract\",\n        abi = \"e2e/sway/contracts/contract_test/out/release/contract_test-abi.json\"\n    ));\n\n    let signer = PrivateKeySigner::random(&mut thread_rng());\n\n    let coins = setup_single_asset_coins(\n        signer.address(),\n        AssetId::zeroed(),\n        DEFAULT_NUM_COINS,\n        DEFAULT_COIN_AMOUNT,\n    );\n    let provider = setup_test_provider(coins, vec![], None, None).await?;\n    let wallet = Wallet::new(signer, provider.clone());\n\n    let contract_id = Contract::load_from(\n        \"sway/contracts/contract_test/out/release/contract_test.bin\",\n        LoadConfiguration::default(),\n    )?\n    .deploy_if_not_exists(&wallet, TxPolicies::default())\n    .await?\n    .contract_id;\n\n    let contract_instance_connected = MyContract::new(contract_id, wallet.clone());\n\n    let response = contract_instance_connected\n        .methods()\n        .initialize_counter(42)\n        .call()\n        .await?;\n    assert_eq!(42, response.value);\n\n    let contract_instance_launched = MyContract::new(contract_id, wallet);\n\n    let response = contract_instance_launched\n        .methods()\n        .increment_counter(10)\n        .call()\n        .await?;\n    assert_eq!(52, response.value);\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_network_error() -> Result<()> {\n    abigen!(Contract(\n        name = \"MyContract\",\n        abi = \"e2e/sway/contracts/contract_test/out/release/contract_test-abi.json\"\n    ));\n\n    let node_config = NodeConfig::default();\n    let chain_config = ChainConfig::default();\n    let state_config = StateConfig::default();\n    let service = FuelService::start(node_config, chain_config, state_config).await?;\n    let provider = Provider::connect(service.bound_address().to_string()).await?;\n\n    let wallet = Wallet::random(&mut thread_rng(), provider.clone());\n\n    // Simulate an unreachable node\n    service.stop().await.unwrap();\n\n    let response = Contract::load_from(\n        \"sway/contracts/contract_test/out/release/contract_test.bin\",\n        LoadConfiguration::default(),\n    )?\n    .deploy_if_not_exists(&wallet, TxPolicies::default())\n    .await;\n\n    assert!(matches!(response, Err(Error::Provider(_))));\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_input_message() -> Result<()> {\n    let compare_messages =\n        |messages_from_provider: Vec<Message>, used_messages: Vec<Message>| -> bool {\n            std::iter::zip(&used_messages, &messages_from_provider).all(|(a, b)| {\n                a.sender == b.sender\n                    && a.recipient == b.recipient\n                    && a.nonce == b.nonce\n                    && a.amount == b.amount\n            })\n        };\n\n    let signer = PrivateKeySigner::random(&mut thread_rng());\n\n    // coin to pay transaction fee\n    let coins =\n        setup_single_asset_coins(signer.address(), AssetId::zeroed(), 1, DEFAULT_COIN_AMOUNT);\n\n    let messages = vec![setup_single_message(\n        Address::default(),\n        signer.address(),\n        DEFAULT_COIN_AMOUNT,\n        0.into(),\n        vec![1, 2],\n    )];\n\n    let provider = setup_test_provider(coins, messages.clone(), None, None).await?;\n    let wallet = Wallet::new(signer, provider.clone());\n\n    setup_program_test!(\n        Abigen(Contract(\n            name = \"TestContract\",\n            project = \"e2e/sway/contracts/contract_test\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TestContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    let spendable_messages = wallet.get_messages().await?;\n\n    assert!(compare_messages(spendable_messages, messages));\n\n    let response = contract_instance\n        .methods()\n        .initialize_counter(42)\n        .call()\n        .await?;\n\n    assert_eq!(42, response.value);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_input_message_pays_fee() -> Result<()> {\n    let signer = PrivateKeySigner::random(&mut thread_rng());\n\n    let messages = setup_single_message(\n        Address::default(),\n        signer.address(),\n        DEFAULT_COIN_AMOUNT,\n        0.into(),\n        vec![],\n    );\n\n    let provider = setup_test_provider(vec![], vec![messages], None, None).await?;\n    let consensus_parameters = provider.consensus_parameters().await?;\n    let base_asset_id = consensus_parameters.base_asset_id();\n    let wallet = Wallet::new(signer, provider.clone());\n\n    abigen!(Contract(\n        name = \"MyContract\",\n        abi = \"e2e/sway/contracts/contract_test/out/release/contract_test-abi.json\"\n    ));\n\n    let deploy_response = Contract::load_from(\n        \"sway/contracts/contract_test/out/release/contract_test.bin\",\n        LoadConfiguration::default(),\n    )?\n    .deploy_if_not_exists(&wallet, TxPolicies::default())\n    .await?;\n\n    let contract_instance = MyContract::new(deploy_response.contract_id, wallet.clone());\n\n    let call_response = contract_instance\n        .methods()\n        .initialize_counter(42)\n        .call()\n        .await?;\n\n    assert_eq!(42, call_response.value);\n\n    let balance = wallet.get_asset_balance(base_asset_id).await?;\n    let deploy_fee = deploy_response.tx_status.unwrap().total_fee;\n    let call_fee = call_response.tx_status.total_fee;\n    assert_eq!(\n        balance,\n        (DEFAULT_COIN_AMOUNT - deploy_fee - call_fee) as u128\n    );\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn can_increase_block_height() -> Result<()> {\n    // ANCHOR: use_produce_blocks_to_increase_block_height\n    let wallets =\n        launch_custom_provider_and_get_wallets(WalletsConfig::default(), None, None).await?;\n    let wallet = &wallets[0];\n    let provider = wallet.provider();\n\n    assert_eq!(provider.latest_block_height().await?, 0u32);\n\n    provider.produce_blocks(3, None).await?;\n\n    assert_eq!(provider.latest_block_height().await?, 3u32);\n    // ANCHOR_END: use_produce_blocks_to_increase_block_height\n    Ok(())\n}\n\n// debug builds are slower (20x for `fuel-core-lib`, 4x for a release-fuel-core-binary), makes for\n// flaky tests\n#[cfg(not(feature = \"fuel-core-lib\"))]\n#[tokio::test]\nasync fn can_set_custom_block_time() -> Result<()> {\n    // ANCHOR: use_produce_blocks_custom_time\n    let block_time = 20u32; // seconds\n    let config = NodeConfig {\n        // This is how you specify the time between blocks\n        block_production: Trigger::Interval {\n            block_time: std::time::Duration::from_secs(block_time.into()),\n        },\n        ..NodeConfig::default()\n    };\n    let wallets =\n        launch_custom_provider_and_get_wallets(WalletsConfig::default(), Some(config), None)\n            .await?;\n    let wallet = &wallets[0];\n    let provider = wallet.provider();\n\n    assert_eq!(provider.latest_block_height().await?, 0u32);\n    let origin_block_time = provider.latest_block_time().await?.unwrap();\n    let blocks_to_produce = 3;\n\n    provider.produce_blocks(blocks_to_produce, None).await?;\n    assert_eq!(provider.latest_block_height().await?, blocks_to_produce);\n    let expected_latest_block_time = origin_block_time\n        .checked_add_signed(Duration::try_seconds((blocks_to_produce * block_time) as i64).unwrap())\n        .unwrap();\n    assert_eq!(\n        provider.latest_block_time().await?.unwrap(),\n        expected_latest_block_time\n    );\n    // ANCHOR_END: use_produce_blocks_custom_time\n\n    let req = PaginationRequest {\n        cursor: None,\n        results: 10,\n        direction: PageDirection::Forward,\n    };\n    let blocks: Vec<fuels::types::block::Block> = provider.get_blocks(req).await?.results;\n\n    assert_eq!(blocks[1].header.time.unwrap().timestamp(), 20);\n    assert_eq!(blocks[2].header.time.unwrap().timestamp(), 40);\n    assert_eq!(blocks[3].header.time.unwrap().timestamp(), 60);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn can_retrieve_latest_block_time() -> Result<()> {\n    let provider = setup_test_provider(vec![], vec![], None, None).await?;\n    let since_epoch = 1676039910;\n\n    let latest_timestamp = Utc.timestamp_opt(since_epoch, 0).unwrap();\n    provider.produce_blocks(1, Some(latest_timestamp)).await?;\n\n    assert_eq!(\n        provider.latest_block_time().await?.unwrap(),\n        latest_timestamp\n    );\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn contract_deployment_respects_maturity_and_expiration() -> Result<()> {\n    abigen!(Contract(\n        name = \"MyContract\",\n        abi = \"e2e/sway/contracts/transaction_block_height/out/release/transaction_block_height-abi.json\"\n    ));\n\n    let wallet = launch_provider_and_get_wallet().await?;\n    let provider = wallet.provider().clone();\n\n    let maturity = 10;\n    let expiration = 20;\n\n    let deploy_w_maturity_and_expiration = || {\n        Contract::load_from(\n            \"sway/contracts/transaction_block_height/out/release/transaction_block_height.bin\",\n            LoadConfiguration::default(),\n        )\n        .map(|loaded_contract| {\n            loaded_contract.deploy(\n                &wallet,\n                TxPolicies::default()\n                    .with_maturity(maturity)\n                    .with_expiration(expiration),\n            )\n        })\n    };\n\n    {\n        let err = deploy_w_maturity_and_expiration()?\n            .await\n            .expect_err(\"maturity not reached\");\n\n        assert!(err.to_string().contains(\"TransactionMaturity\"));\n    }\n    {\n        provider.produce_blocks(15, None).await?;\n        deploy_w_maturity_and_expiration()?\n            .await\n            .expect(\"should succeed. Block height between `maturity` and `expiration`\");\n    }\n    {\n        provider.produce_blocks(15, None).await?;\n        let err = deploy_w_maturity_and_expiration()?\n            .await\n            .expect_err(\"expiration reached\");\n\n        assert!(err.to_string().contains(\"TransactionExpiration\"));\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_gas_forwarded_defaults_to_tx_limit() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TestContract\",\n            project = \"e2e/sway/contracts/contract_test\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TestContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    // The gas used by the script to call a contract and forward remaining gas limit.\n    let gas_used_by_script = 205;\n    let gas_limit = 225_883;\n    let response = contract_instance\n        .methods()\n        .initialize_counter(42)\n        .with_tx_policies(TxPolicies::default().with_script_gas_limit(gas_limit))\n        .call()\n        .await?;\n\n    let gas_forwarded = response\n        .tx_status\n        .receipts\n        .iter()\n        .find(|r| matches!(r, Receipt::Call { .. }))\n        .unwrap()\n        .gas()\n        .unwrap();\n\n    assert_eq!(gas_limit, gas_forwarded + gas_used_by_script);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_amount_and_asset_forwarding() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TokenContract\",\n            project = \"e2e/sway/contracts/token_ops\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TokenContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n    let contract_id = contract_instance.contract_id();\n    let contract_methods = contract_instance.methods();\n    let asset_id = contract_id.asset_id(&SubAssetId::zeroed());\n\n    let mut balance_response = contract_methods\n        .get_balance(contract_id, asset_id)\n        .call()\n        .await?;\n    assert_eq!(balance_response.value, 0);\n\n    contract_methods.mint_coins(5_000_000).call().await?;\n\n    balance_response = contract_methods\n        .get_balance(contract_id, asset_id)\n        .call()\n        .await?;\n    assert_eq!(balance_response.value, 5_000_000);\n\n    let tx_policies = TxPolicies::default().with_script_gas_limit(1_000_000);\n    // Forward 1_000_000 coin amount of base asset_id\n    // this is a big number for checking that amount can be a u64\n    let call_params = CallParameters::default().with_amount(1_000_000);\n\n    let response = contract_methods\n        .get_msg_amount()\n        .with_tx_policies(tx_policies)\n        .call_params(call_params)?\n        .call()\n        .await?;\n\n    assert_eq!(response.value, 1_000_000);\n\n    let call_response = response\n        .tx_status\n        .receipts\n        .iter()\n        .find(|&r| matches!(r, Receipt::Call { .. }));\n\n    assert!(call_response.is_some());\n\n    assert_eq!(call_response.unwrap().amount().unwrap(), 1_000_000);\n    assert_eq!(\n        call_response.unwrap().asset_id().unwrap(),\n        &AssetId::zeroed()\n    );\n\n    let address = wallet.address();\n\n    // withdraw some tokens to wallet\n    contract_methods\n        .transfer(1_000_000, asset_id, address.into())\n        .with_variable_output_policy(VariableOutputPolicy::Exactly(1))\n        .call()\n        .await?;\n\n    let asset_id = AssetId::from(*contract_id);\n    let call_params = CallParameters::default()\n        .with_amount(0)\n        .with_asset_id(asset_id);\n    let tx_policies = TxPolicies::default().with_script_gas_limit(1_000_000);\n\n    let response = contract_methods\n        .get_msg_amount()\n        .with_tx_policies(tx_policies)\n        .call_params(call_params)?\n        .call()\n        .await?;\n\n    assert_eq!(response.value, 0);\n\n    let call_response = response\n        .tx_status\n        .receipts\n        .iter()\n        .find(|&r| matches!(r, Receipt::Call { .. }));\n\n    assert!(call_response.is_some());\n\n    assert_eq!(call_response.unwrap().amount().unwrap(), 0);\n    assert_eq!(\n        call_response.unwrap().asset_id().unwrap(),\n        &AssetId::from(*contract_id)\n    );\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_gas_errors() -> Result<()> {\n    let signer = PrivateKeySigner::random(&mut thread_rng());\n    let number_of_coins = 1;\n    let amount_per_coin = 1_000_000;\n    let coins = setup_single_asset_coins(\n        signer.address(),\n        AssetId::zeroed(),\n        number_of_coins,\n        amount_per_coin,\n    );\n\n    let provider = setup_test_provider(coins.clone(), vec![], None, None).await?;\n    let wallet = Wallet::new(signer, provider.clone());\n\n    setup_program_test!(\n        Abigen(Contract(\n            name = \"TestContract\",\n            project = \"e2e/sway/contracts/contract_test\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TestContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    // Test running out of gas. Gas price as `None` will be 0.\n    let gas_limit = 42;\n    let contract_instance_call = contract_instance\n        .methods()\n        .initialize_counter(42) // Build the ABI call\n        .with_tx_policies(TxPolicies::default().with_script_gas_limit(gas_limit));\n\n    //  Test that the call will use more gas than the gas limit\n    let total_gas = contract_instance_call\n        .estimate_transaction_cost(None, None)\n        .await?\n        .total_gas;\n    assert!(total_gas > gas_limit);\n\n    let response = contract_instance_call\n        .call()\n        .await\n        .expect_err(\"should error\");\n\n    let expected = \"transaction reverted: OutOfGas\";\n    assert!(response.to_string().starts_with(expected));\n\n    // Test for insufficient base asset amount to pay for the transaction fee\n    let response = contract_instance\n        .methods()\n        .initialize_counter(42) // Build the ABI call\n        .with_tx_policies(TxPolicies::default().with_tip(100_000_000_000))\n        .call()\n        .await\n        .expect_err(\"should error\");\n\n    let expected = \"Response errors; Validity(InsufficientFeeAmount\";\n    assert!(response.to_string().contains(expected));\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_call_param_gas_errors() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TestContract\",\n            project = \"e2e/sway/contracts/contract_test\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TestContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    // Transaction gas_limit is sufficient, call gas_forwarded is too small\n    let contract_methods = contract_instance.methods();\n    let response = contract_methods\n        .initialize_counter(42)\n        .with_tx_policies(TxPolicies::default().with_script_gas_limit(446000))\n        .call_params(CallParameters::default().with_gas_forwarded(1))?\n        .call()\n        .await\n        .expect_err(\"should error\");\n\n    let expected = \"transaction reverted: OutOfGas\";\n    assert!(response.to_string().starts_with(expected));\n\n    // Call params gas_forwarded exceeds transaction limit\n    let response = contract_methods\n        .initialize_counter(42)\n        .with_tx_policies(TxPolicies::default().with_script_gas_limit(1))\n        .call_params(CallParameters::default().with_gas_forwarded(1_000))?\n        .call()\n        .await\n        .expect_err(\"should error\");\n\n    assert!(response.to_string().contains(expected));\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_get_gas_used() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TestContract\",\n            project = \"e2e/sway/contracts/contract_test\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TestContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    let total_gas = contract_instance\n        .methods()\n        .initialize_counter(42)\n        .call()\n        .await?\n        .tx_status\n        .total_gas;\n\n    assert!(total_gas > 0);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_parse_block_time() -> Result<()> {\n    let signer = PrivateKeySigner::random(&mut thread_rng());\n    let asset_id = AssetId::zeroed();\n    let coins = setup_single_asset_coins(signer.address(), asset_id, 1, DEFAULT_COIN_AMOUNT);\n    let provider = setup_test_provider(coins.clone(), vec![], None, None).await?;\n    let wallet = Wallet::new(signer, provider.clone());\n    let tx_policies = TxPolicies::default().with_script_gas_limit(2000);\n\n    let wallet_2 = wallet.lock();\n    let tx_response = wallet\n        .transfer(wallet_2.address(), 100, asset_id, tx_policies)\n        .await?;\n\n    let tx_response = wallet\n        .try_provider()?\n        .get_transaction_by_id(&tx_response.tx_id)\n        .await?\n        .unwrap();\n    assert!(tx_response.time.is_some());\n\n    let block = wallet\n        .try_provider()?\n        .block_by_height(tx_response.block_height.unwrap())\n        .await?\n        .unwrap();\n    assert!(block.header.time.is_some());\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_get_spendable_with_exclusion() -> Result<()> {\n    let coin_amount_1 = 1000;\n    let coin_amount_2 = 500;\n\n    let signer = PrivateKeySigner::random(&mut thread_rng());\n    let address = signer.address();\n\n    let coins = [coin_amount_1, coin_amount_2]\n        .into_iter()\n        .flat_map(|amount| setup_single_asset_coins(address, AssetId::zeroed(), 1, amount))\n        .collect::<Vec<_>>();\n\n    let message_amount = 200;\n    let message = given_a_message(address, message_amount);\n\n    let coin_1_utxo_id = coins[0].utxo_id;\n    let coin_2_utxo_id = coins[1].utxo_id;\n\n    let message_nonce = message.nonce;\n\n    let provider = setup_test_provider(coins, vec![message], None, None).await?;\n\n    let wallet = Wallet::new(signer, provider.clone());\n\n    let requested_amount = coin_amount_1 + coin_amount_2 + message_amount;\n    let consensus_parameters = provider.consensus_parameters().await?;\n    {\n        let resources = wallet\n            .get_spendable_resources(\n                *consensus_parameters.base_asset_id(),\n                requested_amount.into(),\n                None,\n            )\n            .await\n            .unwrap();\n        assert_eq!(resources.len(), 3);\n    }\n\n    {\n        let filter = ResourceFilter {\n            from: wallet.address(),\n            amount: coin_amount_1.into(),\n            excluded_utxos: vec![coin_2_utxo_id],\n            excluded_message_nonces: vec![message_nonce],\n            ..Default::default()\n        };\n        let resources = provider.get_spendable_resources(filter).await.unwrap();\n\n        match resources.as_slice() {\n            [CoinType::Coin(coin)] => {\n                assert_eq!(coin.utxo_id, coin_1_utxo_id);\n            }\n            _ => {\n                panic!(\"This shouldn't happen!\")\n            }\n        }\n    }\n\n    Ok(())\n}\n\nfn given_a_message(address: Address, message_amount: u64) -> Message {\n    setup_single_message(\n        Address::default(),\n        address,\n        message_amount,\n        0.into(),\n        vec![],\n    )\n}\n\nfn convert_to_datetime(timestamp: u64) -> DateTime<Utc> {\n    let unix = tai64::Tai64(timestamp).to_unix();\n    DateTime::from_timestamp(unix, 0).unwrap()\n}\n\n/// This test is here in addition to `can_set_custom_block_time` because even though this test\n/// passed, the Sway `timestamp` function didn't take into account the block time change. This\n/// was fixed and this test is here to demonstrate the fix.\n#[tokio::test]\nasync fn test_sway_timestamp() -> Result<()> {\n    let block_time = 1u32; // seconds\n    let provider_config = NodeConfig {\n        block_production: Trigger::Interval {\n            block_time: std::time::Duration::from_secs(block_time.into()),\n        },\n        ..NodeConfig::default()\n    };\n    let mut wallets = launch_custom_provider_and_get_wallets(\n        WalletsConfig::new(Some(1), Some(1), Some(100)),\n        Some(provider_config),\n        None,\n    )\n    .await?;\n    let wallet = wallets.pop().unwrap();\n    let provider = wallet.provider();\n\n    setup_program_test!(\n        Abigen(Contract(\n            name = \"TestContract\",\n            project = \"e2e/sway/contracts/block_timestamp\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TestContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    let origin_timestamp = provider.latest_block_time().await?.unwrap();\n    let methods = contract_instance.methods();\n\n    let response = methods.return_timestamp().call().await?;\n    let mut expected_datetime =\n        origin_timestamp.add(Duration::try_seconds(block_time as i64).unwrap());\n    assert_eq!(convert_to_datetime(response.value), expected_datetime);\n\n    let blocks_to_produce = 600;\n    provider.produce_blocks(blocks_to_produce, None).await?;\n\n    let response = methods.return_timestamp().call().await?;\n\n    // `produce_blocks` call\n    expected_datetime = expected_datetime\n        .add(Duration::try_seconds((block_time * blocks_to_produce) as i64).unwrap());\n    // method call\n    expected_datetime = expected_datetime.add(Duration::try_seconds(block_time as i64).unwrap());\n\n    assert_eq!(convert_to_datetime(response.value), expected_datetime);\n    assert_eq!(\n        provider.latest_block_time().await?.unwrap(),\n        expected_datetime\n    );\n    Ok(())\n}\n\n#[cfg(feature = \"coin-cache\")]\nasync fn create_transfer(wallet: &Wallet, amount: u64, to: Address) -> Result<ScriptTransaction> {\n    let asset_id = AssetId::zeroed();\n    let inputs = wallet\n        .get_asset_inputs_for_amount(asset_id, amount.into(), None)\n        .await?;\n    let outputs = wallet.get_asset_outputs_for_amount(to, asset_id, amount);\n\n    let mut tb = ScriptTransactionBuilder::prepare_transfer(inputs, outputs, TxPolicies::default());\n\n    wallet.adjust_for_fee(&mut tb, amount.into()).await?;\n    wallet.add_witnesses(&mut tb)?;\n\n    tb.build(wallet.provider()).await\n}\n\n#[cfg(feature = \"coin-cache\")]\n#[tokio::test]\nasync fn transactions_with_the_same_utxo() -> Result<()> {\n    use fuels::types::errors::transaction;\n\n    let wallet_1 = launch_provider_and_get_wallet().await?;\n    let provider = wallet_1.provider();\n    let wallet_2 = Wallet::random(&mut thread_rng(), provider.clone());\n\n    let tx_1 = create_transfer(&wallet_1, 100, wallet_2.address()).await?;\n    let tx_2 = create_transfer(&wallet_1, 101, wallet_2.address()).await?;\n\n    let _tx_id = provider.send_transaction(tx_1).await?;\n    let res = provider.send_transaction(tx_2).await;\n\n    let err = res.expect_err(\"is error\");\n\n    assert!(matches!(\n        err,\n        Error::Transaction(transaction::Reason::Validation(..))\n    ));\n    assert!(\n        err.to_string()\n            .contains(\"was submitted recently in a transaction \")\n    );\n\n    Ok(())\n}\n\n#[cfg(feature = \"coin-cache\")]\n#[tokio::test]\nasync fn coin_caching() -> Result<()> {\n    let amount = 1000;\n    let num_coins = 50;\n    let mut wallets = launch_custom_provider_and_get_wallets(\n        WalletsConfig::new(Some(1), Some(num_coins), Some(amount)),\n        Some(NodeConfig::default()),\n        None,\n    )\n    .await?;\n    let wallet_1 = wallets.pop().unwrap();\n    let provider = wallet_1.provider();\n    let wallet_2 = Wallet::random(&mut thread_rng(), provider.clone());\n\n    // Consecutively send transfer txs. Without caching, the txs will\n    // end up trying to use the same input coins because 'get_spendable_coins()'\n    // won't filter out recently used coins.\n    let num_iterations = 10;\n    let amount_to_send = 100;\n    let mut tx_ids = vec![];\n    for _ in 0..num_iterations {\n        let tx = create_transfer(&wallet_1, amount_to_send, wallet_2.address()).await?;\n        let tx_id = provider.send_transaction(tx).await?;\n        tx_ids.push(tx_id);\n    }\n\n    provider.produce_blocks(10, None).await?;\n\n    // Confirm all txs are settled\n    for tx_id in tx_ids {\n        let status = provider.tx_status(&tx_id).await?;\n        assert!(matches!(status, TxStatus::Success { .. }));\n    }\n\n    // Verify the transfers were successful\n    assert_eq!(\n        wallet_2.get_asset_balance(&AssetId::zeroed()).await?,\n        (num_iterations * amount_to_send) as u128\n    );\n\n    Ok(())\n}\n\n#[cfg(feature = \"coin-cache\")]\nasync fn create_revert_tx(wallet: &Wallet) -> Result<ScriptTransaction> {\n    let script = std::fs::read(\"sway/scripts/reverting/out/release/reverting.bin\")?;\n\n    let amount = 1u64;\n    let asset_id = AssetId::zeroed();\n    let inputs = wallet\n        .get_asset_inputs_for_amount(asset_id, amount.into(), None)\n        .await?;\n    let outputs = wallet.get_asset_outputs_for_amount(Address::default(), asset_id, amount);\n\n    let mut tb = ScriptTransactionBuilder::prepare_transfer(inputs, outputs, TxPolicies::default())\n        .with_script(script);\n    wallet.adjust_for_fee(&mut tb, amount.into()).await?;\n    wallet.add_witnesses(&mut tb)?;\n\n    tb.build(wallet.provider()).await\n}\n\n#[cfg(feature = \"coin-cache\")]\n#[tokio::test]\nasync fn test_cache_invalidation_on_await() -> Result<()> {\n    let block_time = 1u32;\n    let provider_config = NodeConfig {\n        block_production: Trigger::Interval {\n            block_time: std::time::Duration::from_secs(block_time.into()),\n        },\n        ..NodeConfig::default()\n    };\n\n    // create wallet with 1 coin so that the cache prevents further\n    // spending unless the coin is invalidated from the cache\n    let mut wallets = launch_custom_provider_and_get_wallets(\n        WalletsConfig::new(Some(1), Some(1), Some(100)),\n        Some(provider_config),\n        None,\n    )\n    .await?;\n    let wallet = wallets.pop().unwrap();\n\n    let provider = wallet.provider();\n    let tx = create_revert_tx(&wallet).await?;\n\n    // Pause time so that the cache doesn't invalidate items based on TTL\n    tokio::time::pause();\n\n    // tx inputs should be cached and then invalidated due to the tx failing\n    let tx_status = provider.send_transaction_and_await_commit(tx).await?;\n\n    assert!(matches!(tx_status, TxStatus::Failure { .. }));\n\n    let consensus_parameters = provider.consensus_parameters().await?;\n    let coins = wallet\n        .get_spendable_resources(*consensus_parameters.base_asset_id(), 1, None)\n        .await?;\n    assert_eq!(coins.len(), 1);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn can_fetch_mint_transactions() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TestContract\",\n            project = \"e2e/sway/contracts/contract_test\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TestContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    let provider = wallet.provider();\n\n    let transactions = provider\n        .get_transactions(PaginationRequest {\n            cursor: None,\n            results: 20,\n            direction: PageDirection::Forward,\n        })\n        .await?\n        .results;\n\n    // TODO: remove once (fuels-rs#1093)[https://github.com/FuelLabs/fuels-rs/issues/1093] is in\n    // until then the type is explicitly mentioned to check that we're reexporting it through fuels\n    let _: ::fuels::types::transaction::MintTransaction = transactions\n        .into_iter()\n        .find_map(|tx| match tx.transaction {\n            TransactionType::Mint(tx) => Some(tx),\n            _ => None,\n        })\n        .expect(\"Should have had at least one mint transaction\");\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_build_with_provider() -> Result<()> {\n    let wallet = launch_provider_and_get_wallet().await?;\n    let provider = wallet.provider();\n\n    let receiver = Wallet::random(&mut thread_rng(), provider.clone());\n\n    let consensus_parameters = provider.consensus_parameters().await?;\n    let inputs = wallet\n        .get_asset_inputs_for_amount(*consensus_parameters.base_asset_id(), 100, None)\n        .await?;\n    let outputs = wallet.get_asset_outputs_for_amount(\n        receiver.address(),\n        *consensus_parameters.base_asset_id(),\n        100,\n    );\n\n    let mut tb = ScriptTransactionBuilder::prepare_transfer(inputs, outputs, TxPolicies::default());\n    wallet.add_witnesses(&mut tb)?;\n\n    let tx = tb.build(provider).await?;\n\n    provider.send_transaction_and_await_commit(tx).await?;\n\n    let receiver_balance = receiver\n        .get_asset_balance(consensus_parameters.base_asset_id())\n        .await?;\n\n    assert_eq!(receiver_balance, 100);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn send_transaction_and_await_status() -> Result<()> {\n    let wallet = launch_provider_and_get_wallet().await?;\n    let provider = wallet.provider();\n\n    let consensus_parameters = provider.consensus_parameters().await?;\n    let inputs = wallet\n        .get_asset_inputs_for_amount(*consensus_parameters.base_asset_id(), 100, None)\n        .await?;\n    let outputs = wallet.get_asset_outputs_for_amount(\n        Address::default(),\n        *consensus_parameters.base_asset_id(),\n        100,\n    );\n\n    // Given\n    let mut tb = ScriptTransactionBuilder::prepare_transfer(inputs, outputs, TxPolicies::default());\n    wallet.add_witnesses(&mut tb)?;\n\n    let tx = tb.build(provider).await?;\n\n    // When\n    let status = provider.send_transaction_and_await_status(tx, true).await?;\n\n    // Then\n    assert_eq!(status.len(), 3);\n    assert!(status.iter().enumerate().all(|(i, tx_status)| {\n        matches!(\n            (i, tx_status.clone().unwrap()),\n            (0, TxStatus::Submitted)\n                | (1, TxStatus::PreconfirmationSuccess { .. })\n                | (2, TxStatus::Success { .. })\n        )\n    }));\n    Ok(())\n}\n\n#[tokio::test]\nasync fn send_transaction_and_subscribe_status() -> Result<()> {\n    let config = NodeConfig {\n        block_production: Trigger::Never,\n        ..NodeConfig::default()\n    };\n    let wallet =\n        launch_custom_provider_and_get_wallets(WalletsConfig::default(), Some(config), None)\n            .await?[0]\n            .clone();\n    let provider = wallet.provider();\n\n    let consensus_parameters = provider.consensus_parameters().await?;\n    let inputs = wallet\n        .get_asset_inputs_for_amount(*consensus_parameters.base_asset_id(), 100, None)\n        .await?;\n    let outputs = wallet.get_asset_outputs_for_amount(\n        Address::default(),\n        *consensus_parameters.base_asset_id(),\n        100,\n    );\n\n    // Given\n    let mut tb = ScriptTransactionBuilder::prepare_transfer(inputs, outputs, TxPolicies::default());\n    wallet.add_witnesses(&mut tb)?;\n\n    let tx = tb.build(provider).await?;\n    let tx_id = tx.id(consensus_parameters.chain_id());\n\n    // When\n    let mut statuses = provider.subscribe_transaction_status(&tx_id, true).await?;\n    let _ = provider.send_transaction(tx).await?;\n\n    // Then\n    assert!(matches!(\n        statuses.next().await.unwrap()?,\n        TxStatus::Submitted\n    ));\n    provider.produce_blocks(1, None).await?;\n    assert!(matches!(\n        statuses.next().await.unwrap()?,\n        TxStatus::PreconfirmationSuccess { .. }\n    ));\n    assert!(matches!(\n        statuses.next().await.unwrap()?,\n        TxStatus::Success { .. }\n    ));\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn can_produce_blocks_with_trig_never() -> Result<()> {\n    let config = NodeConfig {\n        block_production: Trigger::Never,\n        ..NodeConfig::default()\n    };\n    let wallets =\n        launch_custom_provider_and_get_wallets(WalletsConfig::default(), Some(config), None)\n            .await?;\n    let wallet = &wallets[0];\n    let provider = wallet.provider();\n\n    let consensus_parameters = provider.consensus_parameters().await?;\n    let inputs = wallet\n        .get_asset_inputs_for_amount(*consensus_parameters.base_asset_id(), 100, None)\n        .await?;\n    let outputs = wallet.get_asset_outputs_for_amount(\n        Address::default(),\n        *consensus_parameters.base_asset_id(),\n        100,\n    );\n\n    let mut tb = ScriptTransactionBuilder::prepare_transfer(inputs, outputs, TxPolicies::default());\n    wallet.add_witnesses(&mut tb)?;\n    let tx = tb.build(provider).await?;\n    let tx_id = tx.id(consensus_parameters.chain_id());\n\n    provider.send_transaction(tx).await?;\n    provider.produce_blocks(1, None).await?;\n\n    tokio::time::sleep(std::time::Duration::from_millis(500)).await;\n    let status = provider.tx_status(&tx_id).await?;\n    assert!(matches!(status, TxStatus::Success { .. }));\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn can_upload_executor_and_trigger_upgrade() -> Result<()> {\n    let signer = PrivateKeySigner::random(&mut thread_rng());\n\n    // Need more coins to avoid \"not enough coins to fit the target\"\n    let num_coins = 100;\n    let coins = setup_single_asset_coins(\n        signer.address(),\n        AssetId::zeroed(),\n        num_coins,\n        DEFAULT_COIN_AMOUNT,\n    );\n\n    let mut chain_config = ChainConfig::local_testnet();\n    chain_config\n        .consensus_parameters\n        .set_privileged_address(signer.address());\n\n    let provider = setup_test_provider(coins, vec![], None, Some(chain_config)).await?;\n    let wallet = Wallet::new(signer, provider.clone());\n\n    // This is downloaded over in `build.rs`\n    let executor = std::fs::read(Path::new(env!(\"OUT_DIR\")).join(\"fuel-core-wasm-executor.wasm\"))?;\n\n    let subsection_size = 65536;\n    let subsections = UploadSubsection::split_bytecode(&executor, subsection_size).unwrap();\n\n    let root = subsections[0].root;\n    for subsection in subsections {\n        let mut builder =\n            UploadTransactionBuilder::prepare_subsection_upload(subsection, TxPolicies::default());\n        wallet.add_witnesses(&mut builder)?;\n        wallet.adjust_for_fee(&mut builder, 0).await?;\n        let tx = builder.build(&provider).await?;\n\n        provider.send_transaction_and_await_commit(tx).await?;\n    }\n\n    let mut builder =\n        UpgradeTransactionBuilder::prepare_state_transition_upgrade(root, TxPolicies::default());\n    wallet.add_witnesses(&mut builder)?;\n    wallet.adjust_for_fee(&mut builder, 0).await?;\n    let tx = builder.build(provider.clone()).await?;\n\n    provider.send_transaction(tx).await?;\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn tx_respects_policies() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TestContract\",\n            project = \"e2e/sway/contracts/contract_test\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TestContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    let tip = 22;\n    let witness_limit = 1000;\n    let maturity = 4;\n    let expiration = 128;\n    let max_fee = 10_000;\n    let script_gas_limit = 3000;\n    let owner_index = 1;\n    let tx_policies = TxPolicies::new(\n        Some(tip),\n        Some(witness_limit),\n        Some(maturity),\n        Some(expiration),\n        Some(max_fee),\n        Some(script_gas_limit),\n        Some(owner_index),\n    );\n\n    // advance the block height to ensure the maturity is respected\n    let provider = wallet.provider();\n    provider.produce_blocks(4, None).await?;\n\n    // trigger a transaction that contains script code to verify\n    // that policies precede estimated values\n    let response = contract_instance\n        .methods()\n        .initialize_counter(42)\n        .with_tx_policies(tx_policies)\n        .call()\n        .await?;\n\n    let tx_response = provider\n        .get_transaction_by_id(&response.tx_id.unwrap())\n        .await?\n        .expect(\"tx should exist\");\n    let script = match tx_response.transaction {\n        TransactionType::Script(tx) => tx,\n        _ => panic!(\"expected script transaction\"),\n    };\n\n    assert_eq!(script.maturity().unwrap(), maturity);\n    assert_eq!(script.expiration().unwrap(), expiration);\n    assert_eq!(script.tip().unwrap(), tip);\n    assert_eq!(script.witness_limit().unwrap(), witness_limit);\n    assert_eq!(script.max_fee().unwrap(), max_fee);\n    assert_eq!(script.gas_limit(), script_gas_limit);\n    assert_eq!(script.owner().unwrap(), owner_index);\n\n    Ok(())\n}\n\n#[tokio::test]\n#[ignore] // TODO: https://github.com/FuelLabs/fuels-rs/issues/1581\nasync fn can_setup_static_gas_price() -> Result<()> {\n    let expected_gas_price = 474;\n    let node_config = NodeConfig {\n        starting_gas_price: expected_gas_price,\n        ..Default::default()\n    };\n    let provider = setup_test_provider(vec![], vec![], Some(node_config), None).await?;\n\n    let gas_price = provider.estimate_gas_price(0).await?.gas_price;\n\n    let da_cost = 1000;\n    assert_eq!(gas_price, da_cost + expected_gas_price);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn tx_with_witness_data() -> Result<()> {\n    use fuel_asm::{GTFArgs, op};\n\n    let wallet = launch_provider_and_get_wallet().await?;\n    let provider = wallet.provider();\n\n    let receiver = Wallet::random(&mut thread_rng(), provider.clone());\n\n    let consensus_parameters = provider.consensus_parameters().await?;\n    let inputs = wallet\n        .get_asset_inputs_for_amount(*consensus_parameters.base_asset_id(), 10000, None)\n        .await?;\n    let outputs = wallet.get_asset_outputs_for_amount(\n        receiver.address(),\n        *consensus_parameters.base_asset_id(),\n        1,\n    );\n\n    let mut tb = ScriptTransactionBuilder::prepare_transfer(inputs, outputs, TxPolicies::default());\n    wallet.add_witnesses(&mut tb)?;\n\n    // we test that the witness data wasn't tempered with during the build (gas estimation) process\n    // if the witness data is tempered with, the estimation will be off and the transaction\n    // will error out with `OutOfGas`\n    let script: Vec<u8> = vec![\n        // load witness data into register 0x10\n        op::gtf(0x10, 0x00, GTFArgs::WitnessData.into()),\n        op::lw(0x10, 0x10, 0x00),\n        // load expected value into register 0x11\n        op::movi(0x11, 0x0f),\n        // load the offset of the revert instruction into register 0x12\n        op::movi(0x12, 0x08),\n        // compare the two values and jump to the revert instruction if they are not equal\n        op::jne(0x10, 0x11, 0x12),\n        // do some expensive operation so gas estimation is higher if comparison passes\n        op::gtf(0x13, 0x01, GTFArgs::WitnessData.into()),\n        op::gtf(0x14, 0x01, GTFArgs::WitnessDataLength.into()),\n        op::aloc(0x14),\n        op::eck1(RegId::HP, 0x13, 0x13),\n        // return the witness data\n        op::ret(0x10),\n        op::rvrt(RegId::ZERO),\n    ]\n    .into_iter()\n    .collect();\n    tb.script = script;\n\n    let expected_data = 15u64;\n    let witness = Witness::from(expected_data.to_be_bytes().to_vec());\n    tb.witnesses_mut().push(witness);\n\n    let tx = tb\n        .with_tx_policies(TxPolicies::default().with_witness_limit(1000))\n        .build(provider)\n        .await?;\n\n    let status = provider.send_transaction_and_await_commit(tx).await?;\n\n    match status {\n        TxStatus::Success(Success { receipts, .. }) => {\n            let ret: u64 = receipts\n                .as_ref()\n                .iter()\n                .find_map(|receipt| match receipt {\n                    Receipt::Return { val, .. } => Some(*val),\n                    _ => None,\n                })\n                .expect(\"should have return value\");\n\n            assert_eq!(ret, expected_data);\n        }\n        _ => panic!(\"expected success status\"),\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn contract_call_with_impersonation() -> Result<()> {\n    let provider_config = NodeConfig {\n        utxo_validation: false,\n        ..NodeConfig::default()\n    };\n    let mut wallets = launch_custom_provider_and_get_wallets(\n        WalletsConfig::new(Some(1), Some(10), Some(1000)),\n        Some(provider_config),\n        None,\n    )\n    .await?;\n    let wallet = wallets.pop().unwrap();\n    let provider = wallet.provider();\n\n    let impersonator = Wallet::new(FakeSigner::new(wallet.address()), provider.clone());\n\n    abigen!(Contract(\n        name = \"MyContract\",\n        abi = \"e2e/sway/contracts/contract_test/out/release/contract_test-abi.json\"\n    ));\n\n    let contract_id = Contract::load_from(\n        \"sway/contracts/contract_test/out/release/contract_test.bin\",\n        LoadConfiguration::default(),\n    )?\n    .deploy_if_not_exists(&wallet, TxPolicies::default())\n    .await?\n    .contract_id;\n\n    let contract_instance = MyContract::new(contract_id, impersonator.clone());\n\n    // The gas used by the script to call a contract and forward remaining gas limit.\n    contract_instance\n        .methods()\n        .initialize_counter(42)\n        .call()\n        .await?;\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn is_account_query_test() -> Result<()> {\n    {\n        let wallet = launch_provider_and_get_wallet().await?;\n        let provider = wallet.provider().clone();\n\n        let blob = Blob::new(vec![1; 100]);\n        let blob_id = blob.id();\n\n        let is_account = provider.is_user_account(blob_id).await?;\n        assert!(is_account);\n\n        let mut tb = BlobTransactionBuilder::default().with_blob(blob);\n        wallet.adjust_for_fee(&mut tb, 0).await?;\n        wallet.add_witnesses(&mut tb)?;\n        let tx = tb.build(provider.clone()).await?;\n\n        provider\n            .send_transaction_and_await_commit(tx)\n            .await?\n            .check(None)?;\n\n        let is_account = provider.is_user_account(blob_id).await?;\n        assert!(!is_account);\n    }\n    {\n        let wallet = launch_provider_and_get_wallet().await?;\n        let provider = wallet.provider().clone();\n\n        let contract = Contract::load_from(\n            \"sway/contracts/contract_test/out/release/contract_test.bin\",\n            LoadConfiguration::default(),\n        )?;\n        let contract_id = contract.contract_id();\n\n        let is_account = provider.is_user_account(*contract_id).await?;\n        assert!(is_account);\n\n        contract.deploy(&wallet, TxPolicies::default()).await?;\n\n        let is_account = provider.is_user_account(*contract_id).await?;\n        assert!(!is_account);\n    }\n    {\n        let wallet = launch_provider_and_get_wallet().await?;\n        let provider = wallet.provider().clone();\n\n        let mut tb = ScriptTransactionBuilder::default();\n        wallet.adjust_for_fee(&mut tb, 0).await?;\n        wallet.add_witnesses(&mut tb)?;\n        let tx = tb.build(provider.clone()).await?;\n\n        let consensus_parameters = provider.consensus_parameters().await?;\n        let tx_id = tx.id(consensus_parameters.chain_id());\n        let is_account = provider.is_user_account(tx_id).await?;\n        assert!(is_account);\n\n        provider\n            .send_transaction_and_await_commit(tx)\n            .await?\n            .check(None)?;\n        let is_account = provider.is_user_account(tx_id).await?;\n        assert!(!is_account);\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn script_tx_get_owner_returns_owner_when_policy_set_multiple_inputs() -> Result<()> {\n    use fuel_asm::{GMArgs, op};\n\n    let amount = 1000;\n    let num_coins = 1;\n    let mut wallets = launch_custom_provider_and_get_wallets(\n        WalletsConfig::new(Some(3), Some(num_coins), Some(amount)),\n        Some(NodeConfig::default()),\n        None,\n    )\n    .await?;\n    let wallet_0 = wallets.pop().unwrap();\n    let wallet_1 = wallets.pop().unwrap();\n    let wallet_2 = wallets.pop().unwrap();\n    let provider = wallet_0.provider().clone();\n\n    let consensus_parameters = provider.consensus_parameters().await?;\n    let inputs_0 = wallet_0\n        .get_asset_inputs_for_amount(*consensus_parameters.base_asset_id(), amount as u128, None)\n        .await?;\n    let inputs_1 = wallet_1\n        .get_asset_inputs_for_amount(*consensus_parameters.base_asset_id(), amount as u128, None)\n        .await?;\n    let inputs_2 = wallet_2\n        .get_asset_inputs_for_amount(*consensus_parameters.base_asset_id(), amount as u128, None)\n        .await?;\n\n    let mut inputs = vec![];\n    inputs.extend(inputs_0);\n    inputs.extend(inputs_1);\n    inputs.extend(inputs_2);\n\n    let tx_policies = TxPolicies::default().with_owner(1);\n    let mut tb =\n        ScriptTransactionBuilder::prepare_transfer(inputs, vec![], tx_policies).enable_burn(true);\n    wallet_0.add_witnesses(&mut tb)?;\n    wallet_1.add_witnesses(&mut tb)?;\n    wallet_2.add_witnesses(&mut tb)?;\n\n    let script = vec![\n        op::gm_args(0x20, GMArgs::GetOwner),\n        op::movi(0x21, 32),\n        op::retd(0x20, 0x21),\n    ]\n    .into_iter()\n    .collect();\n\n    tb.script = script;\n\n    let expected_data = wallet_1.address();\n\n    let tx = tb.build(&provider).await?;\n\n    let status = provider.send_transaction_and_await_commit(tx).await?;\n\n    match status {\n        TxStatus::Success(Success { receipts, .. }) => {\n            let ret = receipts\n                .as_ref()\n                .iter()\n                .find_map(|receipt| match receipt {\n                    Receipt::ReturnData { data, .. } if data.is_some() => {\n                        Some(data.clone().unwrap())\n                    }\n                    _ => None,\n                })\n                .expect(\"should have return value\");\n\n            assert_eq!(ret, expected_data.as_ref().to_vec().into());\n        }\n        _ => panic!(\"expected success status\"),\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn script_tx_get_owner_panics_when_policy_unset_multiple_inputs() -> Result<()> {\n    use fuel_asm::{GMArgs, op};\n\n    let amount = 1000;\n    let num_coins = 1;\n    let mut wallets = launch_custom_provider_and_get_wallets(\n        WalletsConfig::new(Some(3), Some(num_coins), Some(amount)),\n        Some(NodeConfig::default()),\n        None,\n    )\n    .await?;\n    let wallet_0 = wallets.pop().unwrap();\n    let wallet_1 = wallets.pop().unwrap();\n    let wallet_2 = wallets.pop().unwrap();\n    let provider = wallet_0.provider().clone();\n\n    let consensus_parameters = provider.consensus_parameters().await?;\n    let inputs_0 = wallet_0\n        .get_asset_inputs_for_amount(*consensus_parameters.base_asset_id(), amount as u128, None)\n        .await?;\n    let inputs_1 = wallet_1\n        .get_asset_inputs_for_amount(*consensus_parameters.base_asset_id(), amount as u128, None)\n        .await?;\n    let inputs_2 = wallet_2\n        .get_asset_inputs_for_amount(*consensus_parameters.base_asset_id(), amount as u128, None)\n        .await?;\n\n    let mut inputs = vec![];\n    inputs.extend(inputs_0);\n    inputs.extend(inputs_1);\n    inputs.extend(inputs_2);\n\n    let mut tb = ScriptTransactionBuilder::prepare_transfer(inputs, vec![], TxPolicies::default())\n        .enable_burn(true);\n    wallet_0.add_witnesses(&mut tb)?;\n    wallet_1.add_witnesses(&mut tb)?;\n    wallet_2.add_witnesses(&mut tb)?;\n\n    let script = vec![\n        op::gm_args(0x20, GMArgs::GetOwner),\n        op::movi(0x21, 32),\n        op::retd(0x20, 0x21),\n    ]\n    .into_iter()\n    .collect();\n\n    tb.script = script;\n\n    let tx = tb.build(&provider).await?;\n\n    let status = provider.send_transaction_and_await_commit(tx).await?;\n\n    match status {\n        TxStatus::Failure(Failure { .. }) => {}\n        _ => panic!(\"expected failure status\"),\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn script_tx_get_owner_returns_owner_when_policy_unset_all_inputs_same_owner() -> Result<()> {\n    use fuel_asm::{GMArgs, op};\n\n    let wallet = launch_provider_and_get_wallet().await?;\n    let provider = wallet.provider();\n\n    let receiver = Wallet::random(&mut thread_rng(), provider.clone());\n\n    let consensus_parameters = provider.consensus_parameters().await?;\n    let inputs = wallet\n        .get_asset_inputs_for_amount(*consensus_parameters.base_asset_id(), 1000, None)\n        .await?;\n    let outputs = wallet.get_asset_outputs_for_amount(\n        receiver.address(),\n        *consensus_parameters.base_asset_id(),\n        1,\n    );\n\n    let tx_policies = TxPolicies::default();\n    let mut tb = ScriptTransactionBuilder::prepare_transfer(inputs, outputs, tx_policies);\n    wallet.add_witnesses(&mut tb)?;\n\n    let script = vec![\n        op::gm_args(0x20, GMArgs::GetOwner),\n        op::movi(0x21, 32),\n        op::retd(0x20, 0x21),\n    ]\n    .into_iter()\n    .collect();\n\n    tb.script = script;\n\n    let expected_data = wallet.address();\n\n    let tx = tb.build(provider).await?;\n\n    let status = provider.send_transaction_and_await_commit(tx).await?;\n\n    match status {\n        TxStatus::Success(Success { receipts, .. }) => {\n            let ret = receipts\n                .as_ref()\n                .iter()\n                .find_map(|receipt| match receipt {\n                    Receipt::ReturnData { data, .. } if data.is_some() => {\n                        Some(data.clone().unwrap())\n                    }\n                    _ => None,\n                })\n                .expect(\"should have return value\");\n\n            assert_eq!(ret, expected_data.as_ref().to_vec().into());\n        }\n        _ => panic!(\"expected success status\"),\n    }\n\n    Ok(())\n}\n"
  },
  {
    "path": "e2e/tests/scripts.rs",
    "content": "use std::time::Duration;\n\nuse fuel_tx::Output;\nuse fuels::{\n    accounts::signers::private_key::PrivateKeySigner,\n    client::{PageDirection, PaginationRequest},\n    core::{\n        Configurables,\n        codec::{DecoderConfig, EncoderConfig},\n        traits::Tokenizable,\n    },\n    prelude::*,\n    programs::{DEFAULT_MAX_FEE_ESTIMATION_TOLERANCE, executable::Executable},\n    types::{Bits256, Identity},\n};\nuse rand::thread_rng;\n\n#[tokio::test]\nasync fn main_function_arguments() -> Result<()> {\n    // ANCHOR: script_with_arguments\n    // The abigen is used for the same purpose as with contracts (Rust bindings)\n    abigen!(Script(\n        name = \"MyScript\",\n        abi = \"e2e/sway/scripts/arguments/out/release/arguments-abi.json\"\n    ));\n    let wallet = launch_provider_and_get_wallet().await?;\n    let bin_path = \"sway/scripts/arguments/out/release/arguments.bin\";\n    let script_instance = MyScript::new(wallet, bin_path);\n\n    let bim = Bimbam { val: 90 };\n    let bam = SugarySnack {\n        twix: 100,\n        mars: 1000,\n    };\n\n    let result = script_instance.main(bim, bam).call().await?;\n\n    let expected = Bimbam { val: 2190 };\n    assert_eq!(result.value, expected);\n    // ANCHOR_END: script_with_arguments\n    Ok(())\n}\n\n#[tokio::test]\nasync fn script_call_has_same_estimated_and_used_gas() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Script(\n            name = \"MyScript\",\n            project = \"e2e/sway/scripts/basic_script\"\n        )),\n        LoadScript(\n            name = \"script_instance\",\n            script = \"MyScript\",\n            wallet = \"wallet\"\n        )\n    );\n\n    let tolerance = Some(0.0);\n    let block_horizon = Some(1);\n\n    let a = 4u64;\n    let b = 2u32;\n    let estimated_total_gas = script_instance\n        .main(a, b)\n        .estimate_transaction_cost(tolerance, block_horizon)\n        .await?\n        .total_gas;\n\n    let total_gas = script_instance.main(a, b).call().await?.tx_status.total_gas;\n\n    assert_eq!(estimated_total_gas, total_gas);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_basic_script_with_tx_policies() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Script(\n            name = \"bimbam_script\",\n            project = \"e2e/sway/scripts/basic_script\"\n        )),\n        LoadScript(\n            name = \"script_instance\",\n            script = \"bimbam_script\",\n            wallet = \"wallet\"\n        )\n    );\n\n    let a = 1000u64;\n    let b = 2000u32;\n    let result = script_instance.main(a, b).call().await?;\n    assert_eq!(result.value, \"hello\");\n\n    // ANCHOR: script_with_tx_policies\n    let tx_policies = TxPolicies::default().with_script_gas_limit(1_000_000);\n    let result = script_instance\n        .main(a, b)\n        .with_tx_policies(tx_policies)\n        .call()\n        .await?;\n    // ANCHOR_END: script_with_tx_policies\n    assert_eq!(result.value, \"hello\");\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_output_variable_estimation() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Script(\n            name = \"transfer_script\",\n            project = \"e2e/sway/scripts/transfer_script\"\n        )),\n        LoadScript(\n            name = \"script_instance\",\n            script = \"transfer_script\",\n            wallet = \"wallet\"\n        )\n    );\n\n    let provider = wallet.provider().clone();\n    let receiver = Wallet::random(&mut thread_rng(), provider);\n\n    let amount = 1000;\n    let asset_id = AssetId::zeroed();\n    let script_call = script_instance.main(amount, asset_id, Identity::Address(receiver.address()));\n    let inputs = wallet\n        .get_asset_inputs_for_amount(asset_id, amount.into(), None)\n        .await?;\n    let output = Output::change(wallet.address(), 0, asset_id);\n    let _ = script_call\n        .with_inputs(inputs)\n        .with_outputs(vec![output])\n        .with_variable_output_policy(VariableOutputPolicy::EstimateMinimum)\n        .call()\n        .await?;\n\n    let receiver_balance = receiver.get_asset_balance(&asset_id).await?;\n    assert_eq!(receiver_balance, amount as u128);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_script_struct() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Script(\n            name = \"MyScript\",\n            project = \"e2e/sway/scripts/script_struct\"\n        )),\n        LoadScript(\n            name = \"script_instance\",\n            script = \"MyScript\",\n            wallet = \"wallet\"\n        )\n    );\n\n    let my_struct = MyStruct {\n        number: 42,\n        boolean: true,\n    };\n    let response = script_instance.main(my_struct).call().await?;\n\n    assert_eq!(response.value, 42);\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_script_enum() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Script(\n            name = \"MyScript\",\n            project = \"e2e/sway/scripts/script_enum\"\n        )),\n        LoadScript(\n            name = \"script_instance\",\n            script = \"MyScript\",\n            wallet = \"wallet\"\n        )\n    );\n\n    let my_enum = MyEnum::Two;\n    let response = script_instance.main(my_enum).call().await?;\n\n    assert_eq!(response.value, 2);\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_script_array() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Script(\n            name = \"MyScript\",\n            project = \"e2e/sway/scripts/script_array\"\n        )),\n        LoadScript(\n            name = \"script_instance\",\n            script = \"MyScript\",\n            wallet = \"wallet\"\n        )\n    );\n\n    let my_array: [u64; 4] = [1, 2, 3, 4];\n    let response = script_instance.main(my_array).call().await?;\n\n    assert_eq!(response.value, 10);\n    Ok(())\n}\n\n#[tokio::test]\nasync fn can_configure_decoder_on_script_call() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Script(\n            name = \"MyScript\",\n            project = \"e2e/sway/scripts/script_needs_custom_decoder\"\n        )),\n        LoadScript(\n            name = \"script_instance\",\n            script = \"MyScript\",\n            wallet = \"wallet\"\n        )\n    );\n\n    {\n        // Will fail if max_tokens too low\n        script_instance\n            .main(false)\n            .with_decoder_config(DecoderConfig {\n                max_tokens: 101,\n                ..Default::default()\n            })\n            .call()\n            .await\n            .expect_err(\n                \"Should fail because return type has more tokens than what is allowed by default\",\n            );\n    }\n    {\n        // When the token limit is bumped should pass\n        let response = script_instance\n            .main(false)\n            .with_decoder_config(DecoderConfig {\n                max_tokens: 1002,\n                ..Default::default()\n            })\n            .call()\n            .await?\n            .value\n            .unwrap();\n\n        assert_eq!(response, [0u8; 1000]);\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_script_submit_and_response() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Script(\n            name = \"MyScript\",\n            project = \"e2e/sway/scripts/script_struct\"\n        )),\n        LoadScript(\n            name = \"script_instance\",\n            script = \"MyScript\",\n            wallet = \"wallet\"\n        )\n    );\n\n    let my_struct = MyStruct {\n        number: 42,\n        boolean: true,\n    };\n\n    // ANCHOR: submit_response_script\n    let submitted_tx = script_instance.main(my_struct).submit().await?;\n    tokio::time::sleep(Duration::from_millis(500)).await;\n    let value = submitted_tx.response().await?.value;\n    // ANCHOR_END: submit_response_script\n\n    assert_eq!(value, 42);\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_script_transaction_builder() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Script(\n            name = \"MyScript\",\n            project = \"e2e/sway/scripts/basic_script\"\n        )),\n        LoadScript(\n            name = \"script_instance\",\n            script = \"MyScript\",\n            wallet = \"wallet\"\n        )\n    );\n    let provider = wallet.provider();\n\n    // ANCHOR: script_call_tb\n    let script_call_handler = script_instance.main(1, 2);\n\n    let mut tb = script_call_handler.transaction_builder().await?;\n\n    // customize the builder...\n\n    wallet.adjust_for_fee(&mut tb, 0).await?;\n    wallet.add_witnesses(&mut tb)?;\n\n    let tx = tb.build(provider).await?;\n\n    let tx_id = provider.send_transaction(tx).await?;\n    tokio::time::sleep(Duration::from_millis(500)).await;\n    let tx_status = provider.tx_status(&tx_id).await?;\n\n    let response = script_call_handler.get_response(tx_status)?;\n\n    assert_eq!(response.value, \"hello\");\n    // ANCHOR_END: script_call_tb\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn script_encoder_config_is_applied() {\n    abigen!(Script(\n        name = \"MyScript\",\n        abi = \"e2e/sway/scripts/basic_script/out/release/basic_script-abi.json\"\n    ));\n    let wallet = launch_provider_and_get_wallet().await.expect(\"\");\n    let bin_path = \"sway/scripts/basic_script/out/release/basic_script.bin\";\n\n    let script_instance_without_encoder_config = MyScript::new(wallet.clone(), bin_path);\n    {\n        let _encoding_ok = script_instance_without_encoder_config\n            .main(1, 2)\n            .call()\n            .await\n            .expect(\"should not fail as it uses the default encoder config\");\n    }\n    {\n        let encoder_config = EncoderConfig {\n            max_tokens: 1,\n            ..Default::default()\n        };\n        let script_instance_with_encoder_config =\n            MyScript::new(wallet.clone(), bin_path).with_encoder_config(encoder_config);\n\n        // uses 2 tokens when 1 is the limit\n        let encoding_error = script_instance_with_encoder_config\n            .main(1, 2)\n            .call()\n            .await\n            .expect_err(\"should error\");\n\n        assert!(encoding_error.to_string().contains(\n            \"cannot encode script call arguments: codec: token limit `1` reached while encoding\"\n        ));\n\n        let encoding_error = script_instance_with_encoder_config\n            .main(1, 2)\n            .simulate(Execution::realistic())\n            .await\n            .expect_err(\"should error\");\n\n        assert!(encoding_error.to_string().contains(\n            \"cannot encode script call arguments: codec: token limit `1` reached while encoding\"\n        ));\n    }\n}\n#[tokio::test]\nasync fn simulations_can_be_made_without_coins() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Script(\n            name = \"MyScript\",\n            project = \"e2e/sway/scripts/basic_script\"\n        )),\n        LoadScript(\n            name = \"script_instance\",\n            script = \"MyScript\",\n            wallet = \"wallet\"\n        )\n    );\n    let provider = wallet.provider().clone();\n\n    let no_funds_wallet = Wallet::random(&mut thread_rng(), provider);\n    let script_instance = script_instance.with_account(no_funds_wallet);\n\n    let value = script_instance\n        .main(1000, 2000)\n        .simulate(Execution::state_read_only())\n        .await?\n        .value;\n\n    assert_eq!(value.as_ref(), \"hello\");\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn can_be_run_in_blobs_builder() -> Result<()> {\n    abigen!(Script(\n        abi = \"e2e/sway/scripts/script_blobs/out/release/script_blobs-abi.json\",\n        name = \"MyScript\"\n    ));\n\n    let binary_path = \"./sway/scripts/script_blobs/out/release/script_blobs.bin\";\n    let wallet = launch_provider_and_get_wallet().await?;\n    let provider = wallet.provider().clone();\n\n    // ANCHOR: preload_low_level\n    let regular = Executable::load_from(binary_path)?;\n\n    let configurables = MyScriptConfigurables::default().with_SECRET_NUMBER(10001)?;\n    let loader = regular\n        .convert_to_loader()?\n        .with_configurables(configurables);\n\n    // The Blob must be uploaded manually, otherwise the script code will revert.\n    loader.upload_blob(wallet.clone()).await?;\n\n    let encoder = fuels::core::codec::ABIEncoder::default();\n    let token = MyStruct {\n        field_a: MyEnum::B(99),\n        field_b: Bits256([17; 32]),\n    }\n    .into_token();\n    let data = encoder.encode(&[token])?;\n\n    let mut tb = ScriptTransactionBuilder::default()\n        .with_script(loader.code())\n        .with_script_data(data);\n\n    wallet.adjust_for_fee(&mut tb, 0).await?;\n\n    wallet.add_witnesses(&mut tb)?;\n\n    let tx = tb.build(&provider).await?;\n\n    let response = provider.send_transaction_and_await_commit(tx).await?;\n\n    response.check(None)?;\n    // ANCHOR_END: preload_low_level\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn can_be_run_in_blobs_high_level() -> Result<()> {\n    setup_program_test!(\n        Abigen(Script(\n            project = \"e2e/sway/scripts/script_blobs\",\n            name = \"MyScript\"\n        )),\n        Wallets(\"wallet\"),\n        LoadScript(name = \"my_script\", script = \"MyScript\", wallet = \"wallet\")\n    );\n\n    let configurables = MyScriptConfigurables::default().with_SECRET_NUMBER(10001)?;\n    let mut my_script = my_script.with_configurables(configurables);\n\n    let arg = MyStruct {\n        field_a: MyEnum::B(99),\n        field_b: Bits256([17; 32]),\n    };\n    let secret = my_script\n        .convert_into_loader()\n        .await?\n        .main(arg)\n        .call()\n        .await?\n        .value;\n\n    assert_eq!(secret, 10001);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn high_level_blob_upload_sets_max_fee_tolerance() -> Result<()> {\n    let node_config = NodeConfig {\n        starting_gas_price: 1000000000,\n        ..Default::default()\n    };\n    let signer = PrivateKeySigner::random(&mut thread_rng());\n    let coins = setup_single_asset_coins(signer.address(), AssetId::zeroed(), 1, u64::MAX);\n    let provider = setup_test_provider(coins, vec![], Some(node_config), None).await?;\n    let wallet = Wallet::new(signer, provider.clone());\n\n    setup_program_test!(\n        Abigen(Script(\n            project = \"e2e/sway/scripts/script_blobs\",\n            name = \"MyScript\"\n        )),\n        LoadScript(name = \"my_script\", script = \"MyScript\", wallet = \"wallet\")\n    );\n\n    let loader = Executable::from_bytes(std::fs::read(\n        \"sway/scripts/script_blobs/out/release/script_blobs.bin\",\n    )?)\n    .convert_to_loader()?;\n\n    let zero_tolerance_fee = {\n        let mut tb = BlobTransactionBuilder::default()\n            .with_blob(loader.blob())\n            .with_max_fee_estimation_tolerance(0.);\n\n        wallet.adjust_for_fee(&mut tb, 0).await?;\n\n        wallet.add_witnesses(&mut tb)?;\n        let tx = tb.build(&provider).await?;\n        tx.max_fee().unwrap()\n    };\n\n    let mut my_script = my_script;\n    my_script.convert_into_loader().await?;\n\n    let max_fee_of_sent_blob_tx = provider\n        .get_transactions(PaginationRequest {\n            cursor: None,\n            results: 20,\n            direction: PageDirection::Forward,\n        })\n        .await?\n        .results\n        .into_iter()\n        .find_map(|tx| {\n            if let TransactionType::Blob(blob_transaction) = tx.transaction {\n                blob_transaction.max_fee()\n            } else {\n                None\n            }\n        })\n        .unwrap();\n\n    assert_eq!(\n        max_fee_of_sent_blob_tx,\n        (zero_tolerance_fee as f32 * (1.0 + DEFAULT_MAX_FEE_ESTIMATION_TOLERANCE)).ceil() as u64,\n        \"the blob upload tx should have had the max fee increased by the default estimation tolerance\"\n    );\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn no_data_section_blob_run() -> Result<()> {\n    setup_program_test!(\n        Abigen(Script(\n            project = \"e2e/sway/scripts/empty\",\n            name = \"MyScript\"\n        )),\n        Wallets(\"wallet\"),\n        LoadScript(name = \"my_script\", script = \"MyScript\", wallet = \"wallet\")\n    );\n\n    let mut my_script = my_script;\n\n    // ANCHOR: preload_high_level\n    my_script.convert_into_loader().await?.main().call().await?;\n    // ANCHOR_END: preload_high_level\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn loader_script_calling_loader_proxy() -> Result<()> {\n    setup_program_test!(\n        Abigen(\n            Contract(\n                name = \"MyContract\",\n                project = \"e2e/sway/contracts/huge_contract\"\n            ),\n            Contract(name = \"MyProxy\", project = \"e2e/sway/contracts/proxy\"),\n            Script(name = \"MyScript\", project = \"e2e/sway/scripts/script_proxy\"),\n        ),\n        Wallets(\"wallet\"),\n        LoadScript(name = \"my_script\", script = \"MyScript\", wallet = \"wallet\")\n    );\n\n    let contract_binary = \"sway/contracts/huge_contract/out/release/huge_contract.bin\";\n\n    let contract = Contract::load_from(contract_binary, LoadConfiguration::default())?;\n\n    let contract_id = contract\n        .convert_to_loader(100)?\n        .deploy_if_not_exists(&wallet, TxPolicies::default())\n        .await?\n        .contract_id;\n\n    let contract_binary = \"sway/contracts/proxy/out/release/proxy.bin\";\n\n    let proxy_id = Contract::load_from(contract_binary, LoadConfiguration::default())?\n        .convert_to_loader(100)?\n        .deploy_if_not_exists(&wallet, TxPolicies::default())\n        .await?\n        .contract_id;\n\n    let proxy = MyProxy::new(proxy_id, wallet.clone());\n    proxy\n        .methods()\n        .set_target_contract(contract_id)\n        .call()\n        .await?;\n\n    let mut my_script = my_script;\n    let result = my_script\n        .convert_into_loader()\n        .await?\n        .main(proxy_id)\n        .with_contract_ids(&[contract_id, proxy_id])\n        .call()\n        .await?;\n\n    assert!(result.value);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn loader_can_be_presented_as_a_normal_script_with_shifted_configurables() -> Result<()> {\n    abigen!(Script(\n        abi = \"e2e/sway/scripts/script_blobs/out/release/script_blobs-abi.json\",\n        name = \"MyScript\"\n    ));\n\n    let binary_path = \"./sway/scripts/script_blobs/out/release/script_blobs.bin\";\n    let wallet = launch_provider_and_get_wallet().await?;\n    let provider = wallet.provider().clone();\n\n    let regular = Executable::load_from(binary_path)?;\n\n    let configurables = MyScriptConfigurables::default().with_SECRET_NUMBER(10001)?;\n    let loader = regular.clone().convert_to_loader()?;\n\n    // The Blob must be uploaded manually, otherwise the script code will revert.\n    loader.upload_blob(wallet.clone()).await?;\n\n    let encoder = fuels::core::codec::ABIEncoder::default();\n    let token = MyStruct {\n        field_a: MyEnum::B(99),\n        field_b: Bits256([17; 32]),\n    }\n    .into_token();\n    let data = encoder.encode(&[token])?;\n\n    let configurables: Configurables = configurables.into();\n\n    let offset = regular\n        .configurables_offset_in_code()?\n        .unwrap_or_else(|| regular.data_offset_in_code().unwrap());\n\n    let shifted_configurables = configurables\n        .with_shifted_offsets(-(offset as i64))\n        .unwrap()\n        .with_shifted_offsets(loader.configurables_offset_in_code() as i64)\n        .unwrap();\n\n    let loader_posing_as_normal_script =\n        Executable::from_bytes(loader.code()).with_configurables(shifted_configurables);\n\n    let mut tb = ScriptTransactionBuilder::default()\n        .with_script(loader_posing_as_normal_script.code())\n        .with_script_data(data);\n\n    wallet.adjust_for_fee(&mut tb, 0).await?;\n\n    wallet.add_witnesses(&mut tb)?;\n\n    let tx = tb.build(&provider).await?;\n\n    let response = provider.send_transaction_and_await_commit(tx).await?;\n\n    response.check(None)?;\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn script_call_respects_maturity_and_expiration() -> Result<()> {\n    abigen!(Script(\n        name = \"MyScript\",\n        abi = \"e2e/sway/scripts/basic_script/out/release/basic_script-abi.json\"\n    ));\n    let wallet = launch_provider_and_get_wallet().await.expect(\"\");\n    let provider = wallet.provider().clone();\n    let bin_path = \"sway/scripts/basic_script/out/release/basic_script.bin\";\n\n    let script_instance = MyScript::new(wallet, bin_path);\n\n    let maturity = 10;\n    let expiration = 20;\n    let call_handler = script_instance.main(1, 2).with_tx_policies(\n        TxPolicies::default()\n            .with_maturity(maturity)\n            .with_expiration(expiration),\n    );\n\n    {\n        let err = call_handler\n            .clone()\n            .call()\n            .await\n            .expect_err(\"maturity not reached\");\n\n        assert!(err.to_string().contains(\"TransactionMaturity\"));\n    }\n    {\n        provider.produce_blocks(15, None).await?;\n        call_handler\n            .clone()\n            .call()\n            .await\n            .expect(\"should succeed. Block height between `maturity` and `expiration`\");\n    }\n    {\n        provider.produce_blocks(15, None).await?;\n        let err = call_handler.call().await.expect_err(\"expiration reached\");\n\n        assert!(err.to_string().contains(\"TransactionExpiration\"));\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn script_tx_input_output() -> Result<()> {\n    let [wallet_1, wallet_2] = launch_custom_provider_and_get_wallets(\n        WalletsConfig::new(Some(2), Some(10), Some(1000)),\n        None,\n        None,\n    )\n    .await?\n    .try_into()\n    .unwrap();\n\n    abigen!(Script(\n        name = \"TxScript\",\n        abi = \"e2e/sway/scripts/script_tx_input_output/out/release/script_tx_input_output-abi.json\"\n    ));\n    let script_binary =\n        \"sway/scripts/script_tx_input_output/out/release/script_tx_input_output.bin\";\n\n    // Set `wallet_1` as the custom input owner\n    let configurables = TxScriptConfigurables::default().with_OWNER(wallet_1.address())?;\n\n    let script_instance =\n        TxScript::new(wallet_2.clone(), script_binary).with_configurables(configurables);\n\n    let asset_id = AssetId::zeroed();\n\n    {\n        let custom_inputs = wallet_1\n            .get_asset_inputs_for_amount(asset_id, 10, None)\n            .await?\n            .into_iter()\n            .take(1)\n            .collect();\n\n        let custom_output = vec![Output::change(wallet_1.address(), 0, asset_id)];\n\n        // Input at first position is a coin owned by wallet_1\n        // Output at first position is change to wallet_1\n        // ANCHOR: script_custom_inputs_outputs\n        let _ = script_instance\n            .main(0, 0)\n            .with_inputs(custom_inputs)\n            .with_outputs(custom_output)\n            .add_signer(wallet_1.signer().clone())\n            .call()\n            .await?;\n        // ANCHOR_END: script_custom_inputs_outputs\n    }\n    {\n        // Input at first position is not a coin owned by wallet_1\n        let err = script_instance.main(0, 0).call().await.unwrap_err();\n\n        assert!(err.to_string().contains(\"wrong owner\"));\n\n        let custom_input = wallet_1\n            .get_asset_inputs_for_amount(asset_id, 10, None)\n            .await?\n            .pop()\n            .unwrap();\n\n        // Input at first position is a coin owned by wallet_1\n        // Output at first position is not change to wallet_1\n        let err = script_instance\n            .main(0, 0)\n            .with_inputs(vec![custom_input])\n            .add_signer(wallet_1.signer().clone())\n            .call()\n            .await\n            .unwrap_err();\n\n        assert!(err.to_string().contains(\"wrong change address\"));\n    }\n\n    Ok(())\n}\n"
  },
  {
    "path": "e2e/tests/storage.rs",
    "content": "use fuels::{\n    prelude::*,\n    tx::StorageSlot,\n    types::{Bits256, Bytes32},\n};\n\n#[tokio::test]\nasync fn test_storage_initialization() -> Result<()> {\n    abigen!(Contract(\n        name = \"MyContract\",\n        abi = \"e2e/sway/contracts/storage/out/release/storage-abi.json\"\n    ));\n\n    let wallet = launch_provider_and_get_wallet().await?;\n\n    let key = Bytes32::from([1u8; 32]);\n    let value = Bytes32::from([2u8; 32]);\n    let storage_slot = StorageSlot::new(key, value);\n    let storage_vec = vec![storage_slot.clone()];\n    let storage_configuration = StorageConfiguration::default().add_slot_overrides(storage_vec);\n\n    let contract_id = Contract::load_from(\n        \"sway/contracts/storage/out/release/storage.bin\",\n        LoadConfiguration::default().with_storage_configuration(storage_configuration),\n    )?\n    .deploy_if_not_exists(&wallet, TxPolicies::default())\n    .await?\n    .contract_id;\n\n    let contract_instance = MyContract::new(contract_id, wallet.clone());\n\n    let result = contract_instance\n        .methods()\n        .get_value_b256(Bits256(key.into()))\n        .call()\n        .await?\n        .value;\n    assert_eq!(result.0, *value);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_init_storage_automatically() -> Result<()> {\n    abigen!(Contract(\n        name = \"MyContract\",\n        abi = \"e2e/sway/contracts/storage/out/release/storage-abi.json\"\n    ));\n\n    let wallet = launch_provider_and_get_wallet().await?;\n\n    let contract_id = Contract::load_from(\n        \"sway/contracts/storage/out/release/storage.bin\",\n        LoadConfiguration::default(),\n    )?\n    .deploy_if_not_exists(&wallet, TxPolicies::default())\n    .await?\n    .contract_id;\n\n    let contract_methods = MyContract::new(contract_id, wallet.clone()).methods();\n    {\n        let key: Bytes32 =\n            \"eb390d9f85c8c849ff8aeb05c865ca66b37ba69a7bec8489b1c467f029b650af\".parse()?;\n\n        let value = contract_methods\n            .get_value_b256(Bits256(*key))\n            .call()\n            .await?\n            .value;\n\n        assert_eq!(value.0, [1u8; 32]);\n    }\n    {\n        let key: Bytes32 =\n            \"419b1120ea993203d7e223dfbe76184322453d6f8de946e827a8669102ab395b\".parse()?;\n\n        let value = contract_methods\n            .get_value_u64(Bits256(*key))\n            .call()\n            .await?\n            .value;\n\n        assert_eq!(value, 64);\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn storage_load_error_messages() {\n    {\n        let json_path = \"sway/contracts/storage/out/release/no_file_on_path.json\";\n        let expected_error = format!(\"io: file \\\"{json_path}\\\" does not exist\");\n\n        let error = StorageConfiguration::default()\n            .add_slot_overrides_from_file(json_path)\n            .expect_err(\"should have failed\");\n\n        assert_eq!(error.to_string(), expected_error);\n    }\n    {\n        let json_path = \"sway/contracts/storage/out/release/storage.bin\";\n        let expected_error = format!(\"expected \\\"{json_path}\\\" to have '.json' extension\");\n\n        let error = StorageConfiguration::default()\n            .add_slot_overrides_from_file(json_path)\n            .expect_err(\"should have failed\");\n\n        assert_eq!(error.to_string(), expected_error);\n    }\n}\n"
  },
  {
    "path": "e2e/tests/types_contracts.rs",
    "content": "use std::str::FromStr;\n\nuse fuels::{\n    prelude::*,\n    types::{B512, Bits256, EvmAddress, Identity, SizedAsciiString, U256},\n};\n\n#[tokio::test]\nasync fn test_methods_typeless_argument() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TypesContract\",\n            project = \"e2e/sway/types/contracts/empty_arguments\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TypesContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    let response = contract_instance\n        .methods()\n        .method_with_empty_argument()\n        .call()\n        .await?;\n\n    assert_eq!(response.value, 63);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn call_with_empty_return() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TestContract\",\n            project = \"e2e/sway/types/contracts/call_empty_return\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TestContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    let _response = contract_instance.methods().store_value(42).call().await?;\n    Ok(())\n}\n\n#[tokio::test]\nasync fn call_with_structs() -> Result<()> {\n    // Generates the bindings from the an ABI definition inline.\n    // The generated bindings can be accessed through `MyContract`.\n    // ANCHOR: struct_generation\n    abigen!(Contract(\n        name = \"MyContract\",\n        abi = \"e2e/sway/types/contracts/complex_types_contract/out/release/complex_types_contract-abi.json\"\n    ));\n\n    // Here we can use `CounterConfig`, a struct originally\n    // defined in the contract.\n    let counter_config = CounterConfig {\n        dummy: true,\n        initial_value: 42,\n    };\n    // ANCHOR_END: struct_generation\n\n    let wallet = launch_provider_and_get_wallet().await?;\n\n    let contract_id = Contract::load_from(\n        \"sway/types/contracts/complex_types_contract/out/release/complex_types_contract.bin\",\n        LoadConfiguration::default(),\n    )?\n    .deploy_if_not_exists(&wallet, TxPolicies::default())\n    .await?\n    .contract_id;\n\n    let contract_methods = MyContract::new(contract_id, wallet).methods();\n\n    let response = contract_methods\n        .initialize_counter(counter_config)\n        .call()\n        .await?;\n\n    assert_eq!(42, response.value);\n\n    let response = contract_methods.increment_counter(10).call().await?;\n\n    assert_eq!(52, response.value);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn abigen_different_structs_same_arg_name() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TypesContract\",\n            project = \"e2e/sway/types/contracts/two_structs\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TypesContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    let param_one = StructOne { foo: 42 };\n    let param_two = StructTwo { bar: 42 };\n\n    let contract_methods = contract_instance.methods();\n    let res_one = contract_methods.something(param_one).call().await?;\n\n    assert_eq!(res_one.value, 43);\n\n    let res_two = contract_methods.something_else(param_two).call().await?;\n\n    assert_eq!(res_two.value, 41);\n    Ok(())\n}\n\n#[tokio::test]\nasync fn nested_structs() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TypesContract\",\n            project = \"e2e/sway/types/contracts/nested_structs\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TypesContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    let expected = AllStruct {\n        some_struct: SomeStruct {\n            field: 12345,\n            field_2: true,\n        },\n    };\n\n    let contract_methods = contract_instance.methods();\n    let actual = contract_methods.get_struct().call().await?.value;\n    assert_eq!(actual, expected);\n\n    let fuelvm_judgement = contract_methods\n        .check_struct_integrity(expected)\n        .call()\n        .await?\n        .value;\n\n    assert!(\n        fuelvm_judgement,\n        \"The FuelVM deems that we've not encoded the argument correctly. Investigate!\"\n    );\n\n    let memory_address = MemoryAddress {\n        contract_id: ContractId::zeroed(),\n        function_selector: 10,\n        function_data: 0,\n    };\n\n    let call_data = CallData {\n        memory_address,\n        num_coins_to_forward: 10,\n        asset_id_of_coins_to_forward: ContractId::zeroed(),\n        amount_of_gas_to_forward: 5,\n    };\n\n    let actual = contract_methods\n        .nested_struct_with_reserved_keyword_substring(call_data.clone())\n        .call()\n        .await?\n        .value;\n\n    assert_eq!(actual, call_data);\n    Ok(())\n}\n\n#[tokio::test]\nasync fn calls_with_empty_struct() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TypesContract\",\n            project = \"e2e/sway/types/contracts/complex_types_contract\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TypesContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n    let contract_methods = contract_instance.methods();\n\n    {\n        let response = contract_methods.get_empty_struct().call().await?;\n\n        assert_eq!(response.value, EmptyStruct {});\n    }\n    {\n        let response = contract_methods\n            .input_empty_struct(EmptyStruct {})\n            .call()\n            .await?;\n\n        assert!(response.value);\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn can_use_try_into_to_construct_struct_from_bytes() -> Result<()> {\n    abigen!(Contract(\n        name = \"MyContract\",\n        abi = \"e2e/sway/types/contracts/enum_inside_struct/out/release\\\n        /enum_inside_struct-abi.json\"\n    ));\n    let cocktail_in_bytes: Vec<u8> = vec![\n        0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3,\n    ];\n\n    let expected = Cocktail {\n        the_thing_you_mix_in: Shaker::Mojito(2),\n        glass: 3,\n    };\n\n    // as slice\n    let actual: Cocktail = cocktail_in_bytes[..].try_into()?;\n    assert_eq!(actual, expected);\n\n    // as ref\n    let actual: Cocktail = (&cocktail_in_bytes).try_into()?;\n    assert_eq!(actual, expected);\n\n    // as value\n    let actual: Cocktail = cocktail_in_bytes.try_into()?;\n    assert_eq!(actual, expected);\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_tuples() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TypesContract\",\n            project = \"e2e/sway/types/contracts/tuples\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TypesContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n    let contract_methods = contract_instance.methods();\n\n    {\n        let response = contract_methods.returns_tuple((1, 2)).call().await?;\n\n        assert_eq!(response.value, (1, 2));\n    }\n    {\n        // Tuple with struct.\n        let my_struct_tuple = (\n            42,\n            Person {\n                name: \"Jane\".try_into()?,\n            },\n        );\n        let response = contract_methods\n            .returns_struct_in_tuple(my_struct_tuple.clone())\n            .call()\n            .await?;\n\n        assert_eq!(response.value, my_struct_tuple);\n    }\n    {\n        // Tuple with enum.\n        let my_enum_tuple: (u64, State) = (42, State::A);\n\n        let response = contract_methods\n            .returns_enum_in_tuple(my_enum_tuple.clone())\n            .call()\n            .await?;\n\n        assert_eq!(response.value, my_enum_tuple);\n    }\n    {\n        // Tuple with single element\n        let my_enum_tuple = (123u64,);\n\n        let response = contract_methods\n            .single_element_tuple(my_enum_tuple)\n            .call()\n            .await?;\n\n        assert_eq!(response.value, my_enum_tuple);\n    }\n    {\n        // tuple with b256\n        let id = *ContractId::zeroed();\n        let my_b256_u8_tuple = (Bits256(id), 10);\n\n        let response = contract_methods\n            .tuple_with_b256(my_b256_u8_tuple)\n            .call()\n            .await?;\n\n        assert_eq!(response.value, my_b256_u8_tuple);\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_evm_address() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TypesContract\",\n            project = \"e2e/sway/types/contracts/evm_address\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TypesContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    {\n        // ANCHOR: evm_address_arg\n        let b256 = Bits256::from_hex_str(\n            \"0x1616060606060606060606060606060606060606060606060606060606060606\",\n        )?;\n        let evm_address = EvmAddress::from(b256);\n\n        let call_handler = contract_instance\n            .methods()\n            .evm_address_as_input(evm_address);\n        // ANCHOR_END: evm_address_arg\n\n        assert!(call_handler.call().await?.value);\n    }\n\n    {\n        let b256 = Bits256::from_hex_str(\n            \"0x0606060606060606060606060606060606060606060606060606060606060606\",\n        )?;\n        let expected_evm_address = EvmAddress::from(b256);\n\n        assert_eq!(\n            contract_instance\n                .methods()\n                .evm_address_from_literal()\n                .call()\n                .await?\n                .value,\n            expected_evm_address\n        );\n    }\n\n    {\n        let b256 = Bits256::from_hex_str(\n            \"0x0606060606060606060606060606060606060606060606060606060606060606\",\n        )?;\n        let expected_evm_address = EvmAddress::from(b256);\n\n        assert_eq!(\n            contract_instance\n                .methods()\n                .evm_address_from_argument(b256)\n                .call()\n                .await?\n                .value,\n            expected_evm_address\n        );\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_array() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TypesContract\",\n            project = \"e2e/sway/contracts/contract_test\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TypesContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    assert_eq!(\n        contract_instance\n            .methods()\n            .get_array([42; 2])\n            .call()\n            .await?\n            .value,\n        [42; 2]\n    );\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_arrays_with_custom_types() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TypesContract\",\n            project = \"e2e/sway/contracts/contract_test\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TypesContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    let persons = [\n        Person {\n            name: \"John\".try_into()?,\n        },\n        Person {\n            name: \"Jane\".try_into()?,\n        },\n    ];\n\n    let contract_methods = contract_instance.methods();\n    let response = contract_methods.array_of_structs(persons).call().await?;\n\n    assert_eq!(\"John\", response.value[0].name);\n    assert_eq!(\"Jane\", response.value[1].name);\n\n    let states = [State::A, State::B];\n\n    let response = contract_methods\n        .array_of_enums(states.clone())\n        .call()\n        .await?;\n\n    assert_eq!(states[0], response.value[0]);\n    assert_eq!(states[1], response.value[1]);\n    Ok(())\n}\n\n#[tokio::test]\nasync fn str_in_array() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TypesContract\",\n            project = \"e2e/sway/types/contracts/str_in_array\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TypesContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    let input = [\"foo\", \"bar\", \"baz\"].map(|str| str.try_into().unwrap());\n    let contract_methods = contract_instance.methods();\n    let response = contract_methods\n        .take_array_string_shuffle(input.clone())\n        .call()\n        .await?;\n\n    assert_eq!(response.value, [\"baz\", \"foo\", \"bar\"]);\n\n    let response = contract_methods\n        .take_array_string_return_single(input.clone())\n        .call()\n        .await?;\n\n    assert_eq!(response.value, [\"foo\"]);\n\n    let response = contract_methods\n        .take_array_string_return_single_element(input)\n        .call()\n        .await?;\n\n    assert_eq!(response.value, \"bar\");\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_enum_inside_struct() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TypesContract\",\n            project = \"e2e/sway/types/contracts/enum_inside_struct\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TypesContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    let expected = Cocktail {\n        the_thing_you_mix_in: Shaker::Mojito(11),\n        glass: 333,\n    };\n\n    let contract_methods = contract_instance.methods();\n    let response = contract_methods\n        .return_enum_inside_struct(11)\n        .call()\n        .await?;\n\n    assert_eq!(response.value, expected);\n\n    let enum_inside_struct = Cocktail {\n        the_thing_you_mix_in: Shaker::Cosmopolitan(444),\n        glass: 555,\n    };\n\n    let response = contract_methods\n        .take_enum_inside_struct(enum_inside_struct)\n        .call()\n        .await?;\n\n    assert_eq!(response.value, 555);\n    Ok(())\n}\n\n#[tokio::test]\nasync fn native_types_support() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TypesContract\",\n            project = \"e2e/sway/types/contracts/native_types\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TypesContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    let user = User {\n        weight: 10,\n        address: Address::zeroed(),\n    };\n\n    let contract_methods = contract_instance.methods();\n    let response = contract_methods.wrapped_address(user).call().await?;\n\n    assert_eq!(response.value.address, Address::zeroed());\n\n    let response = contract_methods\n        .unwrapped_address(Address::zeroed())\n        .call()\n        .await?;\n\n    assert_eq!(\n        response.value,\n        Address::from_str(\"0x0000000000000000000000000000000000000000000000000000000000000000\")?\n    );\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn enum_coding_w_variable_width_variants() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TypesContract\",\n            project = \"e2e/sway/types/contracts/enum_encoding\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TypesContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    // If we had a regression on the issue of enum encoding width, then we'll\n    // probably end up mangling arg_2 and onward which will fail this test.\n    let expected = BigBundle {\n        arg_1: EnumThatHasABigAndSmallVariant::Small(12345),\n        arg_2: 6666,\n        arg_3: 7777,\n        arg_4: 8888,\n    };\n\n    let contract_methods = contract_instance.methods();\n    let actual = contract_methods.get_big_bundle().call().await?.value;\n    assert_eq!(actual, expected);\n\n    let fuelvm_judgement = contract_methods\n        .check_big_bundle_integrity(expected)\n        .call()\n        .await?\n        .value;\n\n    assert!(\n        fuelvm_judgement,\n        \"The FuelVM deems that we've not encoded the bundle correctly. Investigate!\"\n    );\n    Ok(())\n}\n\n#[tokio::test]\nasync fn enum_coding_w_unit_enums() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TypesContract\",\n            project = \"e2e/sway/types/contracts/enum_encoding\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TypesContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    // If we had a regression on the issue of unit enum encoding width, then\n    // we'll end up mangling arg_2\n    let expected = UnitBundle {\n        arg_1: UnitEnum::var2,\n        arg_2: u64::MAX,\n    };\n\n    let contract_methods = contract_instance.methods();\n    let actual = contract_methods.get_unit_bundle().call().await?.value;\n    assert_eq!(actual, expected);\n\n    let fuelvm_judgement = contract_methods\n        .check_unit_bundle_integrity(expected)\n        .call()\n        .await?\n        .value;\n\n    assert!(\n        fuelvm_judgement,\n        \"The FuelVM deems that we've not encoded the bundle correctly. Investigate!\"\n    );\n    Ok(())\n}\n\n#[tokio::test]\nasync fn enum_as_input() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TypesContract\",\n            project = \"e2e/sway/types/contracts/enum_as_input\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TypesContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    let expected = MaxedOutVariantsEnum::Variant255(11);\n    let contract_methods = contract_instance.methods();\n    let actual = contract_methods.get_max_variant().call().await?.value;\n    assert_eq!(expected, actual);\n\n    let expected = StandardEnum::Two(12345);\n    let contract_methods = contract_instance.methods();\n    let actual = contract_methods.get_standard_enum().call().await?.value;\n    assert_eq!(expected, actual);\n\n    let fuelvm_judgement = contract_methods\n        .check_standard_enum_integrity(expected)\n        .call()\n        .await?\n        .value;\n    assert!(\n        fuelvm_judgement,\n        \"The FuelVM deems that we've not encoded the standard enum correctly. Investigate!\"\n    );\n\n    let expected = UnitEnum::Two;\n    let actual = contract_methods.get_unit_enum().call().await?.value;\n    assert_eq!(actual, expected);\n\n    let fuelvm_judgement = contract_methods\n        .check_unit_enum_integrity(expected)\n        .call()\n        .await?\n        .value;\n    assert!(\n        fuelvm_judgement,\n        \"The FuelVM deems that we've not encoded the unit enum correctly. Investigate!\"\n    );\n    Ok(())\n}\n\n#[tokio::test]\nasync fn can_use_try_into_to_construct_enum_from_bytes() -> Result<()> {\n    abigen!(Contract(\n        name = \"MyContract\",\n        abi = \"e2e/sway/types/contracts/enum_inside_struct/out/release\\\n        /enum_inside_struct-abi.json\"\n    ));\n    let shaker_in_bytes: Vec<u8> = vec![0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2];\n\n    let expected = Shaker::Mojito(2);\n\n    // as slice\n    let actual: Shaker = shaker_in_bytes[..].try_into()?;\n    assert_eq!(actual, expected);\n\n    // as ref\n    let actual: Shaker = (&shaker_in_bytes).try_into()?;\n    assert_eq!(actual, expected);\n\n    // as value\n    let actual: Shaker = shaker_in_bytes.try_into()?;\n    assert_eq!(actual, expected);\n    Ok(())\n}\n\n#[tokio::test]\nasync fn type_inside_enum() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TypesContract\",\n            project = \"e2e/sway/types/contracts/type_inside_enum\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TypesContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    // String inside enum\n    let enum_string = SomeEnum::SomeStr(\"asdf\".try_into()?);\n    let contract_methods = contract_instance.methods();\n    let response = contract_methods\n        .str_inside_enum(enum_string.clone())\n        .call()\n        .await?;\n    assert_eq!(response.value, enum_string);\n\n    // Array inside enum\n    let enum_array = SomeEnum::SomeArr([1, 2, 3, 4]);\n    let response = contract_methods\n        .arr_inside_enum(enum_array.clone())\n        .call()\n        .await?;\n    assert_eq!(response.value, enum_array);\n\n    // Struct inside enum\n    let response = contract_methods\n        .return_struct_inside_enum(11)\n        .call()\n        .await?;\n    let expected = Shaker::Cosmopolitan(Recipe { ice: 22, sugar: 11 });\n    assert_eq!(response.value, expected);\n\n    let struct_inside_enum = Shaker::Cosmopolitan(Recipe { ice: 22, sugar: 66 });\n    let response = contract_methods\n        .take_struct_inside_enum(struct_inside_enum)\n        .call()\n        .await?;\n    assert_eq!(response.value, 8888);\n\n    // Enum inside enum\n    let expected_enum = EnumLevel3::El2(EnumLevel2::El1(EnumLevel1::Num(42)));\n    let response = contract_methods.get_nested_enum().call().await?;\n    assert_eq!(response.value, expected_enum);\n\n    let response = contract_methods\n        .check_nested_enum_integrity(expected_enum)\n        .call()\n        .await?;\n    assert!(\n        response.value,\n        \"The FuelVM deems that we've not encoded the nested enum correctly. Investigate!\"\n    );\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_rust_option_can_be_decoded() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TypesContract\",\n            project = \"e2e/sway/types/contracts/options\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TypesContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n    let contract_methods = contract_instance.methods();\n\n    let expected_address =\n        Address::from_str(\"0xd58573593432a30a800f97ad32f877425c223a9e427ab557aab5d5bb89156db0\")?;\n\n    let s = TestStruct {\n        option: Some(expected_address),\n    };\n\n    let e = TestEnum::EnumOption(Some(expected_address));\n\n    let expected_some_address = Some(expected_address);\n    let response = contract_methods.get_some_address().call().await?;\n\n    assert_eq!(response.value, expected_some_address);\n\n    let expected_some_u64 = Some(10);\n    let response = contract_methods.get_some_u64().call().await?;\n\n    assert_eq!(response.value, expected_some_u64);\n\n    let response = contract_methods.get_some_struct().call().await?;\n    assert_eq!(response.value, Some(s.clone()));\n\n    let response = contract_methods.get_some_enum().call().await?;\n    assert_eq!(response.value, Some(e.clone()));\n\n    let response = contract_methods.get_some_tuple().call().await?;\n    assert_eq!(response.value, Some((s.clone(), e.clone())));\n\n    let expected_none = None;\n    let response = contract_methods.get_none().call().await?;\n\n    assert_eq!(response.value, expected_none);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_rust_option_can_be_encoded() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TypesContract\",\n            project = \"e2e/sway/types/contracts/options\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TypesContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n    let contract_methods = contract_instance.methods();\n\n    let expected_address =\n        Address::from_str(\"0xd58573593432a30a800f97ad32f877425c223a9e427ab557aab5d5bb89156db0\")?;\n\n    let s = TestStruct {\n        option: Some(expected_address),\n    };\n\n    let e = TestEnum::EnumOption(Some(expected_address));\n\n    let expected_u64 = Some(36);\n    let response = contract_methods\n        .input_primitive(expected_u64)\n        .call()\n        .await?;\n\n    assert!(response.value);\n\n    let expected_struct = Some(s);\n    let response = contract_methods\n        .input_struct(expected_struct)\n        .call()\n        .await?;\n\n    assert!(response.value);\n\n    let expected_enum = Some(e);\n    let response = contract_methods.input_enum(expected_enum).call().await?;\n\n    assert!(response.value);\n\n    let expected_none = None;\n    let response = contract_methods.input_none(expected_none).call().await?;\n\n    assert!(response.value);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_rust_result_can_be_decoded() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TypesContract\",\n            project = \"e2e/sway/types/contracts/results\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TypesContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n    let contract_methods = contract_instance.methods();\n\n    let expected_address =\n        Address::from_str(\"0xd58573593432a30a800f97ad32f877425c223a9e427ab557aab5d5bb89156db0\")?;\n\n    let s = TestStruct {\n        option: Some(expected_address),\n    };\n\n    let e = TestEnum::EnumOption(Some(expected_address));\n\n    let expected_ok_address = Ok(expected_address);\n    let response = contract_methods.get_ok_address().call().await?;\n\n    assert_eq!(response.value, expected_ok_address);\n\n    let expected_some_u64 = Ok(10);\n    let response = contract_methods.get_ok_u64().call().await?;\n\n    assert_eq!(response.value, expected_some_u64);\n\n    let response = contract_methods.get_ok_struct().call().await?;\n    assert_eq!(response.value, Ok(s.clone()));\n\n    let response = contract_methods.get_ok_enum().call().await?;\n    assert_eq!(response.value, Ok(e.clone()));\n\n    let response = contract_methods.get_ok_tuple().call().await?;\n    assert_eq!(response.value, Ok((s, e)));\n\n    let expected_error = Err(TestError::NoAddress(\"error\".try_into().unwrap()));\n    let response = contract_methods.get_error().call().await?;\n\n    assert_eq!(response.value, expected_error);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_rust_result_can_be_encoded() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TypesContract\",\n            project = \"e2e/sway/types/contracts/results\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TypesContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n    let contract_methods = contract_instance.methods();\n\n    let expected_address =\n        Address::from_str(\"0xd58573593432a30a800f97ad32f877425c223a9e427ab557aab5d5bb89156db0\")?;\n\n    let expected_ok_address = Ok(expected_address);\n    let response = contract_methods\n        .input_ok(expected_ok_address)\n        .call()\n        .await?;\n\n    assert!(response.value);\n\n    let expected_error = Err(TestError::NoAddress(\"error\".try_into().unwrap()));\n    let response = contract_methods.input_error(expected_error).call().await?;\n\n    assert!(response.value);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_identity_can_be_decoded() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TypesContract\",\n            project = \"e2e/sway/types/contracts/identity\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TypesContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n    let contract_methods = contract_instance.methods();\n\n    let expected_address =\n        Address::from_str(\"0xd58573593432a30a800f97ad32f877425c223a9e427ab557aab5d5bb89156db0\")?;\n    let expected_contract_id =\n        ContractId::from_str(\"0xd58573593432a30a800f97ad32f877425c223a9e427ab557aab5d5bb89156db0\")?;\n\n    let s = TestStruct {\n        identity: Identity::Address(expected_address),\n    };\n\n    let e = TestEnum::EnumIdentity(Identity::ContractId(expected_contract_id));\n\n    let response = contract_methods.get_identity_address().call().await?;\n    assert_eq!(response.value, Identity::Address(expected_address));\n\n    let response = contract_methods.get_identity_contract_id().call().await?;\n    assert_eq!(response.value, Identity::ContractId(expected_contract_id));\n\n    let response = contract_methods.get_struct_with_identity().call().await?;\n    assert_eq!(response.value, s.clone());\n\n    let response = contract_methods.get_enum_with_identity().call().await?;\n    assert_eq!(response.value, e.clone());\n\n    let response = contract_methods.get_identity_tuple().call().await?;\n    assert_eq!(response.value, (s, e));\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_identity_can_be_encoded() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TypesContract\",\n            project = \"e2e/sway/types/contracts/identity\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TypesContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n    let contract_methods = contract_instance.methods();\n\n    let expected_address =\n        Address::from_str(\"0xd58573593432a30a800f97ad32f877425c223a9e427ab557aab5d5bb89156db0\")?;\n    let expected_contract_id =\n        ContractId::from_str(\"0xd58573593432a30a800f97ad32f877425c223a9e427ab557aab5d5bb89156db0\")?;\n\n    let s = TestStruct {\n        identity: Identity::Address(expected_address),\n    };\n\n    let e = TestEnum::EnumIdentity(Identity::ContractId(expected_contract_id));\n\n    let response = contract_methods\n        .input_identity(Identity::Address(expected_address))\n        .call()\n        .await?;\n\n    assert!(response.value);\n\n    let response = contract_methods\n        .input_struct_with_identity(s)\n        .call()\n        .await?;\n\n    assert!(response.value);\n\n    let response = contract_methods.input_enum_with_identity(e).call().await?;\n\n    assert!(response.value);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_identity_with_two_contracts() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TypesContract\",\n            project = \"e2e/sway/types/contracts/identity\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TypesContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n        Deploy(\n            name = \"contract_instance2\",\n            contract = \"TypesContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    let expected_address =\n        Address::from_str(\"0xd58573593432a30a800f97ad32f877425c223a9e427ab557aab5d5bb89156db0\")?;\n\n    {\n        let response = contract_instance\n            .methods()\n            .input_identity(Identity::Address(expected_address))\n            .call()\n            .await?;\n\n        assert!(response.value);\n    }\n    {\n        let response = contract_instance2\n            .methods()\n            .input_identity(Identity::Address(expected_address))\n            .call()\n            .await?;\n\n        assert!(response.value);\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn generics_test() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TypesContract\",\n            project = \"e2e/sway/types/contracts/generics\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TypesContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n    let contract_methods = contract_instance.methods();\n\n    {\n        // ANCHOR: generic\n        // simple struct with a single generic param\n        let arg1 = SimpleGeneric {\n            single_generic_param: 123u64,\n        };\n\n        let result = contract_methods\n            .struct_w_generic(arg1.clone())\n            .call()\n            .await?\n            .value;\n\n        assert_eq!(result, arg1);\n        // ANCHOR_END: generic\n    }\n    {\n        // struct that delegates the generic param internally\n        let arg1 = PassTheGenericOn {\n            one: SimpleGeneric {\n                single_generic_param: \"abc\".try_into()?,\n            },\n        };\n\n        let result = contract_methods\n            .struct_delegating_generic(arg1.clone())\n            .call()\n            .await?\n            .value;\n\n        assert_eq!(result, arg1);\n    }\n    {\n        // struct that has the generic in an array\n        let arg1 = StructWArrayGeneric { a: [1u32, 2u32] };\n\n        let result = contract_methods\n            .struct_w_generic_in_array(arg1.clone())\n            .call()\n            .await?\n            .value;\n\n        assert_eq!(result, arg1);\n    }\n    {\n        // struct that has a generic struct in an array\n        let inner = [\n            StructWTwoGenerics {\n                a: Bits256([1u8; 32]),\n                b: 1,\n            },\n            StructWTwoGenerics {\n                a: Bits256([2u8; 32]),\n                b: 2,\n            },\n            StructWTwoGenerics {\n                a: Bits256([3u8; 32]),\n                b: 3,\n            },\n        ];\n        let arg1 = StructWArrWGenericStruct { a: inner };\n\n        let result = contract_methods\n            .array_with_generic_struct(arg1.clone())\n            .call()\n            .await?\n            .value;\n\n        assert_eq!(result, arg1);\n    }\n    {\n        // struct that has the generic in a tuple\n        let arg1 = StructWTupleGeneric { a: (1, 2) };\n\n        let result = contract_methods\n            .struct_w_generic_in_tuple(arg1.clone())\n            .call()\n            .await?\n            .value;\n\n        assert_eq!(result, arg1);\n    }\n    {\n        // enum with generic in variant\n        let arg1 = EnumWGeneric::B(10);\n        let result = contract_methods\n            .enum_w_generic(arg1.clone())\n            .call()\n            .await?\n            .value;\n\n        assert_eq!(result, arg1);\n    }\n    {\n        contract_methods\n            .unused_generic_args(StructUnusedGeneric::new(15), EnumUnusedGeneric::One(15))\n            .call()\n            .await?;\n\n        let (the_struct, the_enum) = contract_methods\n            .used_and_unused_generic_args(\n                StructUsedAndUnusedGenericParams::new(10u8),\n                EnumUsedAndUnusedGenericParams::Two(11u8),\n            )\n            .call()\n            .await?\n            .value;\n\n        assert_eq!(the_struct.field, 12u8);\n        if let EnumUsedAndUnusedGenericParams::Two(val) = the_enum {\n            assert_eq!(val, 13)\n        } else {\n            panic!(\"Expected the variant EnumUsedAndUnusedGenericParams::Two\");\n        }\n    }\n    {\n        // complex case\n        let pass_through = PassTheGenericOn {\n            one: SimpleGeneric {\n                single_generic_param: \"ab\".try_into()?,\n            },\n        };\n        let w_arr_generic = StructWArrayGeneric {\n            a: [pass_through.clone(), pass_through],\n        };\n\n        let arg1 = MegaExample {\n            a: ([Bits256([0; 32]), Bits256([0; 32])], \"ab\".try_into()?),\n            b: vec![(\n                [EnumWGeneric::B(StructWTupleGeneric {\n                    a: (w_arr_generic.clone(), w_arr_generic),\n                })],\n                10u32,\n            )],\n        };\n        contract_methods.complex_test(arg1.clone()).call().await?;\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn contract_vectors() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TypesContract\",\n            project = \"e2e/sway/types/contracts/vectors\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TypesContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n    let methods = contract_instance.methods();\n\n    {\n        // vec of u32s\n        let arg = vec![0, 1, 2];\n        methods.u32_vec(arg).call().await?;\n    }\n    {\n        // vec of vecs of u32s\n        let arg = vec![vec![0, 1, 2], vec![0, 1, 2]];\n        methods.vec_in_vec(arg.clone()).call().await?;\n    }\n    {\n        // vec of structs\n        // ANCHOR: passing_in_vec\n        let arg = vec![SomeStruct { a: 0 }, SomeStruct { a: 1 }];\n        methods.struct_in_vec(arg.clone()).call().await?;\n        // ANCHOR_END: passing_in_vec\n    }\n    {\n        // vec in struct\n        let arg = SomeStruct { a: vec![0, 1, 2] };\n        methods.vec_in_struct(arg.clone()).call().await?;\n    }\n    {\n        // array in vec\n        let arg = vec![[0u64, 1u64], [0u64, 1u64]];\n        methods.array_in_vec(arg.clone()).call().await?;\n    }\n    {\n        // vec in array\n        let arg = [vec![0, 1, 2], vec![0, 1, 2]];\n        methods.vec_in_array(arg.clone()).call().await?;\n    }\n    {\n        // vec in enum\n        let arg = SomeEnum::a(vec![0, 1, 2]);\n        methods.vec_in_enum(arg.clone()).call().await?;\n    }\n    {\n        // enum in vec\n        let arg = vec![SomeEnum::a(0), SomeEnum::a(1)];\n        methods.enum_in_vec(arg.clone()).call().await?;\n    }\n    {\n        // tuple in vec\n        let arg = vec![(0, 0), (1, 1)];\n        methods.tuple_in_vec(arg.clone()).call().await?;\n    }\n    {\n        // vec in tuple\n        let arg = (vec![0, 1, 2], vec![0, 1, 2]);\n        methods.vec_in_tuple(arg.clone()).call().await?;\n    }\n    {\n        // vec in a vec in a struct in a vec\n        let arg = vec![\n            SomeStruct {\n                a: vec![vec![0, 1, 2], vec![3, 4, 5]],\n            },\n            SomeStruct {\n                a: vec![vec![6, 7, 8], vec![9, 10, 11]],\n            },\n        ];\n        methods\n            .vec_in_a_vec_in_a_struct_in_a_vec(arg.clone())\n            .call()\n            .await?;\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_b256() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TypesContract\",\n            project = \"e2e/sway/types/contracts/b256\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TypesContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    assert_eq!(\n        Bits256([2; 32]),\n        contract_instance\n            .methods()\n            .b256_as_output()\n            .call()\n            .await?\n            .value\n    );\n\n    {\n        // ANCHOR: 256_arg\n        let b256 = Bits256([1; 32]);\n\n        let call_handler = contract_instance.methods().b256_as_input(b256);\n        // ANCHOR_END: 256_arg\n\n        assert!(call_handler.call().await?.value);\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_b512() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TypesContract\",\n            project = \"e2e/sway/types/contracts/b512\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TypesContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n    let contract_methods = contract_instance.methods();\n\n    // ANCHOR: b512_example\n    let hi_bits = Bits256::from_hex_str(\n        \"0xbd0c9b8792876713afa8bff383eebf31c43437823ed761cc3600d0016de5110c\",\n    )?;\n    let lo_bits = Bits256::from_hex_str(\n        \"0x44ac566bd156b4fc71a4a4cb2655d3dd360c695edb17dc3b64d611e122fea23d\",\n    )?;\n    let b512 = B512::from((hi_bits, lo_bits));\n    // ANCHOR_END: b512_example\n\n    assert_eq!(b512, contract_methods.b512_as_output().call().await?.value);\n\n    {\n        let lo_bits2 = Bits256::from_hex_str(\n            \"0x54ac566bd156b4fc71a4a4cb2655d3dd360c695edb17dc3b64d611e122fea23d\",\n        )?;\n        let b512 = B512::from((hi_bits, lo_bits2));\n\n        assert!(contract_methods.b512_as_input(b512).call().await?.value);\n    }\n\n    Ok(())\n}\n\nfn u128_from(parts: (u64, u64)) -> u128 {\n    let bytes: [u8; 16] = [parts.0.to_be_bytes(), parts.1.to_be_bytes()]\n        .concat()\n        .try_into()\n        .unwrap();\n    u128::from_be_bytes(bytes)\n}\n\n#[tokio::test]\nasync fn test_u128() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TypesContract\",\n            project = \"e2e/sway/types/contracts/u128\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TypesContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n    let contract_methods = contract_instance.methods();\n    {\n        let arg = u128_from((1, 2));\n\n        let actual = contract_methods.u128_sum_and_ret(arg).call().await?.value;\n\n        let expected = arg + u128_from((3, 4));\n\n        assert_eq!(expected, actual);\n    }\n    {\n        let actual = contract_methods.u128_in_enum_output().call().await?.value;\n\n        let expected = SomeEnum::B(u128_from((4, 4)));\n        assert_eq!(expected, actual);\n    }\n    {\n        let input = SomeEnum::B(u128_from((3, 3)));\n\n        contract_methods.u128_in_enum_input(input).call().await?;\n    }\n\n    Ok(())\n}\n\nfn u256_from(parts: (u64, u64, u64, u64)) -> U256 {\n    let bytes: [u8; 32] = [\n        parts.0.to_be_bytes(),\n        parts.1.to_be_bytes(),\n        parts.2.to_be_bytes(),\n        parts.3.to_be_bytes(),\n    ]\n    .concat()\n    .try_into()\n    .unwrap();\n    U256::from(bytes)\n}\n\n#[tokio::test]\nasync fn test_u256() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"TypesContract\",\n            project = \"e2e/sway/types/contracts/u256\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"TypesContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n    let contract_methods = contract_instance.methods();\n    {\n        let arg = u256_from((1, 2, 3, 4));\n        let actual = contract_methods.u256_sum_and_ret(arg).call().await?.value;\n        let expected = arg + u256_from((3, 4, 5, 6));\n\n        assert_eq!(expected, actual);\n    }\n    {\n        let actual = contract_methods.u256_in_enum_output().call().await?.value;\n        let expected = SomeEnum::B(u256_from((1, 2, 3, 4)));\n\n        assert_eq!(expected, actual);\n    }\n    {\n        let input = SomeEnum::B(u256_from((2, 3, 4, 5)));\n\n        contract_methods.u256_in_enum_input(input).call().await?;\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_base_type_in_vec_output() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"VectorOutputContract\",\n            project = \"e2e/sway/types/contracts/vector_output\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"VectorOutputContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n    let contract_methods = contract_instance.methods();\n\n    // ANCHOR: returning_vec\n    let response = contract_methods.u8_in_vec(10).call().await?;\n    assert_eq!(response.value, (0..10).collect::<Vec<_>>());\n    // ANCHOR_END: returning_vec\n\n    let response = contract_methods.u16_in_vec(11).call().await?;\n    assert_eq!(response.value, (0..11).collect::<Vec<_>>());\n\n    let response = contract_methods.u32_in_vec(12).call().await?;\n    assert_eq!(response.value, (0..12).collect::<Vec<_>>());\n\n    let response = contract_methods.u64_in_vec(13).call().await?;\n    assert_eq!(response.value, (0..13).collect::<Vec<_>>());\n\n    let response = contract_methods.bool_in_vec().call().await?;\n    assert_eq!(response.value, [true, false, true, false].to_vec());\n\n    let response = contract_methods.b256_in_vec(13).call().await?;\n    assert_eq!(response.value, vec![Bits256([2; 32]); 13]);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_composite_types_in_vec_output() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"VectorOutputContract\",\n            project = \"e2e/sway/types/contracts/vector_output\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"VectorOutputContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n    let contract_methods = contract_instance.methods();\n\n    {\n        let expected: Vec<[u64; 4]> = vec![[1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3], [4, 4, 4, 4]];\n        let response = contract_methods.array_in_vec().call().await?.value;\n        assert_eq!(response, expected);\n    }\n    {\n        let expected: Vec<Pasta> = vec![\n            Pasta::Tortelini(Bimbam {\n                bim: 1111,\n                bam: 2222_u32,\n            }),\n            Pasta::Rigatoni(1987),\n            Pasta::Spaghetti(true),\n        ];\n\n        let response = contract_methods.enum_in_vec().call().await?.value;\n        assert_eq!(response, expected);\n    }\n\n    {\n        let expected: Vec<Bimbam> = vec![\n            Bimbam {\n                bim: 1111,\n                bam: 2222_u32,\n            },\n            Bimbam {\n                bim: 3333,\n                bam: 4444_u32,\n            },\n            Bimbam {\n                bim: 5555,\n                bam: 6666_u32,\n            },\n        ];\n        let response = contract_methods.struct_in_vec().call().await?.value;\n        assert_eq!(response, expected);\n    }\n\n    {\n        let expected: Vec<(u64, u32)> = vec![(1111, 2222_u32), (3333, 4444_u32), (5555, 6666_u32)];\n        let response = contract_methods.tuple_in_vec().call().await?.value;\n        assert_eq!(response, expected);\n    }\n\n    {\n        let expected: Vec<SizedAsciiString<4>> =\n            vec![\"hell\".try_into()?, \"ello\".try_into()?, \"lloh\".try_into()?];\n        let response = contract_methods.str_in_vec().call().await?.value;\n        assert_eq!(response, expected);\n    }\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_bytes_output() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"BytesOutputContract\",\n            project = \"e2e/sway/types/contracts/bytes\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"BytesOutputContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    let contract_methods = contract_instance.methods();\n    let response = contract_methods.return_bytes(10).call().await?;\n\n    assert_eq!(response.value, (0..10).collect::<Vec<_>>());\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_bytes_as_input() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"BytesInputContract\",\n            project = \"e2e/sway/types/contracts/bytes\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"BytesInputContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n    let contract_methods = contract_instance.methods();\n\n    {\n        // ANCHOR: bytes_arg\n        let bytes = Bytes(vec![40, 41, 42]);\n\n        contract_methods.accept_bytes(bytes).call().await?;\n        // ANCHOR_END: bytes_arg\n    }\n    {\n        let bytes = Bytes(vec![40, 41, 42]);\n        let wrapper = Wrapper {\n            inner: vec![bytes.clone(), bytes.clone()],\n            inner_enum: SomeEnum::Second(bytes),\n        };\n\n        contract_methods.accept_nested_bytes(wrapper).call().await?;\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn contract_raw_slice() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"RawSliceContract\",\n            project = \"e2e/sway/types/contracts/raw_slice\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"RawSliceContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    let contract_methods = contract_instance.methods();\n\n    {\n        for length in 0u8..=10 {\n            let response = contract_methods.return_raw_slice(length).call().await?;\n            assert_eq!(response.value, (0u8..length).collect::<Vec<u8>>());\n        }\n    }\n    {\n        contract_methods\n            .accept_raw_slice(RawSlice(vec![40, 41, 42]))\n            .call()\n            .await?;\n    }\n    {\n        let raw_slice = RawSlice(vec![40, 41, 42]);\n        let wrapper = Wrapper {\n            inner: vec![raw_slice.clone(), raw_slice.clone()],\n            inner_enum: SomeEnum::Second(raw_slice),\n        };\n\n        contract_methods\n            .accept_nested_raw_slice(wrapper)\n            .call()\n            .await?;\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn contract_string_slice() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"StringSliceContract\",\n            project = \"e2e/sway/types/contracts/string_slice\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"StringSliceContract\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    let contract_methods = contract_instance.methods();\n\n    let response = contract_methods\n        .handles_str(\"contract-input\".try_into()?)\n        .call()\n        .await?;\n    assert_eq!(response.value, \"contract-return\");\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn contract_std_lib_string() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"StdLibString\",\n            project = \"e2e/sway/types/contracts/std_lib_string\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"StdLibString\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n    let contract_methods = contract_instance.methods();\n\n    {\n        let resp = contract_methods.return_dynamic_string().call().await?.value;\n        assert_eq!(resp, \"Hello World\");\n    }\n    {\n        let _resp = contract_methods\n            .accepts_dynamic_string(String::from(\"Hello World\"))\n            .call()\n            .await?;\n    }\n    {\n        // confirm encoding/decoding a string wasn't faulty and led to too high gas consumption\n        let _resp = contract_methods\n            .echoes_dynamic_string(String::from(\"Hello Fuel\"))\n            .with_tx_policies(TxPolicies::default().with_script_gas_limit(3600))\n            .call()\n            .await?;\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_heap_type_in_enums() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"HeapTypeInEnum\",\n            project = \"e2e/sway/types/contracts/heap_type_in_enums\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"HeapTypeInEnum\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n    let contract_methods = contract_instance.methods();\n\n    {\n        let resp = contract_methods.returns_bytes_result(true).call().await?;\n        let expected = Ok(Bytes(vec![1, 1, 1, 1]));\n\n        assert_eq!(resp.value, expected);\n    }\n    {\n        let resp = contract_methods.returns_bytes_result(false).call().await?;\n        let expected = Err(TestError::Something([255u8, 255u8, 255u8, 255u8, 255u8]));\n\n        assert_eq!(resp.value, expected);\n    }\n    {\n        let resp = contract_methods.returns_vec_result(true).call().await?;\n        let expected = Ok(vec![2, 2, 2, 2, 2]);\n\n        assert_eq!(resp.value, expected);\n    }\n    {\n        let resp = contract_methods.returns_vec_result(false).call().await?;\n        let expected = Err(TestError::Else(7777));\n\n        assert_eq!(resp.value, expected);\n    }\n    {\n        let resp = contract_methods.returns_string_result(true).call().await?;\n        let expected = Ok(\"Hello World\".to_string());\n\n        assert_eq!(resp.value, expected);\n    }\n    {\n        let resp = contract_methods.returns_string_result(false).call().await?;\n        let expected = Err(TestError::Else(3333));\n\n        assert_eq!(resp.value, expected);\n    }\n    {\n        let resp = contract_methods.returns_str_result(true).call().await?;\n        let expected = Ok(\"Hello World\".try_into()?);\n\n        assert_eq!(resp.value, expected);\n    }\n    {\n        let resp = contract_methods.returns_string_result(false).call().await?;\n        let expected = Err(TestError::Else(3333));\n\n        assert_eq!(resp.value, expected);\n    }\n    {\n        let resp = contract_methods.returns_bytes_option(true).call().await?;\n        let expected = Some(Bytes(vec![1, 1, 1, 1]));\n\n        assert_eq!(resp.value, expected);\n    }\n    {\n        let resp = contract_methods.returns_bytes_option(false).call().await?;\n\n        assert!(resp.value.is_none());\n    }\n    {\n        let resp = contract_methods.returns_vec_option(true).call().await?;\n        let expected = Some(vec![2, 2, 2, 2, 2]);\n\n        assert_eq!(resp.value, expected);\n    }\n    {\n        let resp = contract_methods.returns_vec_option(false).call().await?;\n\n        assert!(resp.value.is_none());\n    }\n    {\n        let resp = contract_methods.returns_string_option(true).call().await?;\n        let expected = Some(\"Hello World\".to_string());\n\n        assert_eq!(resp.value, expected);\n    }\n    {\n        let resp = contract_methods.returns_string_option(false).call().await?;\n\n        assert!(resp.value.is_none());\n    }\n    {\n        let resp = contract_methods.returns_str_option(true).call().await?;\n        let expected = Some(\"Hello World\".try_into()?);\n\n        assert_eq!(resp.value, expected);\n    }\n    {\n        let resp = contract_methods.returns_string_option(false).call().await?;\n\n        assert!(resp.value.is_none());\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn nested_heap_types() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Contract(\n            name = \"HeapTypeInEnum\",\n            project = \"e2e/sway/types/contracts/heap_types\"\n        )),\n        Deploy(\n            name = \"contract_instance\",\n            contract = \"HeapTypeInEnum\",\n            wallet = \"wallet\",\n            random_salt = false,\n        ),\n    );\n\n    let arr = [2u8, 4, 8];\n    let struct_generics = StructGenerics {\n        one: Bytes(arr.to_vec()),\n        two: String::from(\"fuel\"),\n        three: RawSlice(arr.to_vec()),\n    };\n\n    let enum_vec = [struct_generics.clone(), struct_generics].to_vec();\n    let expected = EnumGeneric::One(enum_vec);\n\n    let result = contract_instance\n        .methods()\n        .nested_heap_types()\n        .call()\n        .await?;\n\n    assert_eq!(result.value, expected);\n\n    Ok(())\n}\n"
  },
  {
    "path": "e2e/tests/types_predicates.rs",
    "content": "use std::{default::Default, path::Path};\n\nuse fuels::{\n    accounts::{Account, predicate::Predicate, signers::private_key::PrivateKeySigner},\n    prelude::*,\n    types::{AssetId, Bits256, U256, coin::Coin, message::Message},\n};\n\nasync fn assert_predicate_spendable(data: Vec<u8>, project_path: impl AsRef<Path>) -> Result<()> {\n    let binary_path = project_binary(project_path);\n    let mut predicate: Predicate = Predicate::load_from(&binary_path)?.with_data(data);\n\n    let num_coins = 4;\n    let num_messages = 8;\n    let amount = 16;\n    let (provider, predicate_balance, receiver, receiver_balance, asset_id) =\n        setup_predicate_test(predicate.address(), num_coins, num_messages, amount).await?;\n\n    predicate.set_provider(provider.clone());\n\n    let amount_to_send = 136;\n    let fee = predicate\n        .transfer(\n            receiver.address(),\n            amount_to_send,\n            asset_id,\n            TxPolicies::default(),\n        )\n        .await?\n        .tx_status\n        .total_fee;\n\n    // The predicate has spent the funds\n    assert_address_balance(\n        &predicate.address(),\n        &provider,\n        &asset_id,\n        predicate_balance - amount_to_send - fee,\n    )\n    .await;\n\n    // Funds were transferred\n    assert_address_balance(\n        &receiver.address(),\n        &provider,\n        &asset_id,\n        receiver_balance + amount_to_send,\n    )\n    .await;\n\n    Ok(())\n}\n\nfn project_binary(project_root: impl AsRef<Path>) -> String {\n    let project_root = project_root.as_ref();\n\n    let project_name = project_root\n        .file_name()\n        .expect(\"Couldn't extract project name\")\n        .to_str()\n        .unwrap();\n\n    project_root\n        .join(format!(\"out/release/{project_name}.bin\"))\n        .display()\n        .to_string()\n}\n\nasync fn assert_address_balance(\n    address: &Address,\n    provider: &Provider,\n    asset_id: &AssetId,\n    amount: u64,\n) {\n    let balance = provider\n        .get_asset_balance(address, asset_id)\n        .await\n        .expect(\"Could not retrieve balance\");\n    assert_eq!(balance, amount as u128);\n}\n\nfn get_test_coins_and_messages(\n    address: Address,\n    num_coins: u64,\n    num_messages: u64,\n    amount: u64,\n) -> (Vec<Coin>, Vec<Message>, AssetId) {\n    let asset_id = AssetId::zeroed();\n    let coins = setup_single_asset_coins(address, asset_id, num_coins, amount);\n    let messages = (0..num_messages)\n        .map(|i| setup_single_message(Address::default(), address, amount, i.into(), vec![]))\n        .collect();\n\n    (coins, messages, asset_id)\n}\n\n// Setup function used to assign coins and messages to a predicate address\n// and create a `receiver` wallet\nasync fn setup_predicate_test(\n    predicate_address: Address,\n    num_coins: u64,\n    num_messages: u64,\n    amount: u64,\n) -> Result<(Provider, u64, Wallet, u64, AssetId)> {\n    let receiver_num_coins = 1;\n    let receiver_amount = 1;\n    let receiver_balance = receiver_num_coins * receiver_amount;\n\n    let predicate_balance = (num_coins + num_messages) * amount;\n    let receiver_signer = PrivateKeySigner::random(&mut rand::thread_rng());\n\n    let (mut coins, messages, asset_id) =\n        get_test_coins_and_messages(predicate_address, num_coins, num_messages, amount);\n\n    coins.extend(setup_single_asset_coins(\n        receiver_signer.address(),\n        asset_id,\n        receiver_num_coins,\n        receiver_amount,\n    ));\n\n    let node_config = NodeConfig {\n        starting_gas_price: 0,\n        ..Default::default()\n    };\n    let provider = setup_test_provider(coins, messages, Some(node_config), None).await?;\n    let receiver = Wallet::new(receiver_signer, provider.clone());\n\n    Ok((\n        provider,\n        predicate_balance,\n        receiver,\n        receiver_balance,\n        asset_id,\n    ))\n}\n\n#[tokio::test]\nasync fn spend_predicate_coins_messages_single_u64() -> Result<()> {\n    abigen!(Predicate(\n        name = \"MyPredicate\",\n        abi = \"e2e/sway/types/predicates/u64/out/release/u64-abi.json\"\n    ));\n\n    let data = MyPredicateEncoder::default().encode_data(32768)?;\n\n    assert_predicate_spendable(data, \"sway/types/predicates/u64\").await?;\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn spend_predicate_coins_messages_address() -> Result<()> {\n    abigen!(Predicate(\n        name = \"MyPredicate\",\n        abi = \"e2e/sway/types/predicates/address/out/release/address-abi.json\"\n    ));\n\n    let addr: Address =\n        \"0xef86afa9696cf0dc6385e2c407a6e159a1103cefb7e2ae0636fb33d3cb2a9e4a\".parse()?;\n\n    let data = MyPredicateEncoder::default().encode_data(addr)?;\n\n    assert_predicate_spendable(data, \"sway/types/predicates/address\").await?;\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn spend_predicate_coins_messages_enums() -> Result<()> {\n    abigen!(Predicate(\n        name = \"MyPredicate\",\n        abi = \"e2e/sway/types/predicates/enums/out/release/enums-abi.json\"\n    ));\n\n    let data =\n        MyPredicateEncoder::default().encode_data(TestEnum::A(32), AnotherTestEnum::B(32))?;\n\n    assert_predicate_spendable(data, \"sway/types/predicates/enums\").await?;\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn spend_predicate_coins_messages_structs() -> Result<()> {\n    abigen!(Predicate(\n        name = \"MyPredicate\",\n        abi = \"e2e/sway/types/predicates/structs/out/release/structs-abi.json\"\n    ));\n\n    let data = MyPredicateEncoder::default().encode_data(\n        TestStruct { value: 192 },\n        AnotherTestStruct {\n            value: 64,\n            number: 128,\n        },\n    )?;\n\n    assert_predicate_spendable(data, \"sway/types/predicates/structs\").await?;\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn spend_predicate_coins_messages_tuple() -> Result<()> {\n    abigen!(Predicate(\n        name = \"MyPredicate\",\n        abi = \"e2e/sway/types/predicates/predicate_tuples/out/release/predicate_tuples-abi.json\"\n    ));\n\n    let data = MyPredicateEncoder::default()\n        .encode_data((16, TestStruct { value: 32 }, TestEnum::Value(64)), 128)?;\n\n    assert_predicate_spendable(data, \"sway/types/predicates/predicate_tuples\").await?;\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn spend_predicate_coins_messages_vector() -> Result<()> {\n    abigen!(Predicate(\n        name = \"MyPredicate\",\n        abi = \"e2e/sway/types/predicates/predicate_vector/out/release/predicate_vector-abi.json\"\n    ));\n\n    let data = MyPredicateEncoder::default().encode_data(18, 24, vec![2, 4, 42])?;\n\n    assert_predicate_spendable(data, \"sway/types/predicates/predicate_vector\").await?;\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn spend_predicate_coins_messages_vectors() -> Result<()> {\n    abigen!(Predicate(\n        name = \"MyPredicate\",\n        abi = \"e2e/sway/types/predicates/predicate_vectors/out/release/predicate_vectors-abi.json\"\n    ));\n\n    let u32_vec = vec![0, 4, 3];\n    let vec_in_vec = vec![vec![0, 2, 2], vec![0, 1, 2]];\n    let struct_in_vec = vec![SomeStruct { a: 8 }, SomeStruct { a: 1 }];\n    let vec_in_struct = SomeStruct { a: vec![0, 16, 2] };\n    let array_in_vec = vec![[0u64, 1u64], [32u64, 1u64]];\n    let vec_in_enum = SomeEnum::A(vec![0, 1, 128]);\n    let enum_in_vec = vec![SomeEnum::A(0), SomeEnum::A(16)];\n    let b256_in_vec = vec![Bits256([2; 32]), Bits256([2; 32])];\n    let tuple_in_vec = vec![(0, 0), (128, 1)];\n    let vec_in_tuple = (vec![0, 64, 2], vec![0, 1, 2]);\n    let vec_in_a_vec_in_a_struct_in_a_vec = vec![\n        SomeStruct {\n            a: vec![vec![0, 1, 2], vec![3, 4, 5]],\n        },\n        SomeStruct {\n            a: vec![vec![6, 7, 8], vec![9, 32, 11]],\n        },\n    ];\n\n    let vec_in_array = [vec![0, 64, 2], vec![0, 1, 2]];\n\n    let data = MyPredicateEncoder::default().encode_data(\n        u32_vec,\n        vec_in_vec,\n        struct_in_vec,\n        vec_in_struct,\n        array_in_vec,\n        vec_in_array,\n        vec_in_enum,\n        enum_in_vec,\n        b256_in_vec,\n        tuple_in_vec,\n        vec_in_tuple,\n        vec_in_a_vec_in_a_struct_in_a_vec,\n    )?;\n\n    assert_predicate_spendable(data, \"sway/types/predicates/predicate_vectors\").await?;\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn spend_predicate_coins_messages_generics() -> Result<()> {\n    abigen!(Predicate(\n        name = \"MyPredicate\",\n        abi =\n            \"e2e/sway/types/predicates/predicate_generics/out/release/predicate_generics-abi.json\"\n    ));\n\n    let data = MyPredicateEncoder::default().encode_data(\n        GenericStruct { value: 64u8 },\n        GenericEnum::Generic(GenericStruct { value: 64u16 }),\n    )?;\n\n    assert_predicate_spendable(data, \"sway/types/predicates/predicate_generics\").await?;\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn spend_predicate_coins_messages_bytes_hash() -> Result<()> {\n    abigen!(Predicate(\n        name = \"MyPredicate\",\n        abi = \"e2e/sway/types/predicates/predicate_bytes_hash/out/release/predicate_bytes_hash-abi.json\"\n    ));\n\n    let bytes = Bytes::from_hex_str(\n        \"0x75a448b91bb82a255757e61ba3eb7afe282c09842485268d4d72a027ec0cffc80500000000\",\n    )?;\n\n    let bits256 = Bits256::from_hex_str(\n        \"0x173d69ea3d0aa050d01ff7cc60ccd4579b567c465cd115c6876c2da4a332fb99\",\n    )?;\n\n    let data = MyPredicateEncoder::default().encode_data(bytes, bits256)?;\n\n    assert_predicate_spendable(data, \"sway/types/predicates/predicate_bytes_hash\").await?;\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn spend_predicate_coins_messages_bytes() -> Result<()> {\n    abigen!(Predicate(\n        name = \"MyPredicate\",\n        abi = \"e2e/sway/types/predicates/predicate_bytes/out/release/predicate_bytes-abi.json\"\n    ));\n\n    let bytes = Bytes(vec![40, 41, 42]);\n    let wrapper = Wrapper {\n        inner: vec![bytes.clone(), bytes.clone()],\n        inner_enum: SomeEnum::Second(bytes),\n    };\n\n    let data = MyPredicateEncoder::default().encode_data(wrapper)?;\n\n    assert_predicate_spendable(data, \"sway/types/predicates/predicate_bytes\").await?;\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn spend_predicate_coins_messages_raw_slice() -> Result<()> {\n    abigen!(Predicate(\n        name = \"MyPredicate\",\n        abi = \"e2e/sway/types/predicates/predicate_raw_slice/out/release/predicate_raw_slice-abi.json\"\n    ));\n\n    let raw_slice = RawSlice(vec![40, 41, 42]);\n    let wrapper = Wrapper {\n        inner: vec![raw_slice.clone(), raw_slice.clone()],\n        inner_enum: SomeEnum::Second(raw_slice),\n    };\n\n    let data = MyPredicateEncoder::default().encode_data(wrapper)?;\n\n    assert_predicate_spendable(data, \"sway/types/predicates/predicate_raw_slice\").await?;\n\n    Ok(())\n}\n\nfn u128_from(parts: (u64, u64)) -> u128 {\n    let bytes: [u8; 16] = [parts.0.to_be_bytes(), parts.1.to_be_bytes()]\n        .concat()\n        .try_into()\n        .unwrap();\n    u128::from_be_bytes(bytes)\n}\n\n#[tokio::test]\nasync fn predicate_handles_u128() -> Result<()> {\n    abigen!(Predicate(\n        name = \"MyPredicate\",\n        abi = \"e2e/sway/types/predicates/predicate_u128/out/release/predicate_u128-abi.json\"\n    ));\n\n    let data = MyPredicateEncoder::default().encode_data(u128_from((8, 2)))?;\n    assert_predicate_spendable(data, \"sway/types/predicates/predicate_u128\").await?;\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn predicate_handles_b256() -> Result<()> {\n    abigen!(Predicate(\n        name = \"MyPredicate\",\n        abi = \"e2e/sway/types/predicates/predicate_b256/out/release/predicate_b256-abi.json\"\n    ));\n\n    let data = MyPredicateEncoder::default().encode_data(Bits256([1; 32]))?;\n    assert_predicate_spendable(data, \"sway/types/predicates/predicate_b256\").await?;\n\n    Ok(())\n}\n\nfn u256_from(parts: (u64, u64, u64, u64)) -> U256 {\n    let bytes: [u8; 32] = [\n        parts.0.to_be_bytes(),\n        parts.1.to_be_bytes(),\n        parts.2.to_be_bytes(),\n        parts.3.to_be_bytes(),\n    ]\n    .concat()\n    .try_into()\n    .unwrap();\n    U256::from(bytes)\n}\n\n#[tokio::test]\nasync fn predicate_handles_u256() -> Result<()> {\n    abigen!(Predicate(\n        name = \"MyPredicate\",\n        abi = \"e2e/sway/types/predicates/predicate_u256/out/release/predicate_u256-abi.json\"\n    ));\n\n    let data = MyPredicateEncoder::default().encode_data(u256_from((10, 11, 12, 13)))?;\n    assert_predicate_spendable(data, \"sway/types/predicates/predicate_u256\").await?;\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn predicate_handles_std_string() -> Result<()> {\n    abigen!(Predicate(\n        name = \"MyPredicate\",\n        abi = \"e2e/sway/types/predicates/predicate_std_lib_string/out/release/predicate_std_lib_string-abi.json\"\n    ));\n\n    let data = MyPredicateEncoder::default().encode_data(10, 11, String::from(\"Hello World\"))?;\n    assert_predicate_spendable(data, \"sway/types/predicates/predicate_std_lib_string\").await?;\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn predicate_string_slice() -> Result<()> {\n    abigen!(Predicate(\n        name = \"MyPredicate\",\n        abi = \"e2e/sway/types/predicates/predicate_string_slice/out/release/predicate_string_slice-abi.json\"\n    ));\n\n    let data = MyPredicateEncoder::default().encode_data(\"predicate-input\".try_into()?)?;\n    assert_predicate_spendable(data, \"sway/types/predicates/predicate_string_slice\").await?;\n\n    Ok(())\n}\n"
  },
  {
    "path": "e2e/tests/types_scripts.rs",
    "content": "use fuels::{\n    prelude::*,\n    types::{Bits256, U256},\n};\n\n#[tokio::test]\nasync fn script_b256() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Script(\n            name = \"MyScript\",\n            project = \"e2e/sway/types/scripts/script_b256\"\n        )),\n        LoadScript(\n            name = \"script_instance\",\n            script = \"MyScript\",\n            wallet = \"wallet\"\n        )\n    );\n\n    let b256 = Bits256([1; 32]);\n    let response = script_instance.main(b256).call().await?;\n\n    assert_eq!(response.value, Bits256([2; 32]));\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn main_function_generic_arguments() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Script(\n            name = \"MyScript\",\n            project = \"e2e/sway/types/scripts/script_generics\"\n        )),\n        LoadScript(\n            name = \"script_instance\",\n            script = \"MyScript\",\n            wallet = \"wallet\"\n        )\n    );\n\n    let bim = GenericBimbam { val: 90 };\n    let bam_comp = GenericBimbam { val: 4342 };\n    let bam = GenericSnack {\n        twix: bam_comp,\n        mars: 1000,\n    };\n\n    let result = script_instance\n        .main(bim.clone(), bam.clone())\n        .call()\n        .await?;\n\n    let expected = (\n        GenericSnack {\n            twix: GenericBimbam {\n                val: bam.mars as u64,\n            },\n            mars: 2 * bim.val as u32,\n        },\n        GenericBimbam { val: 255_u8 },\n    );\n\n    assert_eq!(result.value, expected);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn main_function_option_result() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Script(\n            name = \"MyScript\",\n            project = \"e2e/sway/types/scripts/options_results\"\n        )),\n        LoadScript(\n            name = \"script_instance\",\n            script = \"MyScript\",\n            wallet = \"wallet\"\n        )\n    );\n    {\n        let result = script_instance.main(Some(42), None).call().await?;\n\n        assert_eq!(result.value, Ok(Some(true)));\n    }\n    {\n        let result = script_instance.main(Some(987), None).call().await?;\n\n        assert_eq!(result.value, Ok(None));\n    }\n    {\n        let expected_error = Err(TestError::ZimZam(\"error\".try_into().unwrap()));\n        let result = script_instance.main(None, Some(987)).call().await?;\n\n        assert_eq!(result.value, expected_error);\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn main_function_tuple_types() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Script(\n            name = \"MyScript\",\n            project = \"e2e/sway/types/scripts/script_tuples\"\n        )),\n        LoadScript(\n            name = \"script_instance\",\n            script = \"MyScript\",\n            wallet = \"wallet\"\n        )\n    );\n    let bim = Bim { bim: 90 };\n    let bam = Bam {\n        bam: \"itest\".try_into()?,\n    };\n    let boum = Boum { boum: true };\n\n    let result = script_instance\n        .main(\n            (bim, bam, boum),\n            Bam {\n                bam: \"twice\".try_into()?,\n            },\n        )\n        .call()\n        .await?;\n\n    let expected = (\n        (\n            Boum { boum: true },\n            Bim { bim: 193817 },\n            Bam {\n                bam: \"hello\".try_into()?,\n            },\n        ),\n        42242,\n    );\n    assert_eq!(result.value, expected);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn main_function_vector_arguments() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Script(\n            name = \"MyScript\",\n            project = \"e2e/sway/types/scripts/script_vectors\"\n        )),\n        LoadScript(\n            name = \"script_instance\",\n            script = \"MyScript\",\n            wallet = \"wallet\"\n        )\n    );\n\n    let u32_vec = vec![0, 1, 2];\n    let vec_in_vec = vec![vec![0, 1, 2], vec![0, 1, 2]];\n    let struct_in_vec = vec![SomeStruct { a: 0 }, SomeStruct { a: 1 }];\n    let vec_in_struct = SomeStruct { a: vec![0, 1, 2] };\n    let array_in_vec = vec![[0u64, 1u64], [0u64, 1u64]];\n    let vec_in_array = [vec![0, 1, 2], vec![0, 1, 2]];\n    let vec_in_enum = SomeEnum::a(vec![0, 1, 2]);\n    let enum_in_vec = vec![SomeEnum::a(0), SomeEnum::a(1)];\n    let b256_in_vec = vec![Bits256([2; 32]), Bits256([2; 32])];\n\n    let tuple_in_vec = vec![(0, 0), (1, 1)];\n    let vec_in_tuple = (vec![0, 1, 2], vec![0, 1, 2]);\n    let vec_in_a_vec_in_a_struct_in_a_vec = vec![\n        SomeStruct {\n            a: vec![vec![0, 1, 2], vec![3, 4, 5]],\n        },\n        SomeStruct {\n            a: vec![vec![6, 7, 8], vec![9, 10, 11]],\n        },\n    ];\n\n    let result = script_instance\n        .main(\n            u32_vec,\n            vec_in_vec,\n            struct_in_vec,\n            vec_in_struct,\n            array_in_vec,\n            vec_in_array,\n            vec_in_enum,\n            enum_in_vec,\n            b256_in_vec,\n            tuple_in_vec,\n            vec_in_tuple,\n            vec_in_a_vec_in_a_struct_in_a_vec,\n        )\n        .call()\n        .await?;\n\n    assert!(result.value);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn script_raw_slice() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Script(\n            name = \"BimBamScript\",\n            project = \"e2e/sway/types/scripts/script_raw_slice\",\n        )),\n        LoadScript(\n            name = \"script_instance\",\n            script = \"BimBamScript\",\n            wallet = \"wallet\"\n        )\n    );\n\n    let raw_slice = RawSlice(vec![40, 41, 42]);\n    let wrapper = Wrapper {\n        inner: vec![raw_slice.clone(), raw_slice.clone()],\n        inner_enum: SomeEnum::Second(raw_slice),\n    };\n\n    let rtn = script_instance.main(6, wrapper).call().await?.value;\n    assert_eq!(rtn, RawSlice(vec![0, 1, 2, 3, 4, 5]));\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn main_function_bytes_arguments() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Script(\n            name = \"BimBamScript\",\n            project = \"e2e/sway/types/scripts/script_bytes\",\n        )),\n        LoadScript(\n            name = \"script_instance\",\n            script = \"BimBamScript\",\n            wallet = \"wallet\"\n        )\n    );\n\n    let bytes = Bytes(vec![40, 41, 42]);\n    let wrapper = Wrapper {\n        inner: vec![bytes.clone(), bytes.clone()],\n        inner_enum: SomeEnum::Second(bytes),\n    };\n\n    script_instance.main(10, wrapper).call().await?;\n\n    Ok(())\n}\n\nfn u128_from(parts: (u64, u64)) -> u128 {\n    let bytes: [u8; 16] = [parts.0.to_be_bytes(), parts.1.to_be_bytes()]\n        .concat()\n        .try_into()\n        .unwrap();\n    u128::from_be_bytes(bytes)\n}\n\n#[tokio::test]\nasync fn script_handles_u128() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Script(\n            name = \"MyScript\",\n            project = \"e2e/sway/types/scripts/script_u128\",\n        )),\n        LoadScript(\n            name = \"script_instance\",\n            script = \"MyScript\",\n            wallet = \"wallet\"\n        )\n    );\n\n    let arg = u128_from((10, 20));\n    let actual = script_instance.main(arg).call().await?.value;\n\n    let expected = arg + u128_from((8, 2));\n    assert_eq!(expected, actual);\n\n    Ok(())\n}\n\nfn u256_from(parts: (u64, u64, u64, u64)) -> U256 {\n    let bytes: [u8; 32] = [\n        parts.0.to_be_bytes(),\n        parts.1.to_be_bytes(),\n        parts.2.to_be_bytes(),\n        parts.3.to_be_bytes(),\n    ]\n    .concat()\n    .try_into()\n    .unwrap();\n    U256::from(bytes)\n}\n\n#[tokio::test]\nasync fn script_handles_u256() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Script(\n            name = \"MyScript\",\n            project = \"e2e/sway/types/scripts/script_u256\",\n        )),\n        LoadScript(\n            name = \"script_instance\",\n            script = \"MyScript\",\n            wallet = \"wallet\"\n        )\n    );\n\n    let arg = u256_from((10, 20, 30, 40));\n    let actual = script_instance.main(arg).call().await?.value;\n\n    let expected = arg + u256_from((6, 7, 8, 9));\n    assert_eq!(expected, actual);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn script_std_string() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Script(\n            name = \"MyScript\",\n            project = \"e2e/sway/types/scripts/script_std_lib_string\",\n        )),\n        LoadScript(\n            name = \"script_instance\",\n            script = \"MyScript\",\n            wallet = \"wallet\"\n        )\n    );\n\n    let response = script_instance\n        .main(\"script-input\".to_string())\n        .call()\n        .await?;\n    assert_eq!(response.value, \"script-return\".to_string());\n\n    Ok(())\n}\n\n#[tokio::test]\n// TODO: Uncomment this test when we find the reason why it fails\n#[ignore]\nasync fn script_string_slice() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Script(\n            name = \"MyScript\",\n            project = \"e2e/sway/types/scripts/script_string_slice\",\n        )),\n        LoadScript(\n            name = \"script_instance\",\n            script = \"MyScript\",\n            wallet = \"wallet\"\n        )\n    );\n\n    let response = script_instance\n        .main(\"script-input\".try_into()?)\n        .call()\n        .await?;\n    assert_eq!(response.value, \"script-return\");\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn nested_heap_types() -> Result<()> {\n    setup_program_test!(\n        Wallets(\"wallet\"),\n        Abigen(Script(\n            name = \"MyScript\",\n            project = \"e2e/sway/types/scripts/script_heap_types\",\n        )),\n        LoadScript(\n            name = \"script_instance\",\n            script = \"MyScript\",\n            wallet = \"wallet\"\n        )\n    );\n\n    let arr = [2u8, 4, 8];\n    let struct_generics = StructGenerics {\n        one: Bytes(arr.to_vec()),\n        two: String::from(\"fuel\"),\n        three: arr.to_vec(),\n    };\n\n    let enum_vec = [struct_generics.clone(), struct_generics].to_vec();\n    let expected = EnumGeneric::One(enum_vec);\n\n    let result = script_instance.main().call().await?;\n\n    assert_eq!(result.value, expected);\n\n    Ok(())\n}\n"
  },
  {
    "path": "e2e/tests/wallets.rs",
    "content": "use fuels::{\n    accounts::signers::private_key::PrivateKeySigner,\n    prelude::*,\n    types::{coin_type::CoinType, input::Input, output::Output},\n};\nuse rand::{Rng, thread_rng};\n\nasync fn assert_address_balance(\n    address: &Address,\n    provider: &Provider,\n    asset_id: &AssetId,\n    amount: u128,\n) {\n    let balance = provider\n        .get_asset_balance(address, asset_id)\n        .await\n        .expect(\"Could not retrieve balance\");\n    assert_eq!(balance, amount);\n}\n\n#[tokio::test]\nasync fn test_wallet_balance_api_multi_asset() -> Result<()> {\n    let signer = PrivateKeySigner::random(&mut rand::thread_rng());\n    let number_of_assets = 7;\n    let coins_per_asset = 21;\n    let amount_per_coin = 11;\n    let (coins, asset_ids) = setup_multiple_assets_coins(\n        signer.address(),\n        number_of_assets,\n        coins_per_asset,\n        amount_per_coin,\n    );\n\n    let provider = setup_test_provider(coins.clone(), vec![], None, None).await?;\n    let wallet = Wallet::new(signer, provider.clone());\n    let balances = wallet.get_balances().await?;\n    assert_eq!(balances.len() as u64, number_of_assets);\n\n    for asset_id in asset_ids {\n        let balance = wallet.get_asset_balance(&asset_id).await?;\n        assert_eq!(balance, (coins_per_asset * amount_per_coin) as u128);\n\n        let expected_key = asset_id.to_string();\n        assert!(balances.contains_key(&expected_key));\n        assert_eq!(\n            *balances.get(&expected_key).unwrap(),\n            (coins_per_asset * amount_per_coin) as u128\n        );\n    }\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_wallet_balance_api_single_asset() -> Result<()> {\n    let signer = PrivateKeySigner::random(&mut rand::thread_rng());\n    let number_of_coins = 21;\n    let amount_per_coin = 11;\n    let coins = setup_single_asset_coins(\n        signer.address(),\n        AssetId::zeroed(),\n        number_of_coins,\n        amount_per_coin,\n    );\n\n    let provider = setup_test_provider(coins.clone(), vec![], None, None).await?;\n    let wallet = Wallet::new(signer, provider.clone());\n\n    for coin in coins {\n        let balance = wallet.get_asset_balance(&coin.asset_id).await?;\n        assert_eq!(balance, (number_of_coins * amount_per_coin) as u128);\n    }\n\n    let balances = wallet.get_balances().await?;\n    let expected_key = AssetId::zeroed().to_string();\n    assert_eq!(balances.len(), 1); // only the base asset\n    assert!(balances.contains_key(&expected_key));\n    assert_eq!(\n        *balances.get(&expected_key).unwrap(),\n        (number_of_coins * amount_per_coin) as u128\n    );\n\n    Ok(())\n}\n\nfn base_asset_wallet_config(num_wallets: u64) -> WalletsConfig {\n    let asset_configs = vec![AssetConfig {\n        id: AssetId::zeroed(),\n        num_coins: 20,\n        coin_amount: 20,\n    }];\n    WalletsConfig::new_multiple_assets(num_wallets, asset_configs)\n}\n\n#[tokio::test]\nasync fn adjust_fee_empty_transaction() -> Result<()> {\n    let wallet = launch_provider_and_get_wallet().await?;\n\n    let mut tb = ScriptTransactionBuilder::prepare_transfer(vec![], vec![], TxPolicies::default());\n    assert!(tb.inputs().is_empty());\n    assert!(tb.outputs().is_empty());\n\n    wallet.add_witnesses(&mut tb)?;\n    wallet.adjust_for_fee(&mut tb, 0).await?;\n    assert!(!tb.inputs().is_empty(), \"inputs should be added\");\n    assert_eq!(tb.outputs().len(), 1, \"output should be added\");\n\n    let tx = tb.build(wallet.provider()).await?;\n\n    let total_amount_inputs: u64 = tx.inputs().iter().map(|i| i.amount().unwrap()).sum();\n    assert!(\n        total_amount_inputs > tx.max_fee().unwrap(),\n        \"amount should cover tx\"\n    );\n\n    let expected_outputs = vec![Output::change(wallet.address(), 0, AssetId::zeroed())];\n\n    assert_eq!(tx.outputs(), &expected_outputs);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn adjust_for_fee_with_message_data_input() -> Result<()> {\n    let wallet_signer = PrivateKeySigner::random(&mut rand::thread_rng());\n    let receiver_signer = PrivateKeySigner::random(&mut rand::thread_rng());\n\n    let messages = setup_single_message(\n        Address::default(),\n        wallet_signer.address(),\n        100,\n        0.into(),\n        vec![1, 2, 3], // has data\n    );\n    let asset_id = AssetId::zeroed();\n    let coins = setup_single_asset_coins(wallet_signer.address(), asset_id, 1, 50);\n    let provider = setup_test_provider(coins, vec![messages], None, None).await?;\n    let wallet = Wallet::new(wallet_signer, provider.clone());\n    let receiver = Wallet::new(receiver_signer, provider.clone());\n\n    let amount_to_send = 14;\n    let message = wallet.get_messages().await?.pop().unwrap();\n    let input = Input::resource_signed(CoinType::Message(message));\n    let outputs = wallet.get_asset_outputs_for_amount(receiver.address(), asset_id, amount_to_send);\n\n    {\n        // message with data as only input - without adjust for fee\n        let mut tb = ScriptTransactionBuilder::prepare_transfer(\n            vec![input.clone()],\n            outputs.clone(),\n            TxPolicies::default(),\n        );\n        wallet.add_witnesses(&mut tb)?;\n\n        let tx = tb.build(wallet.provider()).await?;\n        let err = provider\n            .send_transaction_and_await_commit(tx)\n            .await\n            .unwrap_err();\n\n        assert!(err.to_string().contains(\"Validity(NoSpendableInput)\"));\n    }\n    {\n        // message with data as only input - with adjust for fee\n        let mut tb = ScriptTransactionBuilder::prepare_transfer(\n            vec![input.clone()],\n            outputs.clone(),\n            TxPolicies::default(),\n        );\n\n        wallet.adjust_for_fee(&mut tb, 0).await.unwrap();\n        wallet.add_witnesses(&mut tb)?;\n\n        let tx = tb.build(wallet.provider()).await?;\n\n        assert_eq!(receiver.get_asset_balance(&asset_id).await?, 0);\n\n        provider\n            .send_transaction_and_await_commit(tx)\n            .await\n            .unwrap();\n\n        assert_eq!(\n            receiver.get_asset_balance(&asset_id).await?,\n            amount_to_send as u128\n        );\n    }\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn adjust_fee_resources_to_transfer_with_base_asset() -> Result<()> {\n    let wallet = launch_provider_and_get_wallet().await?;\n\n    let base_amount = 30;\n    let base_asset_id = AssetId::zeroed();\n    let inputs = wallet\n        .get_asset_inputs_for_amount(base_asset_id, base_amount.into(), None)\n        .await?;\n    let outputs =\n        wallet.get_asset_outputs_for_amount(Address::zeroed(), base_asset_id, base_amount);\n\n    let mut tb = ScriptTransactionBuilder::prepare_transfer(inputs, outputs, TxPolicies::default());\n\n    wallet.adjust_for_fee(&mut tb, base_amount.into()).await?;\n    wallet.add_witnesses(&mut tb)?;\n\n    let tx = tb.build(wallet.provider()).await?;\n\n    let total_amount_inputs: u64 = tx.inputs().iter().map(|i| i.amount().unwrap()).sum();\n    assert!(total_amount_inputs > tx.max_fee().unwrap()); // can cover tx\n\n    let expected_outputs = vec![\n        Output::coin(Address::zeroed(), base_amount, base_asset_id),\n        Output::change(wallet.address(), 0, base_asset_id),\n    ];\n\n    assert_eq!(tx.outputs(), &expected_outputs);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_transfer() -> Result<()> {\n    let wallet_1_signer = PrivateKeySigner::random(&mut rand::thread_rng());\n    let wallet_2_signer = PrivateKeySigner::random(&mut rand::thread_rng());\n\n    let amount = 100;\n    let num_coins = 1;\n    let base_asset_id = AssetId::zeroed();\n    let mut coins_1 =\n        setup_single_asset_coins(wallet_1_signer.address(), base_asset_id, num_coins, amount);\n    let coins_2 =\n        setup_single_asset_coins(wallet_2_signer.address(), base_asset_id, num_coins, amount);\n    coins_1.extend(coins_2);\n\n    let provider = setup_test_provider(coins_1, vec![], None, None).await?;\n    let wallet_1 = Wallet::new(wallet_1_signer, provider.clone());\n    let wallet_2 = Wallet::new(wallet_2_signer, provider.clone()).lock();\n\n    let _ = wallet_1\n        .transfer(\n            wallet_2.address(),\n            amount / 2,\n            Default::default(),\n            TxPolicies::default(),\n        )\n        .await\n        .unwrap();\n\n    let wallet_2_coins = wallet_2.get_coins(base_asset_id).await.unwrap();\n    let wallet_2_balance = wallet_2.get_asset_balance(&base_asset_id).await?;\n    assert_eq!(wallet_2_coins.len(), 2);\n    assert_eq!(wallet_2_balance, (amount + amount / 2) as u128);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn send_transfer_transactions() -> Result<()> {\n    let amount = 5;\n    let (wallet_1, wallet_2) = setup_transfer_test(amount).await?;\n\n    // Configure transaction policies\n    let tip = 2;\n    let script_gas_limit = 500_000;\n    let maturity = 0;\n\n    let tx_policies = TxPolicies::default()\n        .with_tip(tip)\n        .with_maturity(maturity)\n        .with_script_gas_limit(script_gas_limit);\n\n    // Transfer 1 from wallet 1 to wallet 2.\n    let amount_to_send = 1;\n    let base_asset_id = AssetId::zeroed();\n    let tx_id = wallet_1\n        .transfer(\n            wallet_2.address(),\n            amount_to_send,\n            base_asset_id,\n            tx_policies,\n        )\n        .await?\n        .tx_id;\n\n    // Assert that the transaction was properly configured.\n    let res = wallet_1\n        .try_provider()?\n        .get_transaction_by_id(&tx_id)\n        .await?\n        .unwrap();\n\n    let script: ScriptTransaction = match res.transaction {\n        TransactionType::Script(tx) => tx,\n        _ => panic!(\"Received unexpected tx type!\"),\n    };\n    // Transfer scripts uses set `script_gas_limit` despite not having script code\n    assert_eq!(script.gas_limit(), script_gas_limit);\n    assert_eq!(script.maturity().unwrap(), maturity);\n\n    let wallet_1_spendable_resources = wallet_1\n        .get_spendable_resources(base_asset_id, 1, None)\n        .await?;\n    let wallet_2_spendable_resources = wallet_2\n        .get_spendable_resources(base_asset_id, 1, None)\n        .await?;\n    let wallet_1_all_coins = wallet_1.get_coins(base_asset_id).await?;\n    let wallet_2_all_coins = wallet_2.get_coins(base_asset_id).await?;\n\n    // wallet_1 has now only one spent coin\n    assert_eq!(wallet_1_spendable_resources.len(), 1);\n    assert_eq!(wallet_1_all_coins.len(), 1);\n    // Check that wallet two now has a coin.\n    assert_eq!(wallet_2_all_coins.len(), 1);\n    assert_eq!(wallet_2_spendable_resources.len(), 1);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn transfer_coins_with_change() -> Result<()> {\n    const AMOUNT: u64 = 5;\n    let (wallet_1, wallet_2) = setup_transfer_test(AMOUNT).await?;\n\n    // Transfer 2 from wallet 1 to wallet 2.\n    const SEND_AMOUNT: u64 = 2;\n    let fee = wallet_1\n        .transfer(\n            wallet_2.address(),\n            SEND_AMOUNT,\n            AssetId::zeroed(),\n            TxPolicies::default(),\n        )\n        .await?\n        .tx_status\n        .total_fee;\n\n    let base_asset_id = AssetId::zeroed();\n    let wallet_1_final_coins = wallet_1\n        .get_spendable_resources(base_asset_id, 1, None)\n        .await?;\n\n    // Assert that we've sent 2 from wallet 1, resulting in an amount of 3 in wallet 1.\n    let resulting_amount = wallet_1_final_coins.first().unwrap();\n    assert_eq!(resulting_amount.amount(), AMOUNT - SEND_AMOUNT - fee);\n\n    let wallet_2_final_coins = wallet_2.get_coins(base_asset_id).await?;\n    assert_eq!(wallet_2_final_coins.len(), 1);\n\n    let total_amount: u64 = wallet_2_final_coins.iter().map(|c| c.amount).sum();\n    assert_eq!(total_amount, SEND_AMOUNT);\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_wallet_get_coins() -> Result<()> {\n    const AMOUNT: u64 = 1000;\n    const NUM_COINS: u64 = 3;\n    let addr = Address::zeroed();\n    let coins = setup_single_asset_coins(addr, AssetId::zeroed(), NUM_COINS, AMOUNT);\n\n    let provider = setup_test_provider(coins, vec![], None, None).await?;\n    let wallet = Wallet::new_locked(addr, provider.clone());\n\n    let consensus_parameters = provider.consensus_parameters().await?;\n    let wallet_initial_coins = wallet\n        .get_coins(*consensus_parameters.base_asset_id())\n        .await?;\n    let total_amount: u64 = wallet_initial_coins.iter().map(|c| c.amount).sum();\n\n    assert_eq!(wallet_initial_coins.len(), NUM_COINS as usize);\n    assert_eq!(total_amount, AMOUNT * NUM_COINS);\n\n    Ok(())\n}\n\nasync fn setup_transfer_test(amount: u64) -> Result<(Wallet, Wallet)> {\n    let wallet_1_signer = PrivateKeySigner::random(&mut rand::thread_rng());\n\n    let coins = setup_single_asset_coins(wallet_1_signer.address(), AssetId::zeroed(), 1, amount);\n\n    let provider = setup_test_provider(coins, vec![], None, None).await?;\n\n    let wallet_1 = Wallet::new(wallet_1_signer, provider.clone());\n    let wallet_2 = Wallet::random(&mut thread_rng(), provider.clone());\n\n    Ok((wallet_1, wallet_2))\n}\n\n#[tokio::test]\nasync fn transfer_more_than_owned() -> Result<()> {\n    const AMOUNT: u64 = 1000000;\n    let (wallet_1, wallet_2) = setup_transfer_test(AMOUNT).await?;\n\n    // Transferring more than balance should fail.\n    let response = wallet_1\n        .transfer(\n            wallet_2.address(),\n            AMOUNT * 2,\n            Default::default(),\n            TxPolicies::default(),\n        )\n        .await;\n\n    assert!(response.is_err());\n\n    let wallet_2_coins = wallet_2.get_coins(AssetId::zeroed()).await?;\n    assert_eq!(wallet_2_coins.len(), 0);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn transfer_coins_of_non_base_asset() -> Result<()> {\n    const AMOUNT: u64 = 10000;\n    let wallet_1_signer = PrivateKeySigner::random(&mut rand::thread_rng());\n\n    let asset_id: AssetId = AssetId::from([1; 32usize]);\n    let mut coins = setup_single_asset_coins(wallet_1_signer.address(), asset_id, 1, AMOUNT);\n    // setup base asset coins to pay tx fees\n    let base_coins =\n        setup_single_asset_coins(wallet_1_signer.address(), AssetId::zeroed(), 1, AMOUNT);\n    coins.extend(base_coins);\n\n    let provider = setup_test_provider(coins, vec![], None, None).await?;\n\n    let wallet_1 = Wallet::new(wallet_1_signer, provider.clone());\n    let wallet_2 = Wallet::random(&mut thread_rng(), provider.clone());\n\n    const SEND_AMOUNT: u64 = 200;\n    let _ = wallet_1\n        .transfer(\n            wallet_2.address(),\n            SEND_AMOUNT,\n            asset_id,\n            TxPolicies::default(),\n        )\n        .await?;\n\n    let wallet_1_balance = wallet_1.get_asset_balance(&asset_id).await?;\n    assert_eq!(wallet_1_balance, (AMOUNT - SEND_AMOUNT) as u128);\n\n    let wallet_2_final_coins = wallet_2.get_coins(asset_id).await?;\n    assert_eq!(wallet_2_final_coins.len(), 1);\n\n    let total_amount: u64 = wallet_2_final_coins.iter().map(|c| c.amount).sum();\n    assert_eq!(total_amount, SEND_AMOUNT);\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn test_transfer_with_multiple_signatures() -> Result<()> {\n    let wallet_config = base_asset_wallet_config(5);\n    let wallets = launch_custom_provider_and_get_wallets(wallet_config, None, None).await?;\n    let provider = wallets[0].try_provider()?;\n\n    let receiver = Wallet::random(&mut thread_rng(), provider.clone());\n\n    let amount_to_transfer = 20u64;\n\n    let mut inputs = vec![];\n    let consensus_parameters = provider.consensus_parameters().await?;\n    for wallet in &wallets {\n        inputs.extend(\n            wallet\n                .get_asset_inputs_for_amount(\n                    *consensus_parameters.base_asset_id(),\n                    amount_to_transfer.into(),\n                    None,\n                )\n                .await?,\n        );\n    }\n\n    let amount_to_receive = amount_to_transfer * wallets.len() as u64;\n\n    // all change goes to the first wallet\n    let outputs = wallets[0].get_asset_outputs_for_amount(\n        receiver.address(),\n        *consensus_parameters.base_asset_id(),\n        amount_to_receive,\n    );\n\n    let mut tb = ScriptTransactionBuilder::prepare_transfer(inputs, outputs, TxPolicies::default());\n\n    for wallet in wallets.iter() {\n        wallet.add_witnesses(&mut tb)?\n    }\n\n    let tx = tb.build(provider).await?;\n    provider.send_transaction_and_await_commit(tx).await?;\n\n    assert_eq!(\n        receiver\n            .get_asset_balance(consensus_parameters.base_asset_id())\n            .await?,\n        amount_to_receive as u128,\n    );\n\n    Ok(())\n}\n\n#[tokio::test]\nasync fn wallet_transfer_respects_maturity_and_expiration() -> Result<()> {\n    let wallet = launch_provider_and_get_wallet().await?;\n    let asset_id = AssetId::zeroed();\n    let wallet_balance = wallet.get_asset_balance(&asset_id).await?;\n\n    let provider = wallet.provider();\n    let receiver: Address = thread_rng().r#gen();\n\n    let maturity = 10;\n    let expiration = 20;\n    let tx_policies = TxPolicies::default()\n        .with_maturity(maturity)\n        .with_expiration(expiration);\n    let amount_to_send = 10;\n\n    {\n        let err = wallet\n            .transfer(receiver, amount_to_send, asset_id, tx_policies)\n            .await\n            .expect_err(\"maturity not reached\");\n\n        assert!(err.to_string().contains(\"TransactionMaturity\"));\n    }\n    let transaction_fee = {\n        provider.produce_blocks(15, None).await?;\n        wallet\n            .transfer(receiver, amount_to_send, asset_id, tx_policies)\n            .await\n            .expect(\"should succeed. Block height between `maturity` and `expiration`\")\n            .tx_status\n            .total_fee\n    };\n    {\n        provider.produce_blocks(15, None).await?;\n        let err = wallet\n            .transfer(receiver, amount_to_send, asset_id, tx_policies)\n            .await\n            .expect_err(\"expiration reached\");\n\n        assert!(err.to_string().contains(\"TransactionExpiration\"));\n    }\n\n    // Wallet has spent the funds\n    assert_address_balance(\n        &wallet.address(),\n        provider,\n        &asset_id,\n        wallet_balance - amount_to_send as u128 - transaction_fee as u128,\n    )\n    .await;\n\n    // Funds were transferred\n    assert_address_balance(&receiver, provider, &asset_id, amount_to_send as u128).await;\n\n    Ok(())\n}\n"
  },
  {
    "path": "examples/codec/Cargo.toml",
    "content": "[package]\nname = \"fuels-example-codec\"\nversion = { workspace = true }\nauthors = { workspace = true }\nedition = { workspace = true }\nhomepage = { workspace = true }\nlicense = { workspace = true }\npublish = false\nrepository = { workspace = true }\ndescription = \"Fuel Rust SDK codec examples.\"\n\n[dev-dependencies]\nfuels = { workspace = true, features = [\"default\"] }\ntokio = { workspace = true, features = [\"full\"] }\n"
  },
  {
    "path": "examples/codec/src/lib.rs",
    "content": "#[cfg(test)]\nmod tests {\n    use fuels::{\n        core::codec::{DecoderConfig, EncoderConfig},\n        types::errors::Result,\n    };\n\n    #[test]\n    fn encoding_a_type() -> Result<()> {\n        //ANCHOR: encoding_example\n        use fuels::{\n            core::{codec::ABIEncoder, traits::Tokenizable},\n            macros::Tokenizable,\n        };\n\n        #[derive(Tokenizable)]\n        struct MyStruct {\n            field: u64,\n        }\n\n        let instance = MyStruct { field: 101 };\n        let _encoded: Vec<u8> = ABIEncoder::default().encode(&[instance.into_token()])?;\n        //ANCHOR_END: encoding_example\n\n        Ok(())\n    }\n    #[test]\n    fn encoding_via_macro() -> Result<()> {\n        //ANCHOR: encoding_example_w_macro\n        use fuels::{core::codec::calldata, macros::Tokenizable};\n\n        #[derive(Tokenizable)]\n        struct MyStruct {\n            field: u64,\n        }\n        let _: Vec<u8> = calldata!(MyStruct { field: 101 }, MyStruct { field: 102 })?;\n        //ANCHOR_END: encoding_example_w_macro\n\n        Ok(())\n    }\n\n    #[test]\n    fn decoding_example() -> Result<()> {\n        // ANCHOR: decoding_example\n        use fuels::{\n            core::{\n                codec::ABIDecoder,\n                traits::{Parameterize, Tokenizable},\n            },\n            macros::{Parameterize, Tokenizable},\n            types::Token,\n        };\n\n        #[derive(Parameterize, Tokenizable)]\n        struct MyStruct {\n            field: u64,\n        }\n\n        let bytes: &[u8] = &[0, 0, 0, 0, 0, 0, 0, 101];\n\n        let token: Token = ABIDecoder::default().decode(&MyStruct::param_type(), bytes)?;\n\n        let _: MyStruct = MyStruct::from_token(token)?;\n        // ANCHOR_END: decoding_example\n\n        Ok(())\n    }\n\n    #[test]\n    fn decoding_example_try_into() -> Result<()> {\n        // ANCHOR: decoding_example_try_into\n        use fuels::macros::{Parameterize, Tokenizable, TryFrom};\n\n        #[derive(Parameterize, Tokenizable, TryFrom)]\n        struct MyStruct {\n            field: u64,\n        }\n\n        let bytes: &[u8] = &[0, 0, 0, 0, 0, 0, 0, 101];\n\n        let _: MyStruct = bytes.try_into()?;\n        // ANCHOR_END: decoding_example_try_into\n\n        Ok(())\n    }\n\n    #[test]\n    fn configuring_the_decoder() -> Result<()> {\n        // ANCHOR: configuring_the_decoder\n\n        use fuels::core::codec::ABIDecoder;\n\n        ABIDecoder::new(DecoderConfig {\n            max_depth: 5,\n            max_tokens: 100,\n        });\n        // ANCHOR_END: configuring_the_decoder\n\n        Ok(())\n    }\n\n    #[test]\n    fn configuring_the_encoder() -> Result<()> {\n        // ANCHOR: configuring_the_encoder\n        use fuels::core::codec::ABIEncoder;\n\n        ABIEncoder::new(EncoderConfig {\n            max_depth: 5,\n            max_tokens: 100,\n        });\n        // ANCHOR_END: configuring_the_encoder\n\n        Ok(())\n    }\n}\n"
  },
  {
    "path": "examples/contracts/Cargo.toml",
    "content": "[package]\nname = \"fuels-example-contracts\"\nversion = { workspace = true }\nauthors = { workspace = true }\nedition = { workspace = true }\nhomepage = { workspace = true }\nlicense = { workspace = true }\npublish = false\nrepository = { workspace = true }\ndescription = \"Fuel Rust SDK contract examples.\"\n\n[dependencies]\nfuels = { workspace = true, features = [\"default\"] }\nrand = { workspace = true, features = [\"default\"] }\ntokio = { workspace = true, features = [\"full\"] }\ntempfile = { workspace = true }\n\n[features]\nfuel-core-lib = [\"fuels/fuel-core-lib\"]\nrocksdb = [\"fuels/rocksdb\"]\n"
  },
  {
    "path": "examples/contracts/src/lib.rs",
    "content": "#[cfg(test)]\nmod tests {\n    use std::{collections::HashSet, time::Duration};\n\n    use fuels::{\n        accounts::signers::{fake::FakeSigner, private_key::PrivateKeySigner},\n        core::codec::{ABIFormatter, DecoderConfig, EncoderConfig, encode_fn_selector},\n        prelude::{LoadConfiguration, NodeConfig, StorageConfiguration},\n        programs::debug::ScriptType,\n        test_helpers::{ChainConfig, StateConfig},\n        tx::ContractIdExt,\n        types::{\n            SubAssetId,\n            errors::{Result, transaction::Reason},\n        },\n    };\n    use rand::{Rng, thread_rng};\n\n    #[tokio::test]\n    async fn instantiate_client() -> Result<()> {\n        // ANCHOR: instantiate_client\n        use fuels::prelude::{FuelService, Provider};\n\n        // Run the fuel node.\n        let server = FuelService::start(\n            NodeConfig::default(),\n            ChainConfig::default(),\n            StateConfig::default(),\n        )\n        .await?;\n\n        // Create a client that will talk to the node created above.\n        let client = Provider::from(server.bound_address()).await?;\n        assert!(client.healthy().await?);\n        // ANCHOR_END: instantiate_client\n        Ok(())\n    }\n\n    #[tokio::test]\n    async fn deploy_contract() -> Result<()> {\n        use fuels::prelude::*;\n\n        // ANCHOR: deploy_contract\n        // This helper will launch a local node and provide a test wallet linked to it\n        let wallet = launch_provider_and_get_wallet().await?;\n\n        // This will load and deploy your contract binary to the chain so that its ID can\n        // be used to initialize the instance\n        let contract_id = Contract::load_from(\n            \"../../e2e/sway/contracts/contract_test/out/release/contract_test.bin\",\n            LoadConfiguration::default(),\n        )?\n        .deploy(&wallet, TxPolicies::default())\n        .await?\n        .contract_id;\n\n        println!(\"Contract deployed @ {contract_id}\");\n        // ANCHOR_END: deploy_contract\n\n        Ok(())\n    }\n\n    #[tokio::test]\n    async fn setup_program_test_example() -> Result<()> {\n        use fuels::prelude::*;\n\n        // ANCHOR: deploy_contract_setup_macro_short\n        setup_program_test!(\n            Wallets(\"wallet\"),\n            Abigen(Contract(\n                name = \"TestContract\",\n                project = \"e2e/sway/contracts/contract_test\"\n            )),\n            Deploy(\n                name = \"contract_instance\",\n                contract = \"TestContract\",\n                wallet = \"wallet\"\n            ),\n        );\n\n        let response = contract_instance\n            .methods()\n            .initialize_counter(42)\n            .call()\n            .await?;\n\n        assert_eq!(42, response.value);\n        // ANCHOR_END: deploy_contract_setup_macro_short\n\n        Ok(())\n    }\n\n    #[tokio::test]\n    async fn contract_call_cost_estimation() -> Result<()> {\n        use fuels::prelude::*;\n\n        abigen!(Contract(\n            name = \"MyContract\",\n            abi = \"e2e/sway/contracts/contract_test/out/release/contract_test-abi.json\"\n        ));\n\n        let wallet = launch_provider_and_get_wallet().await?;\n\n        let contract_id = Contract::load_from(\n            \"../../e2e/sway/contracts/contract_test/out/release/contract_test.bin\",\n            LoadConfiguration::default(),\n        )?\n        .deploy(&wallet, TxPolicies::default())\n        .await?\n        .contract_id;\n\n        // ANCHOR: contract_call_cost_estimation\n        let contract_instance = MyContract::new(contract_id, wallet);\n\n        let tolerance = Some(0.0);\n        let block_horizon = Some(1);\n        let transaction_cost = contract_instance\n            .methods()\n            .initialize_counter(42) // Build the ABI call\n            .estimate_transaction_cost(tolerance, block_horizon) // Get estimated transaction cost\n            .await?;\n        // ANCHOR_END: contract_call_cost_estimation\n\n        let expected_script_gas = 2340;\n        let expected_total_gas = 8592;\n\n        assert_eq!(transaction_cost.script_gas, expected_script_gas);\n        assert_eq!(transaction_cost.total_gas, expected_total_gas);\n\n        Ok(())\n    }\n\n    #[tokio::test]\n    async fn deploy_with_parameters() -> std::result::Result<(), Box<dyn std::error::Error>> {\n        use fuels::{prelude::*, tx::StorageSlot, types::Bytes32};\n        use rand::prelude::{Rng, SeedableRng, StdRng};\n\n        let wallet = launch_provider_and_get_wallet().await?;\n\n        let contract_id_1 = Contract::load_from(\n            \"../../e2e/sway/contracts/contract_test/out/release/contract_test.bin\",\n            LoadConfiguration::default(),\n        )?\n        .deploy(&wallet, TxPolicies::default())\n        .await?\n        .contract_id;\n\n        // ANCHOR: deploy_with_parameters\n        // Optional: Add `Salt`\n        let rng = &mut StdRng::seed_from_u64(2322u64);\n        let salt: [u8; 32] = rng.r#gen();\n\n        // Optional: Configure storage\n        let key = Bytes32::from([1u8; 32]);\n        let value = Bytes32::from([2u8; 32]);\n        let storage_slot = StorageSlot::new(key, value);\n        let storage_configuration =\n            StorageConfiguration::default().add_slot_overrides([storage_slot]);\n        let configuration = LoadConfiguration::default()\n            .with_storage_configuration(storage_configuration)\n            .with_salt(salt);\n\n        // Optional: Configure deployment parameters\n        let tx_policies = TxPolicies::default()\n            .with_tip(1)\n            .with_script_gas_limit(1_000_000)\n            .with_maturity(0)\n            .with_expiration(10_000);\n\n        let contract_id_2 = Contract::load_from(\n            \"../../e2e/sway/contracts/contract_test/out/release/contract_test.bin\",\n            configuration,\n        )?\n        .deploy(&wallet, tx_policies)\n        .await?\n        .contract_id;\n\n        println!(\"Contract deployed @ {contract_id_2}\");\n        // ANCHOR_END: deploy_with_parameters\n\n        assert_ne!(contract_id_1, contract_id_2);\n\n        // ANCHOR: use_deployed_contract\n        // This will generate your contract's methods onto `MyContract`.\n        // This means an instance of `MyContract` will have access to all\n        // your contract's methods that are running on-chain!\n        // ANCHOR: abigen_example\n        abigen!(Contract(\n            name = \"MyContract\",\n            abi = \"e2e/sway/contracts/contract_test/out/release/contract_test-abi.json\"\n        ));\n        // ANCHOR_END: abigen_example\n\n        // This is an instance of your contract which you can use to make calls to your functions\n        let contract_instance = MyContract::new(contract_id_2, wallet);\n\n        let response = contract_instance\n            .methods()\n            .initialize_counter(42) // Build the ABI call\n            .call() // Perform the network call\n            .await?;\n\n        assert_eq!(42, response.value);\n\n        let response = contract_instance\n            .methods()\n            .increment_counter(10)\n            .call()\n            .await?;\n\n        assert_eq!(52, response.value);\n        // ANCHOR_END: use_deployed_contract\n\n        // ANCHOR: submit_response_contract\n        let response = contract_instance\n            .methods()\n            .initialize_counter(42)\n            .submit()\n            .await?;\n\n        tokio::time::sleep(Duration::from_millis(500)).await;\n        let value = response.response().await?.value;\n\n        // ANCHOR_END: submit_response_contract\n        assert_eq!(42, value);\n\n        Ok(())\n    }\n\n    #[tokio::test]\n    async fn deploy_with_multiple_wallets() -> Result<()> {\n        use fuels::prelude::*;\n\n        abigen!(Contract(\n            name = \"MyContract\",\n            abi = \"e2e/sway/contracts/contract_test/out/release/contract_test-abi.json\"\n        ));\n\n        let wallets =\n            launch_custom_provider_and_get_wallets(WalletsConfig::default(), None, None).await?;\n\n        let contract_id_1 = Contract::load_from(\n            \"../../e2e/sway/contracts/contract_test/out/release/contract_test.bin\",\n            LoadConfiguration::default(),\n        )?\n        .deploy(&wallets[0], TxPolicies::default())\n        .await?\n        .contract_id;\n\n        let contract_instance_1 = MyContract::new(contract_id_1, wallets[0].clone());\n\n        let response = contract_instance_1\n            .methods()\n            .initialize_counter(42)\n            .call()\n            .await?;\n\n        assert_eq!(42, response.value);\n\n        let contract_id_2 = Contract::load_from(\n            \"../../e2e/sway/contracts/contract_test/out/release/contract_test.bin\",\n            LoadConfiguration::default().with_salt([1; 32]),\n        )?\n        .deploy(&wallets[1], TxPolicies::default())\n        .await?\n        .contract_id;\n\n        let contract_instance_2 = MyContract::new(contract_id_2, wallets[1].clone());\n\n        let response = contract_instance_2\n            .methods()\n            .initialize_counter(42) // Build the ABI call\n            .call()\n            .await?;\n\n        assert_eq!(42, response.value);\n\n        Ok(())\n    }\n\n    #[tokio::test]\n    #[allow(unused_variables)]\n    async fn contract_tx_and_call_params() -> Result<()> {\n        use fuels::prelude::*;\n        abigen!(Contract(\n            name = \"MyContract\",\n            abi = \"e2e/sway/contracts/contract_test/out/release/contract_test-abi.json\"\n        ));\n\n        let wallet = launch_provider_and_get_wallet().await?;\n\n        let contract_id = Contract::load_from(\n            \"../../e2e/sway/contracts/contract_test/out/release/contract_test.bin\",\n            LoadConfiguration::default(),\n        )?\n        .deploy(&wallet, TxPolicies::default())\n        .await?\n        .contract_id;\n\n        // ANCHOR: tx_policies\n        let contract_methods = MyContract::new(contract_id, wallet.clone()).methods();\n\n        let tx_policies = TxPolicies::default()\n            .with_tip(1)\n            .with_script_gas_limit(1_000_000)\n            .with_maturity(0)\n            .with_expiration(10_000);\n\n        let response = contract_methods\n            .initialize_counter(42) // Our contract method\n            .with_tx_policies(tx_policies) // Chain the tx policies\n            .call() // Perform the contract call\n            .await?; // This is an async call, `.await` it.\n        // ANCHOR_END: tx_policies\n\n        // ANCHOR: tx_policies_default\n        let response = contract_methods\n            .initialize_counter(42)\n            .with_tx_policies(TxPolicies::default())\n            .call()\n            .await?;\n        // ANCHOR_END: tx_policies_default\n\n        // ANCHOR: call_parameters\n        let contract_methods = MyContract::new(contract_id, wallet.clone()).methods();\n\n        let tx_policies = TxPolicies::default();\n\n        // Forward 1_000_000 coin amount of base asset_id\n        // this is a big number for checking that amount can be a u64\n        let call_params = CallParameters::default().with_amount(1_000_000);\n\n        let response = contract_methods\n            .get_msg_amount() // Our contract method.\n            .with_tx_policies(tx_policies) // Chain the tx policies.\n            .call_params(call_params)? // Chain the call parameters.\n            .call() // Perform the contract call.\n            .await?;\n        // ANCHOR_END: call_parameters\n\n        // ANCHOR: call_parameters_default\n        let response = contract_methods\n            .initialize_counter(42)\n            .call_params(CallParameters::default())?\n            .call()\n            .await?;\n        // ANCHOR_END: call_parameters_default\n        Ok(())\n    }\n\n    #[tokio::test]\n    #[allow(unused_variables)]\n    #[cfg(any(not(feature = \"fuel-core-lib\"), feature = \"rocksdb\"))]\n    async fn token_ops_tests() -> Result<()> {\n        use fuels::{prelude::*, types::SubAssetId};\n        abigen!(Contract(\n            name = \"MyContract\",\n            abi = \"e2e/sway/contracts/token_ops/out/release/token_ops-abi.json\"\n        ));\n\n        let temp_dir = tempfile::tempdir().expect(\"failed to make tempdir\");\n        let temp_dir_name = temp_dir\n            .path()\n            .file_name()\n            .expect(\"failed to get file name\")\n            .to_string_lossy()\n            .to_string();\n        let temp_database_path = temp_dir.path().join(\"db\");\n\n        let node_config = NodeConfig {\n            starting_gas_price: 1100,\n            database_type: DbType::RocksDb(Some(temp_database_path)),\n            historical_execution: true,\n            ..NodeConfig::default()\n        };\n\n        let chain_config = ChainConfig {\n            chain_name: temp_dir_name,\n            ..ChainConfig::default()\n        };\n\n        let wallets = launch_custom_provider_and_get_wallets(\n            WalletsConfig::default(),\n            Some(node_config),\n            Some(chain_config),\n        )\n        .await?;\n        let wallet = wallets.first().expect(\"is there\");\n\n        let contract_id = Contract::load_from(\n            \"../../e2e/sway/contracts/token_ops/out/release/token_ops.bin\",\n            LoadConfiguration::default(),\n        )?\n        .deploy_if_not_exists(wallet, TxPolicies::default())\n        .await?\n        .contract_id;\n\n        let contract_methods = MyContract::new(contract_id, wallet.clone()).methods();\n        // ANCHOR: simulate\n        // you would mint 100 coins if the transaction wasn't simulated\n        let counter = contract_methods\n            .mint_coins(100)\n            .simulate(Execution::realistic())\n            .await?;\n        // ANCHOR_END: simulate\n\n        {\n            // ANCHOR: simulate_read_state\n            // you don't need any funds to read state\n            let balance = contract_methods\n                .get_balance(contract_id, AssetId::zeroed())\n                .simulate(Execution::state_read_only())\n                .await?\n                .value;\n            // ANCHOR_END: simulate_read_state\n        }\n        {\n            let provider = wallet.provider();\n            provider.produce_blocks(2, None).await?;\n            let block_height = provider.latest_block_height().await?;\n\n            // ANCHOR: simulate_read_state_at_height\n            let balance = contract_methods\n                .get_balance(contract_id, AssetId::zeroed())\n                .simulate(Execution::state_read_only().at_height(block_height))\n                .await?\n                .value;\n            // ANCHOR_END: simulate_read_state_at_height\n        }\n\n        let response = contract_methods.mint_coins(1_000_000).call().await?;\n        // ANCHOR: variable_outputs\n        let address = wallet.address();\n        let asset_id = contract_id.asset_id(&SubAssetId::zeroed());\n\n        // withdraw some tokens to wallet\n        let response = contract_methods\n            .transfer(1_000_000, asset_id, address.into())\n            .with_variable_output_policy(VariableOutputPolicy::Exactly(1))\n            .call()\n            .await?;\n        // ANCHOR_END: variable_outputs\n        Ok(())\n    }\n\n    #[tokio::test]\n    #[allow(unused_variables)]\n    async fn dependency_estimation() -> Result<()> {\n        use fuels::prelude::*;\n        abigen!(Contract(\n            name = \"MyContract\",\n            abi = \"e2e/sway/contracts/lib_contract_caller/out/release/lib_contract_caller-abi.json\"\n        ));\n\n        let wallet = launch_provider_and_get_wallet().await?;\n\n        let called_contract_id: ContractId = Contract::load_from(\n            \"../../e2e/sway/contracts/lib_contract/out/release/lib_contract.bin\",\n            LoadConfiguration::default(),\n        )?\n        .deploy(&wallet, TxPolicies::default())\n        .await?\n        .contract_id;\n\n        let bin_path =\n            \"../../e2e/sway/contracts/lib_contract_caller/out/release/lib_contract_caller.bin\";\n        let caller_contract_id = Contract::load_from(bin_path, LoadConfiguration::default())?\n            .deploy(&wallet, TxPolicies::default())\n            .await?\n            .contract_id;\n\n        let contract_methods = MyContract::new(caller_contract_id, wallet.clone()).methods();\n\n        // ANCHOR: dependency_estimation_fail\n        let address = wallet.address();\n        let amount = 100;\n\n        let response = contract_methods\n            .mint_then_increment_from_contract(called_contract_id, amount, address.into())\n            .call()\n            .await;\n\n        assert!(matches!(\n            response,\n            Err(Error::Transaction(Reason::Failure { .. }))\n        ));\n        // ANCHOR_END: dependency_estimation_fail\n\n        // ANCHOR: dependency_estimation_manual\n        let response = contract_methods\n            .mint_then_increment_from_contract(called_contract_id, amount, address.into())\n            .with_variable_output_policy(VariableOutputPolicy::Exactly(1))\n            .with_contract_ids(&[called_contract_id])\n            .call()\n            .await?;\n        // ANCHOR_END: dependency_estimation_manual\n\n        let asset_id = caller_contract_id.asset_id(&SubAssetId::zeroed());\n        let balance = wallet.get_asset_balance(&asset_id).await?;\n        assert_eq!(balance, amount as u128);\n\n        // ANCHOR: dependency_estimation\n        let response = contract_methods\n            .mint_then_increment_from_contract(called_contract_id, amount, address.into())\n            .with_variable_output_policy(VariableOutputPolicy::EstimateMinimum)\n            .determine_missing_contracts()\n            .await?\n            .call()\n            .await?;\n        // ANCHOR_END: dependency_estimation\n\n        let balance = wallet.get_asset_balance(&asset_id).await?;\n        assert_eq!(balance, 2 * amount as u128);\n\n        Ok(())\n    }\n\n    #[tokio::test]\n    #[allow(unused_variables)]\n    async fn get_contract_outputs() -> Result<()> {\n        use fuels::prelude::*;\n\n        // ANCHOR: deployed_contracts\n        abigen!(Contract(\n            name = \"MyContract\",\n            // Replace with your contract ABI.json path\n            abi = \"e2e/sway/contracts/contract_test/out/release/contract_test-abi.json\"\n        ));\n        let wallet_original = launch_provider_and_get_wallet().await?;\n\n        let wallet = wallet_original.clone();\n        let contract_id: ContractId =\n            \"0x65b6a3d081966040bbccbb7f79ac91b48c635729c59a4c02f15ae7da999b32d3\".parse()?;\n\n        let connected_contract_instance = MyContract::new(contract_id, wallet);\n        // ANCHOR_END: deployed_contracts\n\n        Ok(())\n    }\n\n    #[tokio::test]\n    #[allow(unused_variables)]\n    async fn call_params_gas() -> Result<()> {\n        use fuels::prelude::*;\n        abigen!(Contract(\n            name = \"MyContract\",\n            abi = \"e2e/sway/contracts/contract_test/out/release/contract_test-abi.json\"\n        ));\n\n        let wallet = launch_provider_and_get_wallet().await?;\n\n        let contract_id = Contract::load_from(\n            \"../../e2e/sway/contracts/contract_test/out/release/contract_test.bin\",\n            LoadConfiguration::default(),\n        )?\n        .deploy(&wallet, TxPolicies::default())\n        .await?\n        .contract_id;\n\n        let contract_methods = MyContract::new(contract_id, wallet.clone()).methods();\n\n        // ANCHOR: call_params_gas\n        // Set the transaction `gas_limit` to 1_000_000 and `gas_forwarded` to 4300 to specify that\n        // the contract call transaction may consume up to 1_000_000 gas, while the actual call may\n        // only use 4300 gas\n        let tx_policies = TxPolicies::default().with_script_gas_limit(1_000_000);\n        let call_params = CallParameters::default().with_gas_forwarded(4300);\n\n        let response = contract_methods\n            .get_msg_amount() // Our contract method.\n            .with_tx_policies(tx_policies) // Chain the tx policies.\n            .call_params(call_params)? // Chain the call parameters.\n            .call() // Perform the contract call.\n            .await?;\n        // ANCHOR_END: call_params_gas\n        Ok(())\n    }\n\n    #[tokio::test]\n    #[allow(unused_variables)]\n    async fn multi_call_example() -> Result<()> {\n        use fuels::prelude::*;\n\n        abigen!(Contract(\n            name = \"MyContract\",\n            abi = \"e2e/sway/contracts/contract_test/out/release/contract_test-abi.json\"\n        ));\n\n        let wallet = launch_provider_and_get_wallet().await?;\n\n        let contract_id = Contract::load_from(\n            \"../../e2e/sway/contracts/contract_test/out/release/contract_test.bin\",\n            LoadConfiguration::default(),\n        )?\n        .deploy(&wallet, TxPolicies::default())\n        .await?\n        .contract_id;\n\n        // ANCHOR: multi_call_prepare\n        let contract_methods = MyContract::new(contract_id, wallet.clone()).methods();\n\n        let call_handler_1 = contract_methods.initialize_counter(42);\n        let call_handler_2 = contract_methods.get_array([42; 2]);\n        // ANCHOR_END: multi_call_prepare\n\n        // ANCHOR: multi_call_build\n        let multi_call_handler = CallHandler::new_multi_call(wallet.clone())\n            .add_call(call_handler_1)\n            .add_call(call_handler_2)\n            .with_tx_policies(TxPolicies::default());\n        // ANCHOR_END: multi_call_build\n        let multi_call_handler_tmp = multi_call_handler.clone();\n\n        // ANCHOR: multi_call_values\n        let (counter, array): (u64, [u64; 2]) = multi_call_handler.call().await?.value;\n        // ANCHOR_END: multi_call_values\n\n        let multi_call_handler = multi_call_handler_tmp.clone();\n        // ANCHOR: multi_contract_call_response\n        let response = multi_call_handler.call::<(u64, [u64; 2])>().await?;\n        // ANCHOR_END: multi_contract_call_response\n\n        assert_eq!(counter, 42);\n        assert_eq!(array, [42; 2]);\n\n        let multi_call_handler = multi_call_handler_tmp.clone();\n        // ANCHOR: submit_response_multicontract\n        let submitted_tx = multi_call_handler.submit().await?;\n        tokio::time::sleep(Duration::from_millis(500)).await;\n        let (counter, array): (u64, [u64; 2]) = submitted_tx.response().await?.value;\n        // ANCHOR_END: submit_response_multicontract\n\n        assert_eq!(counter, 42);\n        assert_eq!(array, [42; 2]);\n\n        Ok(())\n    }\n\n    #[tokio::test]\n    #[allow(unused_variables)]\n    async fn multi_call_cost_estimation() -> Result<()> {\n        use fuels::prelude::*;\n\n        abigen!(Contract(\n            name = \"MyContract\",\n            abi = \"e2e/sway/contracts/contract_test/out/release/contract_test-abi.json\"\n        ));\n\n        let wallet = launch_provider_and_get_wallet().await?;\n\n        let contract_id = Contract::load_from(\n            \"../../e2e/sway/contracts/contract_test/out/release/contract_test.bin\",\n            LoadConfiguration::default(),\n        )?\n        .deploy(&wallet, TxPolicies::default())\n        .await?\n        .contract_id;\n\n        let contract_methods = MyContract::new(contract_id, wallet.clone()).methods();\n\n        // ANCHOR: multi_call_cost_estimation\n        let call_handler_1 = contract_methods.initialize_counter(42);\n        let call_handler_2 = contract_methods.get_array([42; 2]);\n\n        let multi_call_handler = CallHandler::new_multi_call(wallet.clone())\n            .add_call(call_handler_1)\n            .add_call(call_handler_2);\n\n        let tolerance = Some(0.0);\n        let block_horizon = Some(1);\n        let transaction_cost = multi_call_handler\n            .estimate_transaction_cost(tolerance, block_horizon) // Get estimated transaction cost\n            .await?;\n        // ANCHOR_END: multi_call_cost_estimation\n\n        let expected_script_gas = 3832;\n        let expected_total_gas = 10_661;\n\n        assert_eq!(transaction_cost.script_gas, expected_script_gas);\n        assert_eq!(transaction_cost.total_gas, expected_total_gas);\n\n        Ok(())\n    }\n\n    #[tokio::test]\n    #[allow(unused_variables)]\n    async fn connect_wallet() -> Result<()> {\n        use fuels::prelude::*;\n        abigen!(Contract(\n            name = \"MyContract\",\n            abi = \"e2e/sway/contracts/contract_test/out/release/contract_test-abi.json\"\n        ));\n\n        let config = WalletsConfig::new(Some(2), Some(1), Some(DEFAULT_COIN_AMOUNT));\n        let mut wallets = launch_custom_provider_and_get_wallets(config, None, None).await?;\n        let wallet_1 = wallets.pop().unwrap();\n        let wallet_2 = wallets.pop().unwrap();\n\n        let contract_id = Contract::load_from(\n            \"../../e2e/sway/contracts/contract_test/out/release/contract_test.bin\",\n            LoadConfiguration::default(),\n        )?\n        .deploy(&wallet_1, TxPolicies::default())\n        .await?\n        .contract_id;\n\n        // ANCHOR: connect_wallet\n        // Create contract instance with wallet_1\n        let contract_instance = MyContract::new(contract_id, wallet_1.clone());\n\n        // Perform contract call with wallet_2\n        let response = contract_instance\n            .with_account(wallet_2) // Connect wallet_2\n            .methods() // Get contract methods\n            .get_msg_amount() // Our contract method\n            .call() // Perform the contract call.\n            .await?; // This is an async call, `.await` for it.\n        // ANCHOR_END: connect_wallet\n\n        Ok(())\n    }\n\n    #[tokio::test]\n    async fn custom_assets_example() -> Result<()> {\n        use fuels::prelude::*;\n\n        setup_program_test!(\n            Wallets(\"wallet\", \"wallet_2\"),\n            Abigen(Contract(\n                name = \"MyContract\",\n                project = \"e2e/sway/contracts/contract_test\"\n            )),\n            Deploy(\n                name = \"contract_instance\",\n                contract = \"MyContract\",\n                wallet = \"wallet\"\n            )\n        );\n\n        let some_addr: Address = thread_rng().r#gen();\n\n        // ANCHOR: add_custom_assets\n        let amount = 1000;\n        let _ = contract_instance\n            .methods()\n            .initialize_counter(42)\n            .add_custom_asset(AssetId::zeroed(), amount, Some(some_addr))\n            .call()\n            .await?;\n        // ANCHOR_END: add_custom_assets\n\n        let custom_inputs = vec![];\n        let custom_outputs = vec![];\n        // ANCHOR: add_custom_inputs_outputs\n        let _ = contract_instance\n            .methods()\n            .initialize_counter(42)\n            .with_inputs(custom_inputs)\n            .with_outputs(custom_outputs)\n            .add_signer(wallet_2.signer().clone())\n            .call()\n            .await?;\n        // ANCHOR_END: add_custom_inputs_outputs\n\n        Ok(())\n    }\n\n    #[tokio::test]\n    async fn low_level_call_example() -> Result<()> {\n        use fuels::{core::codec::calldata, prelude::*, types::SizedAsciiString};\n\n        setup_program_test!(\n            Wallets(\"wallet\"),\n            Abigen(\n                Contract(\n                    name = \"MyCallerContract\",\n                    project = \"e2e/sway/contracts/low_level_caller\"\n                ),\n                Contract(\n                    name = \"MyTargetContract\",\n                    project = \"e2e/sway/contracts/contract_test\"\n                ),\n            ),\n            Deploy(\n                name = \"caller_contract_instance\",\n                contract = \"MyCallerContract\",\n                wallet = \"wallet\"\n            ),\n            Deploy(\n                name = \"target_contract_instance\",\n                contract = \"MyTargetContract\",\n                wallet = \"wallet\"\n            ),\n        );\n\n        // ANCHOR: low_level_call\n        let function_selector = encode_fn_selector(\"set_value_multiple_complex\");\n        let call_data = calldata!(\n            MyStruct {\n                a: true,\n                b: [1, 2, 3],\n            },\n            SizedAsciiString::<4>::try_from(\"fuel\")?\n        )?;\n\n        caller_contract_instance\n            .methods()\n            .call_low_level_call(\n                target_contract_instance.id(),\n                Bytes(function_selector),\n                Bytes(call_data),\n            )\n            .determine_missing_contracts()\n            .await?\n            .call()\n            .await?;\n        // ANCHOR_END: low_level_call\n\n        let result_uint = target_contract_instance\n            .methods()\n            .read_counter()\n            .call()\n            .await\n            .unwrap()\n            .value;\n\n        let result_bool = target_contract_instance\n            .methods()\n            .get_bool_value()\n            .call()\n            .await\n            .unwrap()\n            .value;\n\n        let result_str = target_contract_instance\n            .methods()\n            .get_str_value()\n            .call()\n            .await\n            .unwrap()\n            .value;\n\n        assert_eq!(result_uint, 2);\n        assert!(result_bool);\n        assert_eq!(result_str, \"fuel\");\n\n        Ok(())\n    }\n\n    #[tokio::test]\n    async fn configure_the_return_value_decoder() -> Result<()> {\n        use fuels::prelude::*;\n\n        setup_program_test!(\n            Wallets(\"wallet\"),\n            Abigen(Contract(\n                name = \"MyContract\",\n                project = \"e2e/sway/contracts/contract_test\"\n            )),\n            Deploy(\n                name = \"contract_instance\",\n                contract = \"MyContract\",\n                wallet = \"wallet\"\n            )\n        );\n\n        // ANCHOR: contract_decoder_config\n        let _ = contract_instance\n            .methods()\n            .initialize_counter(42)\n            .with_decoder_config(DecoderConfig {\n                max_depth: 10,\n                max_tokens: 2_000,\n            })\n            .call()\n            .await?;\n        // ANCHOR_END: contract_decoder_config\n\n        Ok(())\n    }\n\n    #[tokio::test]\n    async fn storage_slots_override() -> Result<()> {\n        {\n            // ANCHOR: storage_slots_override\n            use fuels::{programs::contract::Contract, tx::StorageSlot};\n            let slot_override = StorageSlot::new([1; 32].into(), [2; 32].into());\n            let storage_config =\n                StorageConfiguration::default().add_slot_overrides([slot_override]);\n\n            let load_config =\n                LoadConfiguration::default().with_storage_configuration(storage_config);\n            let _: Result<_> = Contract::load_from(\"...\", load_config);\n            // ANCHOR_END: storage_slots_override\n        }\n\n        {\n            // ANCHOR: storage_slots_disable_autoload\n            use fuels::programs::contract::Contract;\n            let storage_config = StorageConfiguration::default().with_autoload(false);\n\n            let load_config =\n                LoadConfiguration::default().with_storage_configuration(storage_config);\n            let _: Result<_> = Contract::load_from(\"...\", load_config);\n            // ANCHOR_END: storage_slots_disable_autoload\n        }\n\n        Ok(())\n    }\n\n    #[tokio::test]\n    async fn contract_custom_call() -> Result<()> {\n        use fuels::prelude::*;\n\n        setup_program_test!(\n            Wallets(\"wallet\"),\n            Abigen(Contract(\n                name = \"TestContract\",\n                project = \"e2e/sway/contracts/contract_test\"\n            )),\n            Deploy(\n                name = \"contract_instance\",\n                contract = \"TestContract\",\n                wallet = \"wallet\"\n            ),\n        );\n        let provider = wallet.provider();\n\n        let counter = 42;\n\n        // ANCHOR: contract_call_tb\n        let call_handler = contract_instance.methods().initialize_counter(counter);\n\n        let mut tb = call_handler.transaction_builder().await?;\n\n        // customize the builder...\n\n        wallet.adjust_for_fee(&mut tb, 0).await?;\n        wallet.add_witnesses(&mut tb)?;\n\n        let tx = tb.build(provider).await?;\n\n        let tx_id = provider.send_transaction(tx).await?;\n        tokio::time::sleep(Duration::from_millis(500)).await;\n\n        let tx_status = provider.tx_status(&tx_id).await?;\n\n        let response = call_handler.get_response(tx_status)?;\n\n        assert_eq!(counter, response.value);\n        // ANCHOR_END: contract_call_tb\n\n        Ok(())\n    }\n\n    #[tokio::test]\n    async fn configure_encoder_config() -> Result<()> {\n        use fuels::prelude::*;\n\n        setup_program_test!(\n            Wallets(\"wallet\"),\n            Abigen(Contract(\n                name = \"MyContract\",\n                project = \"e2e/sway/contracts/contract_test\"\n            )),\n            Deploy(\n                name = \"contract_instance\",\n                contract = \"MyContract\",\n                wallet = \"wallet\"\n            )\n        );\n\n        // ANCHOR: contract_encoder_config\n        let _ = contract_instance\n            .with_encoder_config(EncoderConfig {\n                max_depth: 10,\n                max_tokens: 2_000,\n            })\n            .methods()\n            .initialize_counter(42)\n            .call()\n            .await?;\n        // ANCHOR_END: contract_encoder_config\n\n        Ok(())\n    }\n\n    #[tokio::test]\n    async fn contract_call_impersonation() -> Result<()> {\n        use fuels::prelude::*;\n\n        abigen!(Contract(\n            name = \"MyContract\",\n            abi = \"e2e/sway/contracts/contract_test/out/release/contract_test-abi.json\"\n        ));\n\n        // ANCHOR: utxo_validation_off\n        let node_config = NodeConfig {\n            utxo_validation: false,\n            ..Default::default()\n        };\n        // ANCHOR_END: utxo_validation_off\n        let signer = PrivateKeySigner::random(&mut thread_rng());\n        let coins = setup_single_asset_coins(\n            signer.address(),\n            AssetId::zeroed(),\n            DEFAULT_NUM_COINS,\n            DEFAULT_COIN_AMOUNT,\n        );\n        // ANCHOR: utxo_validation_off_node_start\n        let provider = setup_test_provider(coins, vec![], Some(node_config), None).await?;\n        // ANCHOR_END: utxo_validation_off_node_start\n        let wallet = Wallet::new(signer, provider.clone());\n\n        let contract_id = Contract::load_from(\n            \"../../e2e/sway/contracts/contract_test/out/release/contract_test.bin\",\n            LoadConfiguration::default(),\n        )?\n        .deploy(&wallet, TxPolicies::default())\n        .await?\n        .contract_id;\n\n        let some_address = wallet.address();\n        // ANCHOR: contract_call_impersonation\n        // create impersonator for an address\n        let fake_signer = FakeSigner::new(some_address);\n        let impersonator = Wallet::new(fake_signer, provider.clone());\n\n        let contract_instance = MyContract::new(contract_id, impersonator.clone());\n\n        let response = contract_instance\n            .methods()\n            .initialize_counter(42)\n            .call()\n            .await?;\n\n        assert_eq!(42, response.value);\n        // ANCHOR_END: contract_call_impersonation\n\n        Ok(())\n    }\n\n    #[tokio::test]\n    #[allow(unused_variables)]\n    async fn deploying_via_loader() -> Result<()> {\n        use fuels::prelude::*;\n\n        setup_program_test!(\n            Abigen(Contract(\n                name = \"MyContract\",\n                project = \"e2e/sway/contracts/huge_contract\"\n            )),\n            Wallets(\"main_wallet\")\n        );\n        let contract_binary =\n            \"../../e2e/sway/contracts/huge_contract/out/release/huge_contract.bin\";\n\n        let provider: Provider = main_wallet.provider().clone();\n\n        let random_salt = || Salt::new(rand::thread_rng().r#gen());\n        // ANCHOR: show_contract_is_too_big\n        let contract = Contract::load_from(\n            contract_binary,\n            LoadConfiguration::default().with_salt(random_salt()),\n        )?;\n        let max_allowed = provider\n            .consensus_parameters()\n            .await?\n            .contract_params()\n            .contract_max_size();\n\n        assert!(contract.code().len() as u64 > max_allowed);\n        // ANCHOR_END: show_contract_is_too_big\n\n        let wallet = main_wallet.clone();\n\n        // ANCHOR: manual_blob_upload_then_deploy\n        let max_words_per_blob = 10_000;\n        let blobs = Contract::load_from(\n            contract_binary,\n            LoadConfiguration::default().with_salt(random_salt()),\n        )?\n        .convert_to_loader(max_words_per_blob)?\n        .blobs()\n        .to_vec();\n\n        let mut all_blob_ids = vec![];\n        let mut already_uploaded_blobs = HashSet::new();\n        for blob in blobs {\n            let blob_id = blob.id();\n            all_blob_ids.push(blob_id);\n\n            // uploading the same blob twice is not allowed\n            if already_uploaded_blobs.contains(&blob_id) {\n                continue;\n            }\n\n            let mut tb = BlobTransactionBuilder::default().with_blob(blob);\n            wallet.adjust_for_fee(&mut tb, 0).await?;\n            wallet.add_witnesses(&mut tb)?;\n\n            let tx = tb.build(&provider).await?;\n            provider\n                .send_transaction_and_await_commit(tx)\n                .await?\n                .check(None)?;\n\n            already_uploaded_blobs.insert(blob_id);\n        }\n\n        let contract_id = Contract::loader_from_blob_ids(all_blob_ids, random_salt(), vec![])?\n            .deploy(&wallet, TxPolicies::default())\n            .await?\n            .contract_id;\n        // ANCHOR_END: manual_blob_upload_then_deploy\n\n        // ANCHOR: deploy_via_loader\n        let max_words_per_blob = 10_000;\n        let contract_id = Contract::load_from(\n            contract_binary,\n            LoadConfiguration::default().with_salt(random_salt()),\n        )?\n        .convert_to_loader(max_words_per_blob)?\n        .deploy(&wallet, TxPolicies::default())\n        .await?\n        .contract_id;\n        // ANCHOR_END: deploy_via_loader\n\n        // ANCHOR: auto_convert_to_loader\n        let max_words_per_blob = 10_000;\n        let contract_id = Contract::load_from(\n            contract_binary,\n            LoadConfiguration::default().with_salt(random_salt()),\n        )?\n        .smart_deploy(&wallet, TxPolicies::default(), max_words_per_blob)\n        .await?\n        .contract_id;\n        // ANCHOR_END: auto_convert_to_loader\n\n        // ANCHOR: upload_blobs_then_deploy\n        let contract_id = Contract::load_from(\n            contract_binary,\n            LoadConfiguration::default().with_salt(random_salt()),\n        )?\n        .convert_to_loader(max_words_per_blob)?\n        .upload_blobs(&wallet, TxPolicies::default())\n        .await?\n        .deploy(&wallet, TxPolicies::default())\n        .await?\n        .contract_id;\n        // ANCHOR_END: upload_blobs_then_deploy\n\n        let wallet = main_wallet.clone();\n        // ANCHOR: use_loader\n        let contract_instance = MyContract::new(contract_id, wallet);\n        let response = contract_instance.methods().something().call().await?.value;\n        assert_eq!(response, 1001);\n        // ANCHOR_END: use_loader\n\n        // ANCHOR: show_max_tx_size\n        provider\n            .consensus_parameters()\n            .await?\n            .tx_params()\n            .max_size();\n        // ANCHOR_END: show_max_tx_size\n\n        // ANCHOR: show_max_tx_gas\n        provider\n            .consensus_parameters()\n            .await?\n            .tx_params()\n            .max_gas_per_tx();\n        // ANCHOR_END: show_max_tx_gas\n\n        let wallet = main_wallet;\n        // ANCHOR: manual_blobs_then_deploy\n        let chunk_size = 100_000;\n        assert!(\n            chunk_size % 8 == 0,\n            \"all chunks, except the last, must be word-aligned\"\n        );\n        let blobs = contract\n            .code()\n            .chunks(chunk_size)\n            .map(|chunk| Blob::new(chunk.to_vec()))\n            .collect();\n\n        let contract_id = Contract::loader_from_blobs(blobs, random_salt(), vec![])?\n            .deploy(&wallet, TxPolicies::default())\n            .await?\n            .contract_id;\n        // ANCHOR_END: manual_blobs_then_deploy\n\n        // ANCHOR: estimate_max_blob_size\n        let max_blob_size = BlobTransactionBuilder::default()\n            .estimate_max_blob_size(&provider)\n            .await?;\n        // ANCHOR_END: estimate_max_blob_size\n\n        Ok(())\n    }\n\n    #[tokio::test]\n    #[allow(unused_variables)]\n    async fn decoding_script_transactions() -> Result<()> {\n        use fuels::prelude::*;\n\n        setup_program_test!(\n            Abigen(Contract(\n                name = \"MyContract\",\n                project = \"e2e/sway/contracts/contract_test\"\n            )),\n            Wallets(\"wallet\"),\n            Deploy(\n                name = \"contract_instance\",\n                contract = \"MyContract\",\n                wallet = \"wallet\"\n            )\n        );\n\n        let tx_id = contract_instance\n            .methods()\n            .initialize_counter(42)\n            .call()\n            .await?\n            .tx_id\n            .unwrap();\n\n        let provider: &Provider = wallet.provider();\n\n        // ANCHOR: decoding_script_transactions\n        let TransactionType::Script(tx) = provider\n            .get_transaction_by_id(&tx_id)\n            .await?\n            .unwrap()\n            .transaction\n        else {\n            panic!(\"Transaction is not a script transaction\");\n        };\n\n        let ScriptType::ContractCall(calls) = ScriptType::detect(tx.script(), tx.script_data())?\n        else {\n            panic!(\"Script is not a contract call\");\n        };\n\n        let json_abi = std::fs::read_to_string(\n            \"../../e2e/sway/contracts/contract_test/out/release/contract_test-abi.json\",\n        )?;\n        let abi_formatter = ABIFormatter::from_json_abi(json_abi)?;\n\n        let call = &calls[0];\n        let fn_selector = call.decode_fn_selector()?;\n        let decoded_args =\n            abi_formatter.decode_fn_args(&fn_selector, call.encoded_args.as_slice())?;\n\n        eprintln!(\n            \"The script called: {fn_selector}({})\",\n            decoded_args.join(\", \")\n        );\n\n        // ANCHOR_END: decoding_script_transactions\n        Ok(())\n    }\n}\n"
  },
  {
    "path": "examples/cookbook/Cargo.toml",
    "content": "[package]\nname = \"fuels-example-cookbook\"\nversion = { workspace = true }\nauthors = { workspace = true }\nedition = { workspace = true }\nhomepage = { workspace = true }\nlicense = { workspace = true }\npublish = false\nrepository = { workspace = true }\ndescription = \"Fuel Rust SDK cookbook examples.\"\n\n[dependencies]\nfuels = { workspace = true, features = [\"default\"] }\nrand = { workspace = true }\ntokio = { workspace = true, features = [\"full\"] }\n\n[features]\nrocksdb = [\"fuels/rocksdb\"]\nfuel-core-lib = [\"fuels/fuel-core-lib\"]\n"
  },
  {
    "path": "examples/cookbook/src/lib.rs",
    "content": "#[cfg(test)]\nmod tests {\n    use std::{str::FromStr, time::Duration};\n\n    use fuels::{\n        accounts::{\n            ViewOnlyAccount, predicate::Predicate, signers::private_key::PrivateKeySigner,\n            wallet::Wallet,\n        },\n        prelude::Result,\n        test_helpers::{setup_single_asset_coins, setup_test_provider},\n        tx::ContractIdExt,\n        types::{\n            Address, AssetId, SubAssetId,\n            transaction::TxPolicies,\n            transaction_builders::{\n                BuildableTransaction, ScriptTransactionBuilder, TransactionBuilder,\n            },\n            tx_status::TxStatus,\n        },\n    };\n    use rand::thread_rng;\n\n    #[tokio::test]\n    async fn liquidity() -> Result<()> {\n        use fuels::{\n            prelude::*,\n            test_helpers::{AssetConfig, WalletsConfig},\n        };\n\n        // ANCHOR: liquidity_abigen\n        abigen!(Contract(\n            name = \"MyContract\",\n            abi = \"e2e/sway/contracts/liquidity_pool/out/release/liquidity_pool-abi.json\"\n        ));\n        // ANCHOR_END: liquidity_abigen\n\n        // ANCHOR: liquidity_wallet\n        let base_asset_id: AssetId =\n            \"0x9ae5b658754e096e4d681c548daf46354495a437cc61492599e33fc64dcdc30c\".parse()?;\n\n        let asset_ids = [AssetId::zeroed(), base_asset_id];\n        let asset_configs = asset_ids\n            .map(|id| AssetConfig {\n                id,\n                num_coins: 1,\n                coin_amount: 1_000_000,\n            })\n            .into();\n\n        let wallet_config = WalletsConfig::new_multiple_assets(1, asset_configs);\n        let wallets = launch_custom_provider_and_get_wallets(wallet_config, None, None).await?;\n        let wallet = &wallets[0];\n        // ANCHOR_END: liquidity_wallet\n\n        // ANCHOR: liquidity_deploy\n        let contract_id = Contract::load_from(\n            \"../../e2e/sway/contracts/liquidity_pool/out/release/liquidity_pool.bin\",\n            LoadConfiguration::default(),\n        )?\n        .deploy(wallet, TxPolicies::default())\n        .await?\n        .contract_id;\n\n        let contract_methods = MyContract::new(contract_id, wallet.clone()).methods();\n        // ANCHOR_END: liquidity_deploy\n\n        // ANCHOR: liquidity_deposit\n        let deposit_amount = 1_000_000;\n        let call_params = CallParameters::default()\n            .with_amount(deposit_amount)\n            .with_asset_id(base_asset_id);\n\n        contract_methods\n            .deposit(wallet.address().into())\n            .call_params(call_params)?\n            .with_variable_output_policy(VariableOutputPolicy::Exactly(1))\n            .call()\n            .await?;\n        // ANCHOR_END: liquidity_deposit\n\n        // ANCHOR: liquidity_withdraw\n        let lp_asset_id = contract_id.asset_id(&SubAssetId::zeroed());\n        let lp_token_balance = wallet.get_asset_balance(&lp_asset_id).await?;\n\n        let call_params = CallParameters::default()\n            .with_amount(lp_token_balance.try_into().unwrap())\n            .with_asset_id(lp_asset_id);\n\n        contract_methods\n            .withdraw(wallet.address().into())\n            .call_params(call_params)?\n            .with_variable_output_policy(VariableOutputPolicy::Exactly(1))\n            .call()\n            .await?;\n\n        let base_balance = wallet.get_asset_balance(&base_asset_id).await?;\n        assert_eq!(base_balance, deposit_amount as u128);\n        // ANCHOR_END: liquidity_withdraw\n        Ok(())\n    }\n\n    #[tokio::test]\n    async fn custom_chain() -> Result<()> {\n        // ANCHOR: custom_chain_import\n        use fuels::{\n            prelude::*,\n            tx::{ConsensusParameters, FeeParameters, TxParameters},\n        };\n        // ANCHOR_END: custom_chain_import\n\n        // ANCHOR: custom_chain_consensus\n        let tx_params = TxParameters::default()\n            .with_max_gas_per_tx(1_000)\n            .with_max_inputs(2);\n        let fee_params = FeeParameters::default().with_gas_price_factor(10);\n\n        let mut consensus_parameters = ConsensusParameters::default();\n        consensus_parameters.set_tx_params(tx_params);\n        consensus_parameters.set_fee_params(fee_params);\n\n        let chain_config = ChainConfig {\n            consensus_parameters,\n            ..ChainConfig::default()\n        };\n        // ANCHOR_END: custom_chain_consensus\n\n        // ANCHOR: custom_chain_coins\n        let signer = PrivateKeySigner::random(&mut thread_rng());\n        let coins = setup_single_asset_coins(\n            signer.address(),\n            Default::default(),\n            DEFAULT_NUM_COINS,\n            DEFAULT_COIN_AMOUNT,\n        );\n        // ANCHOR_END: custom_chain_coins\n\n        // ANCHOR: custom_chain_provider\n        let node_config = NodeConfig::default();\n        let _provider =\n            setup_test_provider(coins, vec![], Some(node_config), Some(chain_config)).await?;\n        // ANCHOR_END: custom_chain_provider\n        Ok(())\n    }\n\n    #[tokio::test]\n    async fn transfer_multiple() -> Result<()> {\n        use std::str::FromStr;\n\n        use fuels::prelude::*;\n        // ANCHOR: transfer_multiple_setup\n        let wallet_1_signer = PrivateKeySigner::random(&mut thread_rng());\n\n        const NUM_ASSETS: u64 = 5;\n        const AMOUNT: u64 = 100_000;\n        const NUM_COINS: u64 = 1;\n        let (coins, _) =\n            setup_multiple_assets_coins(wallet_1_signer.address(), NUM_ASSETS, NUM_COINS, AMOUNT);\n\n        let provider = setup_test_provider(coins, vec![], None, None).await?;\n\n        let wallet_1 = Wallet::new(wallet_1_signer, provider.clone());\n        let wallet_2 = Wallet::random(&mut thread_rng(), provider.clone());\n        // ANCHOR_END: transfer_multiple_setup\n\n        // ANCHOR: transfer_multiple_input\n        let balances = wallet_1.get_balances().await?;\n\n        let consensus_parameters = provider.consensus_parameters().await?;\n        let mut inputs = vec![];\n        let mut outputs = vec![];\n        for (id_string, amount) in balances {\n            let id = AssetId::from_str(&id_string)?;\n\n            let input = wallet_1\n                .get_asset_inputs_for_amount(id, amount, None)\n                .await?;\n            inputs.extend(input);\n\n            // we don't transfer the full base asset so we can cover fees\n            let output = if id == *consensus_parameters.base_asset_id() {\n                wallet_1.get_asset_outputs_for_amount(wallet_2.address(), id, (amount / 2) as u64)\n            } else {\n                wallet_1.get_asset_outputs_for_amount(wallet_2.address(), id, amount as u64)\n            };\n\n            outputs.extend(output);\n        }\n        // ANCHOR_END: transfer_multiple_input\n\n        // ANCHOR: transfer_multiple_transaction\n        let mut tb =\n            ScriptTransactionBuilder::prepare_transfer(inputs, outputs, TxPolicies::default());\n        wallet_1.add_witnesses(&mut tb)?;\n\n        let tx = tb.build(&provider).await?;\n\n        provider.send_transaction_and_await_commit(tx).await?;\n\n        let balances = wallet_2.get_balances().await?;\n\n        assert_eq!(balances.len(), NUM_ASSETS as usize);\n        for (id, balance) in balances {\n            if id == *consensus_parameters.base_asset_id().to_string() {\n                assert_eq!(balance, (AMOUNT / 2) as u128);\n            } else {\n                assert_eq!(balance, AMOUNT as u128);\n            }\n        }\n        // ANCHOR_END: transfer_multiple_transaction\n\n        Ok(())\n    }\n\n    #[tokio::test]\n    #[cfg(any(not(feature = \"fuel-core-lib\"), feature = \"rocksdb\"))]\n    async fn create_or_use_rocksdb() -> Result<()> {\n        use std::path::PathBuf;\n\n        use fuels::prelude::*;\n        // ANCHOR: create_or_use_rocksdb\n        let provider_config = NodeConfig {\n            database_type: DbType::RocksDb(Some(PathBuf::from(\"/tmp/.spider/db\"))),\n            ..NodeConfig::default()\n        };\n        // ANCHOR_END: create_or_use_rocksdb\n\n        launch_custom_provider_and_get_wallets(Default::default(), Some(provider_config), None)\n            .await?;\n\n        Ok(())\n    }\n\n    #[tokio::test]\n    async fn custom_transaction() -> Result<()> {\n        let hot_wallet_signer = PrivateKeySigner::random(&mut thread_rng());\n\n        let code_path = \"../../e2e/sway/predicates/swap/out/release/swap.bin\";\n        let mut predicate = Predicate::load_from(code_path)?;\n\n        let num_coins = 5;\n        let amount = 1000;\n        let bridged_asset_id = AssetId::from([1u8; 32]);\n        let base_coins = setup_single_asset_coins(\n            hot_wallet_signer.address(),\n            AssetId::zeroed(),\n            num_coins,\n            amount,\n        );\n        let other_coins =\n            setup_single_asset_coins(predicate.address(), bridged_asset_id, num_coins, amount);\n\n        let provider = setup_test_provider(\n            base_coins.into_iter().chain(other_coins).collect(),\n            vec![],\n            None,\n            None,\n        )\n        .await?;\n\n        provider.produce_blocks(100, None).await?;\n\n        let hot_wallet = Wallet::new(hot_wallet_signer, provider.clone());\n        let cold_wallet = Wallet::random(&mut thread_rng(), provider.clone());\n        predicate.set_provider(provider.clone());\n\n        // ANCHOR: custom_tx_receiver\n        let ask_amount = 100;\n        let locked_amount = 500;\n        let bridged_asset_id = AssetId::from([1u8; 32]);\n        let receiver =\n            Address::from_str(\"09c0b2d1a486c439a87bcba6b46a7a1a23f3897cc83a94521a96da5c23bc58db\")?;\n        // ANCHOR_END: custom_tx_receiver\n\n        // ANCHOR: custom_tx\n        let tb = ScriptTransactionBuilder::default();\n        // ANCHOR_END: custom_tx\n\n        // ANCHOR: custom_tx_io_base\n        let consensus_parameters = provider.consensus_parameters().await?;\n        let base_inputs = hot_wallet\n            .get_asset_inputs_for_amount(*consensus_parameters.base_asset_id(), ask_amount, None)\n            .await?;\n        let base_outputs = hot_wallet.get_asset_outputs_for_amount(\n            receiver,\n            *consensus_parameters.base_asset_id(),\n            ask_amount as u64,\n        );\n        // ANCHOR_END: custom_tx_io_base\n\n        // ANCHOR: custom_tx_io_other\n        let other_asset_inputs = predicate\n            .get_asset_inputs_for_amount(bridged_asset_id, locked_amount, None)\n            .await?;\n        let other_asset_outputs =\n            predicate.get_asset_outputs_for_amount(cold_wallet.address(), bridged_asset_id, 500);\n        // ANCHOR_END: custom_tx_io_other\n\n        // ANCHOR: custom_tx_io\n        let inputs = base_inputs\n            .into_iter()\n            .chain(other_asset_inputs.into_iter())\n            .collect();\n        let outputs = base_outputs\n            .into_iter()\n            .chain(other_asset_outputs.into_iter())\n            .collect();\n\n        let mut tb = tb.with_inputs(inputs).with_outputs(outputs);\n        // ANCHOR_END: custom_tx_io\n\n        // ANCHOR: custom_tx_add_signer\n        tb.add_signer(hot_wallet.signer().clone())?;\n        // ANCHOR_END: custom_tx_add_signer\n\n        // ANCHOR: custom_tx_adjust\n        hot_wallet.adjust_for_fee(&mut tb, 100).await?;\n        // ANCHOR_END: custom_tx_adjust\n\n        // ANCHOR: custom_tx_policies\n        let tx_policies = TxPolicies::default().with_maturity(64).with_expiration(128);\n        let tb = tb.with_tx_policies(tx_policies);\n        // ANCHOR_END: custom_tx_policies\n\n        // ANCHOR: custom_tx_build\n        let tx = tb.build(&provider).await?;\n        let tx_id = provider.send_transaction(tx).await?;\n        // ANCHOR_END: custom_tx_build\n\n        tokio::time::sleep(Duration::from_millis(500)).await;\n        // ANCHOR: custom_tx_verify\n        let status = provider.tx_status(&tx_id).await?;\n        assert!(matches!(status, TxStatus::Success { .. }));\n\n        let balance: u128 = cold_wallet.get_asset_balance(&bridged_asset_id).await?;\n        assert_eq!(balance, locked_amount);\n        // ANCHOR_END: custom_tx_verify\n\n        Ok(())\n    }\n}\n"
  },
  {
    "path": "examples/debugging/Cargo.toml",
    "content": "[package]\nname = \"fuels-example-debugging\"\nversion = { workspace = true }\nauthors = { workspace = true }\nedition = { workspace = true }\nhomepage = { workspace = true }\nlicense = { workspace = true }\npublish = false\nrepository = { workspace = true }\ndescription = \"Fuel Rust SDK debugging examples.\"\n\n[dev-dependencies]\nfuel-abi-types = { workspace = true }\nfuels = { workspace = true, features = [\"default\"] }\nrand = { workspace = true }\nserde_json = { workspace = true }\ntokio = { workspace = true, features = [\"full\"] }\n"
  },
  {
    "path": "examples/debugging/src/lib.rs",
    "content": "#[cfg(test)]\nmod tests {\n    use std::collections::HashMap;\n\n    use fuel_abi_types::abi::unified_program::UnifiedProgramABI;\n    use fuels::{\n        core::codec::ABIDecoder,\n        macros::abigen,\n        types::{SizedAsciiString, errors::Result, param_types::ParamType},\n    };\n\n    #[test]\n    fn encode_fn_selector() {\n        use fuels::core::codec::encode_fn_selector;\n\n        // ANCHOR: example_fn_selector\n        // fn some_fn_name(arg1: Vec<str[3]>, arg2: u8)\n        let fn_name = \"some_fn_name\";\n\n        let selector = encode_fn_selector(fn_name);\n\n        assert_eq!(\n            selector,\n            [\n                0, 0, 0, 0, 0, 0, 0, 12, 115, 111, 109, 101, 95, 102, 110, 95, 110, 97, 109, 101\n            ]\n        );\n        // ANCHOR_END: example_fn_selector\n    }\n\n    #[test]\n    fn decoded_debug_matches_rust_debug() -> Result<()> {\n        abigen!(Contract(\n            name = \"MyContract\",\n            abi = \"e2e/sway/types/contracts/generics/out/release/generics-abi.json\"\n        ));\n\n        let json_abi_file = \"../../e2e/sway/types/contracts/generics/out/release/generics-abi.json\";\n        let abi_file_contents = std::fs::read_to_string(json_abi_file)?;\n\n        let parsed_abi = UnifiedProgramABI::from_json_abi(&abi_file_contents)?;\n\n        let type_lookup = parsed_abi\n            .types\n            .into_iter()\n            .map(|decl| (decl.type_id, decl))\n            .collect::<HashMap<_, _>>();\n\n        let get_first_fn_argument = |fn_name: &str| {\n            parsed_abi\n                .functions\n                .iter()\n                .find(|abi_fun| abi_fun.name == fn_name)\n                .expect(\"should be there\")\n                .inputs\n                .first()\n                .expect(\"should be there\")\n        };\n        let decoder = ABIDecoder::default();\n\n        {\n            // simple struct with a single generic parameter\n            let type_application = get_first_fn_argument(\"struct_w_generic\");\n            let param_type = ParamType::try_from_type_application(type_application, &type_lookup)?;\n\n            let expected_struct = SimpleGeneric {\n                single_generic_param: 123u64,\n            };\n\n            assert_eq!(\n                format!(\"{expected_struct:?}\"),\n                decoder.decode_as_debug_str(&param_type, [0, 0, 0, 0, 0, 0, 0, 123].as_slice())?\n            );\n        }\n        {\n            // struct that delegates the generic param internally\n            let type_application = get_first_fn_argument(\"struct_delegating_generic\");\n            let param_type = ParamType::try_from_type_application(type_application, &type_lookup)?;\n\n            let expected_struct = PassTheGenericOn {\n                one: SimpleGeneric {\n                    single_generic_param: SizedAsciiString::<3>::try_from(\"abc\")?,\n                },\n            };\n\n            assert_eq!(\n                format!(\"{expected_struct:?}\"),\n                decoder.decode_as_debug_str(&param_type, [97, 98, 99].as_slice())?\n            );\n        }\n        {\n            // enum with generic in variant\n            let type_application = get_first_fn_argument(\"enum_w_generic\");\n            let param_type = ParamType::try_from_type_application(type_application, &type_lookup)?;\n\n            let expected_enum = EnumWGeneric::B(10u64);\n\n            assert_eq!(\n                format!(\"{expected_enum:?}\"),\n                decoder.decode_as_debug_str(\n                    &param_type,\n                    [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 10].as_slice()\n                )?\n            );\n        }\n        {\n            // logged type\n            let logged_type = parsed_abi\n                .logged_types\n                .as_ref()\n                .expect(\"has logs\")\n                .first()\n                .expect(\"has log\");\n\n            let param_type =\n                ParamType::try_from_type_application(&logged_type.application, &type_lookup)?;\n\n            let expected_u8 = 1;\n\n            assert_eq!(\n                format!(\"{expected_u8}\"),\n                decoder.decode_as_debug_str(&param_type, [1].as_slice())?\n            );\n        }\n\n        Ok(())\n    }\n}\n"
  },
  {
    "path": "examples/macros/Cargo.toml",
    "content": "[package]\nname = \"fuels-example-macros\"\nversion = { workspace = true }\nauthors = { workspace = true }\nedition = { workspace = true }\nhomepage = { workspace = true }\nlicense = { workspace = true }\npublish = false\nrepository = { workspace = true }\ndescription = \"Fuel Rust SDK macro examples.\"\n\n[dev-dependencies]\nfuels = { workspace = true, features = [\"default\"] }\ntokio = { workspace = true, features = [\"full\"] }\n"
  },
  {
    "path": "examples/macros/src/lib.rs",
    "content": "extern crate alloc;\n\n#[cfg(test)]\nmod tests {\n    use fuels::prelude::*;\n\n    #[test]\n    fn example_of_abigen_usage() {\n        // ANCHOR: multiple_abigen_program_types\n        abigen!(\n            Contract(\n                name = \"ContractA\",\n                abi = \"e2e/sway/bindings/sharing_types/contract_a/out/release/contract_a-abi.json\"\n            ),\n            Contract(\n                name = \"ContractB\",\n                abi = \"e2e/sway/bindings/sharing_types/contract_b/out/release/contract_b-abi.json\"\n            ),\n            Script(\n                name = \"MyScript\",\n                abi = \"e2e/sway/scripts/arguments/out/release/arguments-abi.json\"\n            ),\n            Predicate(\n                name = \"MyPredicateEncoder\",\n                abi = \"e2e/sway/predicates/basic_predicate/out/release/basic_predicate-abi.json\"\n            ),\n        );\n        // ANCHOR_END: multiple_abigen_program_types\n    }\n\n    #[test]\n    fn macro_deriving() {\n        // ANCHOR: deriving_traits\n        use fuels::macros::{Parameterize, Tokenizable};\n\n        #[derive(Parameterize, Tokenizable)]\n        #[allow(dead_code)]\n        struct MyStruct {\n            field_a: u8,\n        }\n\n        #[derive(Parameterize, Tokenizable)]\n        #[allow(dead_code)]\n        enum SomeEnum {\n            A(MyStruct),\n            B(Vec<u64>),\n        }\n        // ANCHOR_END: deriving_traits\n    }\n    #[test]\n    fn macro_deriving_extra() {\n        {\n            use fuels::{\n                core as fuels_core_elsewhere,\n                macros::{Parameterize, Tokenizable},\n                types as fuels_types_elsewhere,\n            };\n\n            // ANCHOR: deriving_traits_paths\n            #[derive(Parameterize, Tokenizable)]\n            #[FuelsCorePath = \"fuels_core_elsewhere\"]\n            #[FuelsTypesPath = \"fuels_types_elsewhere\"]\n            #[allow(dead_code)]\n            pub struct SomeStruct {\n                field_a: u64,\n            }\n            // ANCHOR_END: deriving_traits_paths\n        }\n        {\n            // ANCHOR: deriving_traits_nostd\n            use fuels::macros::{Parameterize, Tokenizable};\n            #[derive(Parameterize, Tokenizable)]\n            #[NoStd]\n            #[allow(dead_code)]\n            pub struct SomeStruct {\n                field_a: u64,\n            }\n            // ANCHOR_END: deriving_traits_nostd\n        }\n    }\n}\n"
  },
  {
    "path": "examples/predicates/Cargo.toml",
    "content": "[package]\nname = \"fuels-example-predicates\"\nversion = { workspace = true }\nauthors = { workspace = true }\nedition = { workspace = true }\nhomepage = { workspace = true }\nlicense = { workspace = true }\npublish = false\nrepository = { workspace = true }\ndescription = \"Fuel Rust SDK predicate examples.\"\n\n[dev-dependencies]\nfuels = { workspace = true, features = [\"default\"] }\nrand = { workspace = true }\ntokio = { workspace = true, features = [\"full\"] }\n"
  },
  {
    "path": "examples/predicates/src/lib.rs",
    "content": "#[cfg(test)]\nmod tests {\n    use fuels::{\n        accounts::{Account, predicate::Predicate, signers::private_key::PrivateKeySigner},\n        crypto::Message,\n        prelude::*,\n        types::B512,\n    };\n    use rand::thread_rng;\n\n    #[tokio::test]\n    async fn predicate_example() -> Result<()> {\n        // ANCHOR: predicate_signers\n        let wallet_signer = PrivateKeySigner::new(\n            \"0x862512a2363db2b3a375c0d4bbbd27172180d89f23f2e259bac850ab02619301\".parse()?,\n        );\n        let wallet2_signer = PrivateKeySigner::new(\n            \"0x37fa81c84ccd547c30c176b118d5cb892bdb113e8e80141f266519422ef9eefd\".parse()?,\n        );\n        let wallet3_signer = PrivateKeySigner::new(\n            \"0x976e5c3fa620092c718d852ca703b6da9e3075b9f2ecb8ed42d9f746bf26aafb\".parse()?,\n        );\n        let receiver_signer = PrivateKeySigner::random(&mut thread_rng());\n        // ANCHOR_END: predicate_signers\n\n        // ANCHOR: predicate_coins\n        let asset_id = AssetId::zeroed();\n        let num_coins = 32;\n        let amount = 64;\n        let initial_balance = amount * num_coins;\n        let all_coins = [\n            &wallet_signer,\n            &wallet2_signer,\n            &wallet3_signer,\n            &receiver_signer,\n        ]\n        .iter()\n        .flat_map(|signer| setup_single_asset_coins(signer.address(), asset_id, num_coins, amount))\n        .collect::<Vec<_>>();\n\n        let provider = setup_test_provider(all_coins, vec![], None, None).await?;\n\n        let wallet = Wallet::new(wallet_signer, provider.clone());\n        let wallet2 = Wallet::new(wallet2_signer, provider.clone());\n        let wallet3 = Wallet::new(wallet3_signer, provider.clone());\n        let receiver = Wallet::new(receiver_signer, provider.clone());\n        // ANCHOR_END: predicate_coins\n\n        let data_to_sign = Message::new([0; 32]);\n        let signature1: B512 = wallet\n            .signer()\n            .sign(data_to_sign)\n            .await?\n            .as_ref()\n            .try_into()?;\n        let signature2: B512 = wallet2\n            .signer()\n            .sign(data_to_sign)\n            .await?\n            .as_ref()\n            .try_into()?;\n        let signature3: B512 = wallet3\n            .signer()\n            .sign(data_to_sign)\n            .await?\n            .as_ref()\n            .try_into()?;\n\n        let signatures = [signature1, signature2, signature3];\n\n        // ANCHOR: predicate_load\n        abigen!(Predicate(\n            name = \"MyPredicate\",\n            abi = \"e2e/sway/predicates/signatures/out/release/signatures-abi.json\"\n        ));\n\n        let predicate_data = MyPredicateEncoder::default().encode_data(signatures)?;\n        let code_path = \"../../e2e/sway/predicates/signatures/out/release/signatures.bin\";\n\n        let predicate: Predicate = Predicate::load_from(code_path)?\n            .with_provider(provider)\n            .with_data(predicate_data);\n        // ANCHOR_END: predicate_load\n\n        // ANCHOR: predicate_receive\n        let amount_to_predicate = 500;\n\n        wallet\n            .transfer(\n                predicate.address(),\n                amount_to_predicate,\n                asset_id,\n                TxPolicies::default(),\n            )\n            .await?;\n\n        let predicate_balance = predicate.get_asset_balance(&asset_id).await?;\n        assert_eq!(predicate_balance, amount_to_predicate as u128);\n        // ANCHOR_END: predicate_receive\n\n        // ANCHOR: predicate_spend\n        let amount_to_receiver = 300;\n        predicate\n            .transfer(\n                receiver.address(),\n                amount_to_receiver,\n                asset_id,\n                TxPolicies::default(),\n            )\n            .await?;\n\n        let receiver_balance_after = receiver.get_asset_balance(&asset_id).await?;\n        assert_eq!(\n            (initial_balance + amount_to_receiver) as u128,\n            receiver_balance_after\n        );\n        // ANCHOR_END: predicate_spend\n\n        Ok(())\n    }\n\n    #[tokio::test]\n    async fn predicate_data_example() -> Result<()> {\n        // ANCHOR: predicate_data_setup\n        let asset_id = AssetId::zeroed();\n        let wallets_config = WalletsConfig::new_multiple_assets(\n            2,\n            vec![AssetConfig {\n                id: asset_id,\n                num_coins: 1,\n                coin_amount: 1_000,\n            }],\n        );\n\n        let wallets = &launch_custom_provider_and_get_wallets(wallets_config, None, None).await?;\n\n        let first_wallet = &wallets[0];\n        let second_wallet = &wallets[1];\n\n        abigen!(Predicate(\n            name = \"MyPredicate\",\n            abi = \"e2e/sway/predicates/basic_predicate/out/release/basic_predicate-abi.json\"\n        ));\n        // ANCHOR_END: predicate_data_setup\n\n        // ANCHOR: with_predicate_data\n        let predicate_data = MyPredicateEncoder::default().encode_data(4096, 4096)?;\n        let code_path = \"../../e2e/sway/predicates/basic_predicate/out/release/basic_predicate.bin\";\n\n        let predicate: Predicate = Predicate::load_from(code_path)?\n            .with_provider(first_wallet.provider().clone())\n            .with_data(predicate_data);\n        // ANCHOR_END: with_predicate_data\n\n        // ANCHOR: predicate_data_lock_amount\n        // First wallet transfers amount to predicate.\n        first_wallet\n            .transfer(predicate.address(), 500, asset_id, TxPolicies::default())\n            .await?;\n\n        // Check predicate balance.\n        let balance = predicate.get_asset_balance(&AssetId::zeroed()).await?;\n\n        assert_eq!(balance, 500);\n        // ANCHOR_END: predicate_data_lock_amount\n\n        // ANCHOR: predicate_data_unlock\n        let amount_to_unlock = 300;\n\n        predicate\n            .transfer(\n                second_wallet.address(),\n                amount_to_unlock,\n                asset_id,\n                TxPolicies::default(),\n            )\n            .await?;\n\n        // Second wallet balance is updated.\n        let balance = second_wallet.get_asset_balance(&AssetId::zeroed()).await?;\n        assert_eq!(balance, 1300);\n        // ANCHOR_END: predicate_data_unlock\n        Ok(())\n    }\n}\n"
  },
  {
    "path": "examples/providers/Cargo.toml",
    "content": "[package]\nname = \"fuels-example-providers\"\nversion = { workspace = true }\nauthors = { workspace = true }\nedition = { workspace = true }\nhomepage = { workspace = true }\nlicense = { workspace = true }\npublish = false\nrepository = { workspace = true }\ndescription = \"Fuel Rust SDK provider examples.\"\n\n[dev-dependencies]\nfuels = { workspace = true, features = [\"default\"] }\nrand = { workspace = true }\ntokio = { workspace = true, features = [\"full\"] }\n"
  },
  {
    "path": "examples/providers/src/lib.rs",
    "content": "#[cfg(test)]\nmod tests {\n    use std::time::Duration;\n\n    use fuels::{accounts::signers::private_key::PrivateKeySigner, prelude::Result};\n\n    #[ignore = \"testnet currently not compatible with the sdk\"]\n    #[tokio::test]\n    async fn connect_to_fuel_node() -> Result<()> {\n        // ANCHOR: connect_to_testnet\n        use std::str::FromStr;\n\n        use fuels::{crypto::SecretKey, prelude::*};\n\n        // Create a provider pointing to the testnet.\n        let provider = Provider::connect(\"testnet.fuel.network\").await.unwrap();\n\n        // Setup a private key\n        let secret = SecretKey::from_str(\n            \"a1447cd75accc6b71a976fd3401a1f6ce318d27ba660b0315ee6ac347bf39568\",\n        )?;\n\n        // Create the wallet\n        let wallet = Wallet::new(PrivateKeySigner::new(secret), provider);\n\n        // Get the wallet address. Used later with the faucet\n        dbg!(wallet.address().to_string());\n        // ANCHOR_END: connect_to_testnet\n\n        let provider = setup_test_provider(vec![], vec![], None, None).await?;\n        let port = provider.url().split(':').next_back().unwrap();\n\n        // ANCHOR: local_node_address\n        let _provider = Provider::connect(format!(\"127.0.0.1:{port}\")).await?;\n        // ANCHOR_END: local_node_address\n\n        Ok(())\n    }\n    #[tokio::test]\n    async fn query_the_blockchain() -> Result<()> {\n        // ANCHOR: setup_test_blockchain\n        use fuels::prelude::*;\n\n        // Set up our test blockchain.\n\n        // Create a random signer\n        // ANCHOR: setup_single_asset\n        let wallet_signer = PrivateKeySigner::random(&mut rand::thread_rng());\n\n        // How many coins in our wallet.\n        let number_of_coins = 1;\n\n        // The amount/value in each coin in our wallet.\n        let amount_per_coin = 3;\n\n        let coins = setup_single_asset_coins(\n            wallet_signer.address(),\n            AssetId::zeroed(),\n            number_of_coins,\n            amount_per_coin,\n        );\n        // ANCHOR_END: setup_single_asset\n\n        // ANCHOR: configure_retry\n        let retry_config = RetryConfig::new(3, Backoff::Fixed(Duration::from_secs(2)))?;\n        let provider = setup_test_provider(coins.clone(), vec![], None, None)\n            .await?\n            .with_retry_config(retry_config);\n        // ANCHOR_END: configure_retry\n        // ANCHOR_END: setup_test_blockchain\n\n        // ANCHOR: get_coins\n        let consensus_parameters = provider.consensus_parameters().await?;\n        let coins = provider\n            .get_coins(\n                &wallet_signer.address(),\n                *consensus_parameters.base_asset_id(),\n            )\n            .await?;\n        assert_eq!(coins.len(), 1);\n        // ANCHOR_END: get_coins\n\n        // ANCHOR: get_spendable_resources\n        let filter = ResourceFilter {\n            from: wallet_signer.address(),\n            amount: 1,\n            ..Default::default()\n        };\n        let spendable_resources = provider.get_spendable_resources(filter).await?;\n        assert_eq!(spendable_resources.len(), 1);\n        // ANCHOR_END: get_spendable_resources\n\n        // ANCHOR: get_balances\n        let _balances = provider.get_balances(&wallet_signer.address()).await?;\n        // ANCHOR_END: get_balances\n\n        Ok(())\n    }\n}\n"
  },
  {
    "path": "examples/rust_bindings/Cargo.toml",
    "content": "[package]\nname = \"fuels-example-rust-bindings\"\nversion = { workspace = true }\nauthors = { workspace = true }\nedition = { workspace = true }\nhomepage = { workspace = true }\nlicense = { workspace = true }\npublish = false\nrepository = { workspace = true }\ndescription = \"Fuel Rust SDK examples for Rust-native bindings\"\n\n[dev-dependencies]\nfuels = { workspace = true, features = [\"default\"] }\nfuels-code-gen = { workspace = true }\nfuels-macros = { workspace = true }\nproc-macro2 = { workspace = true }\nrand = { workspace = true }\ntokio = { workspace = true, features = [\"full\"] }\n"
  },
  {
    "path": "examples/rust_bindings/src/abi.json",
    "content": "{\n  \"programType\": \"contract\",\n  \"specVersion\": \"1\",\n  \"encodingVersion\": \"1\",\n  \"concreteTypes\": [\n    {\n      \"concreteTypeId\": \"1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0\",\n      \"type\": \"u64\"\n    }\n  ],\n  \"functions\": [\n    {\n      \"inputs\": [\n        {\n          \"name\": \"value\",\n          \"concreteTypeId\": \"1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0\"\n        }\n      ],\n      \"name\": \"initialize_counter\",\n      \"output\": \"1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0\"\n    },\n    {\n      \"inputs\": [\n        {\n          \"name\": \"value\",\n          \"concreteTypeId\": \"1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0\"\n        }\n      ],\n      \"name\": \"increment_counter\",\n      \"output\": \"1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0\"\n    }\n  ],\n  \"metadataTypes\": []\n}\n"
  },
  {
    "path": "examples/rust_bindings/src/lib.rs",
    "content": "#[cfg(test)]\nmod tests {\n    use fuels::prelude::Result;\n\n    #[tokio::test]\n    #[allow(unused_variables)]\n    async fn transform_json_to_bindings() -> Result<()> {\n        use fuels::test_helpers::launch_provider_and_get_wallet;\n        let wallet = launch_provider_and_get_wallet().await?;\n        {\n            // ANCHOR: use_abigen\n            use fuels::prelude::*;\n            // Replace with your own JSON abi path (relative to the root of your crate)\n            abigen!(Contract(\n                name = \"MyContractName\",\n                abi = \"examples/rust_bindings/src/abi.json\"\n            ));\n            // ANCHOR_END: use_abigen\n        }\n\n        {\n            // ANCHOR: abigen_with_string\n            use fuels::prelude::*;\n            abigen!(Contract(\n                name = \"MyContract\",\n                abi = r#\"\n            {\n              \"programType\": \"contract\",\n              \"specVersion\": \"1\",\n              \"encodingVersion\": \"1\",\n              \"concreteTypes\": [\n                {\n                  \"concreteTypeId\": \"1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0\",\n                  \"type\": \"u64\"\n                }\n              ],\n              \"functions\": [\n                {\n                  \"inputs\": [\n                    {\n                      \"name\": \"value\",\n                      \"concreteTypeId\": \"1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0\"\n                    }\n                  ],\n                  \"name\": \"initialize_counter\",\n                  \"output\": \"1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0\"\n                },\n                {\n                  \"inputs\": [\n                    {\n                      \"name\": \"value\",\n                      \"concreteTypeId\": \"1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0\"\n                    }\n                  ],\n                  \"name\": \"increment_counter\",\n                  \"output\": \"1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0\"\n                }\n              ],\n              \"metadataTypes\": []\n            }\n            \"#\n            ));\n            // ANCHOR_END: abigen_with_string\n        }\n        Ok(())\n    }\n}\n"
  },
  {
    "path": "examples/rust_bindings/src/rust_bindings_formatted.rs",
    "content": "pub mod abigen_bindings {\n    pub mod my_contract_mod {\n        #[derive(Debug, Clone)]\n        pub struct MyContract<A: ::fuels::accounts::Account> {\n            contract_id: ::fuels::types::ContractId,\n            account: A,\n            log_decoder: ::fuels::core::codec::LogDecoder,\n            encoder_config: ::fuels::core::codec::EncoderConfig,\n        }\n        impl<A: ::fuels::accounts::Account> MyContract<A> {\n            pub fn new(contract_id: ::fuels::types::ContractId, account: A) -> Self {\n                let log_decoder = ::fuels::core::codec::LogDecoder::new(\n                    ::fuels::core::codec::log_formatters_lookup(vec![], contract_id.clone().into()),\n                );\n                let encoder_config = ::fuels::core::codec::EncoderConfig::default();\n                Self {\n                    contract_id,\n                    account,\n                    log_decoder,\n                    encoder_config,\n                }\n            }\n            pub fn contract_id(&self) -> &::fuels::types::ContractId {\n                self.contract_id\n            }\n            pub fn account(&self) -> A {\n                self.account.clone()\n            }\n            pub fn with_account<U: ::fuels::accounts::Account>(self, account: U) -> MyContract<U> {\n                MyContract {\n                    contract_id: self.contract_id,\n                    account,\n                    log_decoder: self.log_decoder,\n                    encoder_config: self.encoder_config,\n                }\n            }\n            pub fn with_encoder_config(\n                mut self,\n                encoder_config: ::fuels::core::codec::EncoderConfig,\n            ) -> MyContract<A> {\n                self.encoder_config = encoder_config;\n                self\n            }\n            pub async fn get_balances(\n                &self,\n            ) -> ::fuels::types::errors::Result<\n                ::std::collections::HashMap<::fuels::types::AssetId, u64>,\n            > {\n                ::fuels::accounts::ViewOnlyAccount::try_provider(&self.account)?\n                    .get_contract_balances(&self.contract_id)\n                    .await\n                    .map_err(::std::convert::Into::into)\n            }\n            pub fn methods(&self) -> MyContractMethods<A> {\n                MyContractMethods {\n                    contract_id: self.contract_id.clone(),\n                    account: self.account.clone(),\n                    log_decoder: self.log_decoder.clone(),\n                    encoder_config: self.encoder_config.clone(),\n                }\n            }\n        }\n        pub struct MyContractMethods<A: ::fuels::accounts::Account> {\n            contract_id: ::fuels::types::ContractId,\n            account: A,\n            log_decoder: ::fuels::core::codec::LogDecoder,\n            encoder_config: ::fuels::core::codec::EncoderConfig,\n        }\n        impl<A: ::fuels::accounts::Account> MyContractMethods<A> {\n            #[doc = \" This method will read the counter from storage, increment it\"]\n            #[doc = \" and write the incremented value to storage\"]\n            pub fn increment_counter(\n                &self,\n                value: ::core::primitive::u64,\n            ) -> ::fuels::programs::calls::CallHandler<\n                A,\n                ::fuels::programs::calls::ContractCall,\n                ::core::primitive::u64,\n            > {\n                ::fuels::programs::calls::CallHandler::new_contract_call(\n                    self.contract_id.clone(),\n                    self.account.clone(),\n                    ::fuels::core::codec::encode_fn_selector(\"increment_counter\"),\n                    &[::fuels::core::traits::Tokenizable::into_token(value)],\n                    self.log_decoder.clone(),\n                    false,\n                    self.encoder_config.clone(),\n                )\n            }\n            pub fn initialize_counter(\n                &self,\n                value: ::core::primitive::u64,\n            ) -> ::fuels::programs::calls::CallHandler<\n                A,\n                ::fuels::programs::calls::ContractCall,\n                ::core::primitive::u64,\n            > {\n                ::fuels::programs::calls::CallHandler::new_contract_call(\n                    self.contract_id.clone(),\n                    self.account.clone(),\n                    ::fuels::core::codec::encode_fn_selector(\"initialize_counter\"),\n                    &[::fuels::core::traits::Tokenizable::into_token(value)],\n                    self.log_decoder.clone(),\n                    false,\n                    self.encoder_config.clone(),\n                )\n            }\n        }\n        impl<A: ::fuels::accounts::Account> ::fuels::programs::calls::ContractDependency for MyContract<A> {\n            fn id(&self) -> ::fuels::types::ContractId {\n                self.contract_id.clone()\n            }\n            fn log_decoder(&self) -> ::fuels::core::codec::LogDecoder {\n                self.log_decoder.clone()\n            }\n        }\n        #[derive(Clone, Debug, Default)]\n        pub struct MyContractConfigurables {\n            offsets_with_data: ::std::vec::Vec<(u64, ::std::vec::Vec<u8>)>,\n            encoder: ::fuels::core::codec::ABIEncoder,\n        }\n        impl MyContractConfigurables {\n            pub fn new(encoder_config: ::fuels::core::codec::EncoderConfig) -> Self {\n                Self {\n                    encoder: ::fuels::core::codec::ABIEncoder::new(encoder_config),\n                    ..::std::default::Default::default()\n                }\n            }\n        }\n        impl From<MyContractConfigurables> for ::fuels::core::Configurables {\n            fn from(config: MyContractConfigurables) -> Self {\n                ::fuels::core::Configurables::new(config.offsets_with_data)\n            }\n        }\n    }\n}\npub use abigen_bindings::my_contract_mod::MyContract;\npub use abigen_bindings::my_contract_mod::MyContractConfigurables;\npub use abigen_bindings::my_contract_mod::MyContractMethods;\n"
  },
  {
    "path": "examples/types/Cargo.toml",
    "content": "[package]\nname = \"fuels-example-types\"\nversion = { workspace = true }\nauthors = { workspace = true }\nedition = { workspace = true }\nhomepage = { workspace = true }\nlicense = { workspace = true }\npublish = false\nrepository = { workspace = true }\ndescription = \"Fuel Rust SDK types examples.\"\n\n[dev-dependencies]\nfuels = { workspace = true, features = [\"default\"] }\nrand = { workspace = true }\ntokio = { workspace = true, features = [\"full\"] }\n"
  },
  {
    "path": "examples/types/src/lib.rs",
    "content": "#[cfg(test)]\nmod tests {\n    use fuels::{\n        prelude::Result,\n        types::{Bits256, EvmAddress, Identity},\n    };\n\n    #[tokio::test]\n    async fn bytes32() -> Result<()> {\n        // ANCHOR: bytes32\n        use std::str::FromStr;\n\n        use fuels::types::Bytes32;\n\n        // Zeroed Bytes32\n        let b256 = Bytes32::zeroed();\n\n        // Grab the inner `[u8; 32]` from\n        // `Bytes32` by dereferencing (i.e. `*`) it.\n        assert_eq!([0u8; 32], *b256);\n\n        // From a `[u8; 32]`.\n        // ANCHOR: array_to_bytes32\n        let my_slice = [1u8; 32];\n        let b256 = Bytes32::new(my_slice);\n        // ANCHOR_END: array_to_bytes32\n        assert_eq!([1u8; 32], *b256);\n\n        // From a hex string.\n        // ANCHOR: hex_string_to_bytes32\n        let hex_str = \"0x0000000000000000000000000000000000000000000000000000000000000000\";\n        let b256 = Bytes32::from_str(hex_str)?;\n        // ANCHOR_END: hex_string_to_bytes32\n        assert_eq!([0u8; 32], *b256);\n        // ANCHOR_END: bytes32\n\n        // ANCHOR: bytes32_format\n        let b256_string = b256.to_string();\n        let b256_hex_string = format!(\"{b256:#x}\");\n        // ANCHOR_END: bytes32_format\n\n        assert_eq!(hex_str[2..], b256_string);\n        assert_eq!(hex_str, b256_hex_string);\n\n        // ANCHOR: bytes32_to_str\n        let _str_from_bytes32: &str = b256.to_string().as_str();\n        // ANCHOR_END: bytes32_to_str\n\n        Ok(())\n    }\n    #[tokio::test]\n    async fn address() -> Result<()> {\n        // ANCHOR: address\n        use std::str::FromStr;\n\n        use fuels::types::Address;\n\n        // Zeroed Bytes32\n        let address = Address::zeroed();\n\n        // Grab the inner `[u8; 32]` from\n        // `Bytes32` by dereferencing (i.e. `*`) it.\n        assert_eq!([0u8; 32], *address);\n\n        // From a `[u8; 32]`.\n        // ANCHOR: array_to_address\n        let my_slice = [1u8; 32];\n        let address = Address::new(my_slice);\n        // ANCHOR_END: array_to_address\n        assert_eq!([1u8; 32], *address);\n\n        // From a string.\n        // ANCHOR: hex_string_to_address\n        let hex_str = \"0x0000000000000000000000000000000000000000000000000000000000000000\";\n        let address = Address::from_str(hex_str)?;\n        // ANCHOR_END: hex_string_to_address\n        assert_eq!([0u8; 32], *address);\n        // ANCHOR_END: address\n\n        // ANCHOR: address_to_identity\n        let _identity_from_address = Identity::Address(address);\n        // ANCHOR_END: address_to_identity\n\n        // ANCHOR: address_to_str\n        let _str_from_address: &str = address.to_string().as_str();\n        // ANCHOR_END: address_to_str\n\n        // ANCHOR: address_to_bits256\n        let bits_256 = Bits256(address.into());\n        // ANCHOR_END: address_to_bits256\n\n        // ANCHOR: b256_to_evm_address\n        let _evm_address = EvmAddress::from(bits_256);\n        // ANCHOR_END: b256_to_evm_address\n\n        Ok(())\n    }\n\n    #[tokio::test]\n    async fn asset_id() -> Result<()> {\n        // ANCHOR: asset_id\n        use std::str::FromStr;\n\n        use fuels::types::AssetId;\n\n        // Zeroed Bytes32\n        let asset_id = AssetId::zeroed();\n\n        // Grab the inner `[u8; 32]` from\n        // `Bytes32` by dereferencing (i.e. `*`) it.\n        assert_eq!([0u8; 32], *asset_id);\n\n        // From a `[u8; 32]`.\n        // ANCHOR: array_to_asset_id\n        let my_slice = [1u8; 32];\n        let asset_id = AssetId::new(my_slice);\n        // ANCHOR_END: array_to_asset_id\n        assert_eq!([1u8; 32], *asset_id);\n\n        // From a string.\n        // ANCHOR: string_to_asset_id\n        let hex_str = \"0x0000000000000000000000000000000000000000000000000000000000000000\";\n        let asset_id = AssetId::from_str(hex_str)?;\n        // ANCHOR_END: string_to_asset_id\n        assert_eq!([0u8; 32], *asset_id);\n        // ANCHOR_END: asset_id\n        Ok(())\n    }\n\n    #[tokio::test]\n    async fn contract_id() -> Result<()> {\n        // ANCHOR: contract_id\n        use std::str::FromStr;\n\n        use fuels::types::ContractId;\n\n        // Zeroed Bytes32\n        let contract_id = ContractId::zeroed();\n\n        // Grab the inner `[u8; 32]` from\n        // `Bytes32` by dereferencing (i.e. `*`) it.\n        assert_eq!([0u8; 32], *contract_id);\n\n        // From a `[u8; 32]`.\n        // ANCHOR: array_to_contract_id\n        let my_slice = [1u8; 32];\n        let contract_id = ContractId::new(my_slice);\n        // ANCHOR_END: array_to_contract_id\n        assert_eq!([1u8; 32], *contract_id);\n\n        // From a string.\n        // ANCHOR: string_to_contract_id\n        let hex_str = \"0x0000000000000000000000000000000000000000000000000000000000000000\";\n        let contract_id = ContractId::from_str(hex_str)?;\n        // ANCHOR_END: string_to_contract_id\n        assert_eq!([0u8; 32], *contract_id);\n        // ANCHOR_END: contract_id\n\n        // ANCHOR: contract_id_to_identity\n        let _identity_from_contract_id = Identity::ContractId(contract_id);\n        // ANCHOR_END: contract_id_to_identity\n\n        // ANCHOR: contract_id_to_str\n        let _str_from_contract_id: &str = contract_id.to_string().as_str();\n        // ANCHOR_END: contract_id_to_str\n\n        Ok(())\n    }\n\n    #[tokio::test]\n    async fn type_conversion() -> Result<()> {\n        // ANCHOR: type_conversion\n        use fuels::types::{AssetId, ContractId};\n\n        let contract_id = ContractId::new([1u8; 32]);\n\n        let asset_id: AssetId = AssetId::new(*contract_id);\n\n        assert_eq!([1u8; 32], *asset_id);\n        // ANCHOR_END: type_conversion\n\n        // ANCHOR: asset_id_to_str\n        let _str_from_asset_id: &str = asset_id.to_string().as_str();\n        // ANCHOR_END: asset_id_to_str\n\n        // ANCHOR: contract_id_to_bits256\n        let _contract_id_to_bits_256 = Bits256(contract_id.into());\n        // ANCHOR_END: contract_id_to_bits256\n\n        // ANCHOR: asset_id_to_bits256\n        let _asset_id_to_bits_256 = Bits256(asset_id.into());\n        // ANCHOR_END: asset_id_to_bits256\n\n        Ok(())\n    }\n\n    #[tokio::test]\n    async fn unused_generics() -> Result<()> {\n        use fuels::prelude::*;\n        abigen!(Contract(\n            name = \"MyContract\",\n            abi = \"e2e/sway/types/contracts/generics/out/release/generics-abi.json\"\n        ));\n\n        // ANCHOR: unused_generics_struct\n        assert_eq!(\n            <StructUnusedGeneric<u16, u32>>::new(15),\n            StructUnusedGeneric {\n                field: 15,\n                _unused_generic_0: std::marker::PhantomData,\n                _unused_generic_1: std::marker::PhantomData\n            }\n        );\n        // ANCHOR_END: unused_generics_struct\n\n        let my_enum = <EnumUnusedGeneric<u32, u64>>::One(15);\n        // ANCHOR: unused_generics_enum\n        match my_enum {\n            EnumUnusedGeneric::One(_value) => {}\n            EnumUnusedGeneric::IgnoreMe(..) => panic!(\"Will never receive this variant\"),\n        }\n        // ANCHOR_END: unused_generics_enum\n\n        Ok(())\n    }\n}\n"
  },
  {
    "path": "examples/wallets/Cargo.toml",
    "content": "[package]\nname = \"fuels-example-wallets\"\nversion = { workspace = true }\nauthors = { workspace = true }\nedition = { workspace = true }\nhomepage = { workspace = true }\nlicense = { workspace = true }\npublish = false\nrepository = { workspace = true }\ndescription = \"Fuel Rust SDK wallet examples.\"\n\n[dev-dependencies]\nfuels = { workspace = true, features = [\"default\", \"accounts-keystore\"] }\nrand = { workspace = true }\ntokio = { workspace = true, features = [\"full\"] }\n"
  },
  {
    "path": "examples/wallets/src/lib.rs",
    "content": "#[cfg(test)]\nmod tests {\n    use fuels::{\n        accounts::{\n            keystore::Keystore,\n            signers::{derivation::DEFAULT_DERIVATION_PATH, private_key::PrivateKeySigner},\n        },\n        crypto::SecretKey,\n        prelude::*,\n    };\n    use rand::thread_rng;\n\n    #[tokio::test]\n    async fn create_random_wallet() -> Result<()> {\n        // ANCHOR: create_random_wallet\n        use fuels::prelude::*;\n\n        // Use the test helper to setup a test provider.\n        let provider = setup_test_provider(vec![], vec![], None, None).await?;\n\n        // Create the wallet.\n        let _wallet = Wallet::random(&mut thread_rng(), provider);\n        // ANCHOR_END: create_random_wallet\n\n        Ok(())\n    }\n\n    #[tokio::test]\n    async fn create_wallet_from_secret_key() -> std::result::Result<(), Box<dyn std::error::Error>>\n    {\n        // ANCHOR: create_wallet_from_secret_key\n        use std::str::FromStr;\n\n        use fuels::{crypto::SecretKey, prelude::*};\n\n        // Use the test helper to setup a test provider.\n        let provider = setup_test_provider(vec![], vec![], None, None).await?;\n\n        // Setup the private key.\n        let secret = SecretKey::from_str(\n            \"5f70feeff1f229e4a95e1056e8b4d80d0b24b565674860cc213bdb07127ce1b1\",\n        )?;\n\n        // Create the wallet.\n        let _wallet = Wallet::new(PrivateKeySigner::new(secret), provider);\n        // ANCHOR_END: create_wallet_from_secret_key\n        Ok(())\n    }\n\n    #[tokio::test]\n    async fn create_wallet_from_mnemonic() -> Result<()> {\n        // ANCHOR: create_wallet_from_mnemonic\n        use fuels::prelude::*;\n\n        let phrase =\n            \"oblige salon price punch saddle immune slogan rare snap desert retire surprise\";\n\n        // Use the test helper to setup a test provider.\n        let provider = setup_test_provider(vec![], vec![], None, None).await?;\n\n        // Create first account from mnemonic phrase.\n        let key =\n            SecretKey::new_from_mnemonic_phrase_with_path(phrase, \"m/44'/1179993420'/0'/0/0\")?;\n        let signer = PrivateKeySigner::new(key);\n        let _wallet = Wallet::new(signer, provider.clone());\n\n        // Or with the default derivation path.\n        let key = SecretKey::new_from_mnemonic_phrase_with_path(phrase, DEFAULT_DERIVATION_PATH)?;\n        let signer = PrivateKeySigner::new(key);\n        let wallet = Wallet::new(signer, provider);\n\n        let expected_address = \"f18b6446deb8135544ba60333e5b7522685cd2cf64aa4e4c75df725149850b65\";\n\n        assert_eq!(wallet.address().to_string(), expected_address);\n        // ANCHOR_END: create_wallet_from_mnemonic\n        Ok(())\n    }\n\n    #[tokio::test]\n    async fn create_and_store_mnemonic_key() -> Result<()> {\n        // ANCHOR: create_and_store_mnemonic_key\n        let dir = std::env::temp_dir();\n        let keystore = Keystore::new(&dir);\n\n        let phrase =\n            \"oblige salon price punch saddle immune slogan rare snap desert retire surprise\";\n\n        // Create a key from the mnemonic phrase using the default derivation path.\n        let key = SecretKey::new_from_mnemonic_phrase_with_path(phrase, DEFAULT_DERIVATION_PATH)?;\n        let password = \"my_master_password\";\n\n        // Encrypt and store the key on disk. It can be recovered using `Keystore::load_key`.\n        let uuid = keystore.save_key(key, password, thread_rng())?;\n\n        // Recover key from disk\n        let recovered_key = keystore.load_key(&uuid, password)?;\n        // ANCHOR_END: create_and_store_mnemonic_key\n\n        assert_eq!(key, recovered_key);\n        Ok(())\n    }\n\n    #[tokio::test]\n    async fn wallet_transfer() -> Result<()> {\n        // ANCHOR: wallet_transfer\n        use fuels::prelude::*;\n\n        // Setup 2 test wallets with 1 coin each.\n        let num_wallets = 2;\n        let coins_per_wallet = 1;\n        let coin_amount = 2;\n\n        let wallets = launch_custom_provider_and_get_wallets(\n            WalletsConfig::new(Some(num_wallets), Some(coins_per_wallet), Some(coin_amount)),\n            None,\n            None,\n        )\n        .await?;\n\n        // Transfer the base asset with amount 1 from wallet 1 to wallet 2.\n        let transfer_amount = 1;\n        let asset_id = Default::default();\n        let _res = wallets[0]\n            .transfer(\n                wallets[1].address(),\n                transfer_amount,\n                asset_id,\n                TxPolicies::default(),\n            )\n            .await?;\n\n        let wallet_2_final_coins = wallets[1].get_coins(AssetId::zeroed()).await?;\n\n        // Check that wallet 2 now has 2 coins.\n        assert_eq!(wallet_2_final_coins.len(), 2);\n        // ANCHOR_END: wallet_transfer\n        Ok(())\n    }\n\n    #[tokio::test]\n    async fn wallet_contract_transfer() -> Result<()> {\n        use fuels::prelude::*;\n        use rand::Fill;\n\n        let mut rng = rand::thread_rng();\n\n        let base_asset = AssetConfig {\n            id: AssetId::zeroed(),\n            num_coins: 1,\n            coin_amount: 1000,\n        };\n\n        let mut random_asset_id = AssetId::zeroed();\n        random_asset_id.try_fill(&mut rng).unwrap();\n        let random_asset = AssetConfig {\n            id: random_asset_id,\n            num_coins: 3,\n            coin_amount: 100,\n        };\n\n        let wallet_config = WalletsConfig::new_multiple_assets(1, vec![random_asset, base_asset]);\n        let wallet = launch_custom_provider_and_get_wallets(wallet_config, None, None)\n            .await?\n            .pop()\n            .unwrap();\n\n        let contract_id = Contract::load_from(\n            \"../../e2e/sway/contracts/contract_test/out/release/contract_test.bin\",\n            LoadConfiguration::default(),\n        )?\n        .deploy(&wallet, TxPolicies::default())\n        .await?\n        .contract_id;\n\n        // ANCHOR: wallet_contract_transfer\n        // Check the current balance of the contract with id 'contract_id'.\n        let contract_balances = wallet\n            .try_provider()?\n            .get_contract_balances(&contract_id)\n            .await?;\n        assert!(contract_balances.is_empty());\n\n        // Transfer an amount of 300 to the contract.\n        let amount = 300;\n        let asset_id = random_asset_id;\n        let _res = wallet\n            .force_transfer_to_contract(contract_id, amount, asset_id, TxPolicies::default())\n            .await?;\n\n        // Check that the contract now has 1 coin.\n        let contract_balances = wallet\n            .try_provider()?\n            .get_contract_balances(&contract_id)\n            .await?;\n        assert_eq!(contract_balances.len(), 1);\n\n        let random_asset_balance = contract_balances.get(&random_asset_id).unwrap();\n        assert_eq!(*random_asset_balance, 300);\n        // ANCHOR_END: wallet_contract_transfer\n        Ok(())\n    }\n\n    #[tokio::test]\n    #[allow(unused_variables)]\n    async fn setup_multiple_wallets() -> Result<()> {\n        // ANCHOR: multiple_wallets_helper\n        use fuels::prelude::*;\n        // This helper launches a local node and provides 10 test wallets linked to it.\n        // The initial balance defaults to 1 coin per wallet with an amount of 1_000_000_000.\n        let wallets =\n            launch_custom_provider_and_get_wallets(WalletsConfig::default(), None, None).await?;\n        // ANCHOR_END: multiple_wallets_helper\n\n        // ANCHOR: setup_5_wallets\n        let num_wallets = 5;\n        let coins_per_wallet = 3;\n        let amount_per_coin = 100;\n        let config = WalletsConfig::new(\n            Some(num_wallets),\n            Some(coins_per_wallet),\n            Some(amount_per_coin),\n        );\n        // Launches a local node and provides test wallets as specified by the config.\n        let wallets = launch_custom_provider_and_get_wallets(config, None, None).await?;\n        // ANCHOR_END: setup_5_wallets\n        Ok(())\n    }\n\n    #[tokio::test]\n    #[allow(unused_variables)]\n    async fn setup_wallet_multiple_assets() -> Result<()> {\n        // ANCHOR: multiple_assets_wallet\n        // ANCHOR: multiple_assets_coins\n        use fuels::prelude::*;\n        let signer = PrivateKeySigner::random(&mut thread_rng());\n        let num_assets = 5;\n        let coins_per_asset = 10;\n        let amount_per_coin = 15;\n\n        let (coins, asset_ids) = setup_multiple_assets_coins(\n            signer.address(),\n            num_assets,\n            coins_per_asset,\n            amount_per_coin,\n        );\n        // ANCHOR_END: multiple_assets_coins\n        let provider = setup_test_provider(coins.clone(), vec![], None, None).await?;\n        let wallet = Wallet::new(signer, provider);\n        // ANCHOR_END: multiple_assets_wallet\n        Ok(())\n    }\n\n    #[tokio::test]\n    #[allow(unused_variables)]\n    async fn setup_wallet_custom_assets() -> std::result::Result<(), Box<dyn std::error::Error>> {\n        // ANCHOR: custom_assets_wallet\n        use fuels::prelude::*;\n        use rand::Fill;\n\n        let mut rng = rand::thread_rng();\n        let signer = PrivateKeySigner::random(&mut rng);\n\n        let asset_base = AssetConfig {\n            id: AssetId::zeroed(),\n            num_coins: 2,\n            coin_amount: 4,\n        };\n\n        let mut asset_id_1 = AssetId::zeroed();\n        asset_id_1.try_fill(&mut rng)?;\n        let asset_1 = AssetConfig {\n            id: asset_id_1,\n            num_coins: 6,\n            coin_amount: 8,\n        };\n\n        let mut asset_id_2 = AssetId::zeroed();\n        asset_id_2.try_fill(&mut rng)?;\n        let asset_2 = AssetConfig {\n            id: asset_id_2,\n            num_coins: 10,\n            coin_amount: 12,\n        };\n\n        let assets = vec![asset_base, asset_1, asset_2];\n        let coins = setup_custom_assets_coins(signer.address(), &assets);\n        let provider = setup_test_provider(coins, vec![], None, None).await?;\n        let wallet = Wallet::new(signer, provider.clone());\n        // ANCHOR_END: custom_assets_wallet\n\n        // ANCHOR: custom_assets_wallet_short\n        let num_wallets = 1;\n        let wallet_config = WalletsConfig::new_multiple_assets(num_wallets, assets);\n        let wallets = launch_custom_provider_and_get_wallets(wallet_config, None, None).await?;\n        // ANCHOR_END: custom_assets_wallet_short\n\n        // ANCHOR: wallet_to_address\n        let wallet = Wallet::random(&mut rng, provider);\n        let address: Address = wallet.address();\n        // ANCHOR_END: wallet_to_address\n        Ok(())\n    }\n\n    #[tokio::test]\n    #[allow(unused_variables)]\n    async fn get_balances() -> Result<()> {\n        use std::collections::HashMap;\n\n        use fuels::{\n            prelude::{DEFAULT_COIN_AMOUNT, DEFAULT_NUM_COINS, launch_provider_and_get_wallet},\n            types::AssetId,\n        };\n\n        let wallet = launch_provider_and_get_wallet().await?;\n        // ANCHOR: get_asset_balance\n        let asset_id = AssetId::zeroed();\n        let balance: u128 = wallet.get_asset_balance(&asset_id).await?;\n        // ANCHOR_END: get_asset_balance\n\n        // ANCHOR: get_balances\n        let balances: HashMap<String, u128> = wallet.get_balances().await?;\n        // ANCHOR_END: get_balances\n\n        // ANCHOR: get_balance_hashmap\n        let asset_balance = balances.get(&asset_id.to_string()).unwrap();\n        // ANCHOR_END: get_balance_hashmap\n\n        assert_eq!(\n            *asset_balance,\n            (DEFAULT_COIN_AMOUNT * DEFAULT_NUM_COINS) as u128\n        );\n\n        Ok(())\n    }\n\n    #[tokio::test]\n    async fn wallet_transfer_to_base_layer() -> Result<()> {\n        // ANCHOR: wallet_withdraw_to_base\n        use std::str::FromStr;\n\n        use fuels::prelude::*;\n\n        let wallets = launch_custom_provider_and_get_wallets(\n            WalletsConfig::new(Some(1), None, None),\n            None,\n            None,\n        )\n        .await?;\n        let wallet = wallets.first().unwrap();\n\n        let amount = 1000;\n        let base_layer_address = Address::from_str(\n            \"0x4710162c2e3a95a6faff05139150017c9e38e5e280432d546fae345d6ce6d8fe\",\n        )?;\n\n        // Transfer an amount of 1000 to the specified base layer address.\n        let response = wallet\n            .withdraw_to_base_layer(base_layer_address, amount, TxPolicies::default())\n            .await?;\n\n        let _block_height = wallet.provider().produce_blocks(1, None).await?;\n\n        // Retrieve a message proof from the provider.\n        let proof = wallet\n            .try_provider()?\n            .get_message_proof(&response.tx_id, &response.nonce, None, Some(2))\n            .await?;\n\n        // Verify the amount and recipient.\n        assert_eq!(proof.amount, amount);\n        assert_eq!(proof.recipient, base_layer_address);\n        // ANCHOR_END: wallet_withdraw_to_base\n        Ok(())\n    }\n}\n"
  },
  {
    "path": "packages/fuels/Cargo.toml",
    "content": "[package]\nname = \"fuels\"\nversion = { workspace = true }\nauthors = { workspace = true }\nedition = { workspace = true }\nhomepage = { workspace = true }\nreadme = { workspace = true }\nlicense = { workspace = true }\nrepository = { workspace = true }\nrust-version = { workspace = true }\ndescription = \"Fuel Rust SDK.\"\n\n[package.metadata.cargo-machete]\nignored = [\"fuel-core\"]\n\n[dependencies]\nfuel-core-client = { workspace = true, optional = true }\nfuel-crypto = { workspace = true }\nfuel-tx = { workspace = true }\nfuels-accounts = { workspace = true, default-features = false }\nfuels-core = { workspace = true }\nfuels-macros = { workspace = true }\nfuels-programs = { workspace = true }\nfuels-test-helpers = { workspace = true, optional = true }\n\n[features]\ndefault = [\"std\", \"fuels-test-helpers?/fuels-accounts\", \"coin-cache\"]\ncoin-cache = [\"fuels-accounts/coin-cache\"]\ntest-helpers = [\"dep:fuels-test-helpers\", \"fuels-accounts/test-helpers\"]\n\n# The crates enabled via `dep:` below are not currently wasm compatible, as\n# such they are only available if `std` is enabled. The `dep:` syntax was\n# used so that we don't get a new feature flag for every optional dependency.\nstd = [\n  \"dep:fuel-core-client\",\n  \"fuels-programs/std\",\n  \"dep:fuels-test-helpers\",\n  \"fuels-accounts/std\",\n  \"fuels-core/std\",\n  \"fuels-test-helpers?/std\",\n]\nfuel-core-lib = [\"fuels-test-helpers?/fuel-core-lib\"]\nrocksdb = [\"fuels-test-helpers?/rocksdb\"]\naccounts-signer-aws-kms = [\"fuels-accounts/signer-aws-kms\"]\naccounts-signer-google-kms = [\"fuels-accounts/signer-google-kms\"]\naccounts-keystore = [\"fuels-accounts/keystore\"]\nfault-proving = [\"fuel-core-client?/fault-proving\", \"fuels-test-helpers?/fault-proving\", \"fuels-accounts/fault-proving\", \"fuels-core/fault-proving\", \"fuels-programs/fault-proving\"]\n"
  },
  {
    "path": "packages/fuels/src/lib.rs",
    "content": "//! # Fuel Rust SDK.\n//!\n//! ## Quickstart: `prelude`\n//!\n//! A prelude is provided which imports all the important data types and traits for you. Use this when you want to quickly bootstrap a new project.\n//!\n//! ```no_run\n//! # #[allow(unused)]\n//! use fuels::prelude::*;\n//! ```\n//!\n//! Examples on how you can use the types imported by the prelude can be found in\n//! the [test suite](https://github.com/FuelLabs/fuels-rs/tree/master/packages/fuels/tests)\n\npub mod tx {\n    pub use fuel_tx::{\n        ConsensusParameters, ContractIdExt, ContractParameters, FeeParameters, GasCosts,\n        PredicateParameters, Receipt, ScriptExecutionResult, ScriptParameters, StorageSlot,\n        Transaction as FuelTransaction, TxId, TxParameters, TxPointer, UpgradePurpose,\n        UploadSubsection, UtxoId, Witness, consensus_parameters, field,\n    };\n}\n\n#[cfg(feature = \"std\")]\npub mod client {\n    pub use fuel_core_client::client::{\n        FuelClient,\n        pagination::{PageDirection, PaginationRequest},\n    };\n}\n\npub mod macros {\n    pub use fuels_macros::*;\n}\n\npub mod programs {\n    pub use fuels_programs::*;\n}\n\npub mod core {\n    pub use fuels_core::{Configurable, Configurables, codec, constants, offsets, traits};\n}\n\npub mod crypto {\n    pub use fuel_crypto::{Hasher, Message, PublicKey, SecretKey, Signature};\n}\n\npub mod accounts {\n    pub use fuels_accounts::*;\n}\n\npub mod types {\n    pub use fuels_core::types::*;\n}\n\n#[cfg(feature = \"std\")]\npub mod test_helpers {\n    pub use fuels_test_helpers::*;\n}\n\n#[doc(hidden)]\npub mod prelude {\n    #[cfg(feature = \"std\")]\n    pub use super::{\n        accounts::{\n            Account, ViewOnlyAccount, predicate::Predicate, provider::*, signers::*, wallet::Wallet,\n        },\n        core::{\n            codec::{LogDecoder, LogId, LogResult},\n            traits::Signer,\n        },\n        macros::setup_program_test,\n        programs::{\n            calls::{CallHandler, CallParameters, ContractDependency, Execution},\n            contract::{Contract, LoadConfiguration, StorageConfiguration},\n        },\n        test_helpers::*,\n        types::transaction_builders::*,\n    };\n    pub use super::{\n        core::constants::*,\n        macros::abigen,\n        tx::Receipt,\n        types::{\n            Address, AssetId, Bytes, ContractId, RawSlice, Salt,\n            errors::{Error, Result},\n            transaction::*,\n        },\n    };\n}\n"
  },
  {
    "path": "packages/fuels-accounts/Cargo.toml",
    "content": "[package]\nname = \"fuels-accounts\"\nversion = { workspace = true }\nauthors = { workspace = true }\nedition = { workspace = true }\nhomepage = { workspace = true }\nlicense = { workspace = true }\nrepository = { workspace = true }\nrust-version = { workspace = true }\ndescription = \"Fuel Rust SDK accounts.\"\n\n[package.metadata.cargo-machete]\nignored = [\"aws-config\"]\n\n[dependencies]\nasync-trait = { workspace = true, default-features = false }\naws-config = { workspace = true, features = [\n  \"behavior-version-latest\",\n], optional = true }\naws-sdk-kms = { workspace = true, features = [\"default\"], optional = true }\nchrono = { workspace = true }\ncynic = { workspace = true, optional = true }\neth-keystore = { workspace = true, optional = true }\nfuel-core-client = { workspace = true, optional = true }\nfuel-core-types = { workspace = true }\nfuel-crypto = { workspace = true, features = [\"random\"] }\nfuel-tx = { workspace = true }\nfuel-types = { workspace = true, features = [\"random\"] }\nfuels-core = { workspace = true, default-features = false }\nfutures = { workspace = true}\ngoogle-cloud-kms = { workspace = true, features = [\"auth\"], optional = true }\nitertools = { workspace = true }\nk256 = { workspace = true, features = [\"ecdsa-core\", \"pem\"] }\nrand = { workspace = true, default-features = false }\nsemver = { workspace = true }\ntai64 = { workspace = true, features = [\"serde\"] }\nthiserror = { workspace = true, default-features = false }\ntokio = { workspace = true, features = [\"full\"], optional = true }\nzeroize = { workspace = true, features = [\"derive\"] }\n\n[dev-dependencies]\nfuel-tx = { workspace = true, features = [\"test-helpers\", \"random\"] }\nmockall = { workspace = true, default-features = false }\ntempfile = { workspace = true }\ntokio = { workspace = true, features = [\"test-util\"] }\n\n[features]\ndefault = [\"std\"]\ncoin-cache = [\"tokio/time\"]\nstd = [\"fuels-core/std\", \"dep:tokio\", \"fuel-core-client/default\", \"dep:cynic\"]\ntest-helpers = []\nkeystore = [\"dep:eth-keystore\"]\nsigner-aws-kms = [\"dep:aws-sdk-kms\", \"dep:aws-config\"]\nsigner-google-kms = [\"dep:google-cloud-kms\"]\nfault-proving = [\"fuel-core-types/fault-proving\", \"fuel-core-client?/fault-proving\", \"fuels-core/fault-proving\"]\n"
  },
  {
    "path": "packages/fuels-accounts/src/account.rs",
    "content": "use std::collections::HashMap;\n\nuse async_trait::async_trait;\nuse fuel_core_client::client::pagination::{PaginatedResult, PaginationRequest};\nuse fuel_tx::{Output, TxId, TxPointer, UtxoId};\nuse fuels_core::types::{\n    Address, AssetId, Bytes32, ContractId, Nonce,\n    coin::Coin,\n    coin_type::CoinType,\n    coin_type_id::CoinTypeId,\n    errors::{Context, Result},\n    input::Input,\n    message::Message,\n    transaction::{Transaction, TxPolicies},\n    transaction_builders::{BuildableTransaction, ScriptTransactionBuilder, TransactionBuilder},\n    transaction_response::TransactionResponse,\n    tx_response::TxResponse,\n    tx_status::Success,\n};\n\nuse crate::{\n    accounts_utils::{\n        add_base_change_if_needed, available_base_assets_and_amount, calculate_missing_base_amount,\n        extract_message_nonce, split_into_utxo_ids_and_nonces,\n    },\n    provider::{Provider, ResourceFilter},\n};\n\n#[derive(Clone, Debug)]\npub struct WithdrawToBaseResponse {\n    pub tx_status: Success,\n    pub tx_id: TxId,\n    pub nonce: Nonce,\n}\n\n#[cfg_attr(not(target_arch = \"wasm32\"), async_trait)]\npub trait ViewOnlyAccount: Send + Sync {\n    fn address(&self) -> Address;\n\n    fn try_provider(&self) -> Result<&Provider>;\n\n    async fn get_transactions(\n        &self,\n        request: PaginationRequest<String>,\n    ) -> Result<PaginatedResult<TransactionResponse, String>> {\n        Ok(self\n            .try_provider()?\n            .get_transactions_by_owner(&self.address(), request)\n            .await?)\n    }\n\n    /// Gets all unspent coins of asset `asset_id` owned by the account.\n    async fn get_coins(&self, asset_id: AssetId) -> Result<Vec<Coin>> {\n        Ok(self\n            .try_provider()?\n            .get_coins(&self.address(), asset_id)\n            .await?)\n    }\n\n    /// Get the balance of all spendable coins `asset_id` for address `address`. This is different\n    /// from getting coins because we are just returning a number (the sum of UTXOs amount) instead\n    /// of the UTXOs.\n    async fn get_asset_balance(&self, asset_id: &AssetId) -> Result<u128> {\n        self.try_provider()?\n            .get_asset_balance(&self.address(), asset_id)\n            .await\n    }\n\n    /// Gets all unspent messages owned by the account.\n    async fn get_messages(&self) -> Result<Vec<Message>> {\n        Ok(self.try_provider()?.get_messages(&self.address()).await?)\n    }\n\n    /// Get all the spendable balances of all assets for the account. This is different from getting\n    /// the coins because we are only returning the sum of UTXOs coins amount and not the UTXOs\n    /// coins themselves.\n    async fn get_balances(&self) -> Result<HashMap<String, u128>> {\n        self.try_provider()?.get_balances(&self.address()).await\n    }\n\n    /// Get some spendable resources (coins and messages) of asset `asset_id` owned by the account\n    /// that add up at least to amount `amount`. The returned coins (UTXOs) are actual coins that\n    /// can be spent. The number of UXTOs is optimized to prevent dust accumulation.\n    async fn get_spendable_resources(\n        &self,\n        asset_id: AssetId,\n        amount: u128,\n        excluded_coins: Option<Vec<CoinTypeId>>,\n    ) -> Result<Vec<CoinType>> {\n        let (excluded_utxos, excluded_message_nonces) =\n            split_into_utxo_ids_and_nonces(excluded_coins);\n\n        let filter = ResourceFilter {\n            from: self.address(),\n            asset_id: Some(asset_id),\n            amount,\n            excluded_utxos,\n            excluded_message_nonces,\n        };\n\n        self.try_provider()?.get_spendable_resources(filter).await\n    }\n\n    /// Returns a vector containing the output coin and change output given an asset and amount\n    fn get_asset_outputs_for_amount(\n        &self,\n        to: Address,\n        asset_id: AssetId,\n        amount: u64,\n    ) -> Vec<Output> {\n        vec![\n            Output::coin(to, amount, asset_id),\n            // Note that the change will be computed by the node.\n            // Here we only have to tell the node who will own the change and its asset ID.\n            Output::change(self.address(), 0, asset_id),\n        ]\n    }\n\n    /// Returns a vector consisting of `Input::Coin`s and `Input::Message`s for the given\n    /// asset ID and amount.\n    async fn get_asset_inputs_for_amount(\n        &self,\n        asset_id: AssetId,\n        amount: u128,\n        excluded_coins: Option<Vec<CoinTypeId>>,\n    ) -> Result<Vec<Input>>;\n\n    /// Add base asset inputs to the transaction to cover the estimated fee\n    /// and add a change output for the base asset if needed.\n    /// Requires contract inputs to be at the start of the transactions inputs vec\n    /// so that their indexes are retained\n    async fn adjust_for_fee<Tb: TransactionBuilder + Sync>(\n        &self,\n        tb: &mut Tb,\n        used_base_amount: u128,\n    ) -> Result<()> {\n        let provider = self.try_provider()?;\n        let consensus_parameters = provider.consensus_parameters().await?;\n        let base_asset_id = consensus_parameters.base_asset_id();\n        let (base_assets, base_amount) = available_base_assets_and_amount(tb, base_asset_id);\n        let missing_base_amount =\n            calculate_missing_base_amount(tb, base_amount, used_base_amount, provider).await?;\n\n        if missing_base_amount > 0 {\n            let new_base_inputs = self\n                .get_asset_inputs_for_amount(\n                    *consensus_parameters.base_asset_id(),\n                    missing_base_amount,\n                    Some(base_assets),\n                )\n                .await\n                .with_context(|| {\n                    format!(\"failed to get base asset ({base_asset_id}) inputs with amount: `{missing_base_amount}`\")\n                })?;\n\n            tb.inputs_mut().extend(new_base_inputs);\n        };\n\n        add_base_change_if_needed(tb, self.address(), *consensus_parameters.base_asset_id());\n\n        Ok(())\n    }\n}\n\n#[cfg_attr(not(target_arch = \"wasm32\"), async_trait)]\npub trait Account: ViewOnlyAccount {\n    // Add signatures to the builder if the underlying account is a wallet\n    fn add_witnesses<Tb: TransactionBuilder>(&self, _tb: &mut Tb) -> Result<()> {\n        Ok(())\n    }\n\n    /// Transfer funds from this account to another `Address`.\n    /// Fails if amount for asset ID is larger than address's spendable coins.\n    /// Returns the transaction ID that was sent and the list of receipts.\n    async fn transfer(\n        &self,\n        to: Address,\n        amount: u64,\n        asset_id: AssetId,\n        tx_policies: TxPolicies,\n    ) -> Result<TxResponse> {\n        let provider = self.try_provider()?;\n\n        let inputs = self\n            .get_asset_inputs_for_amount(asset_id, amount.into(), None)\n            .await?;\n        let outputs = self.get_asset_outputs_for_amount(to, asset_id, amount);\n\n        let mut tx_builder =\n            ScriptTransactionBuilder::prepare_transfer(inputs, outputs, tx_policies);\n\n        self.add_witnesses(&mut tx_builder)?;\n\n        let consensus_parameters = provider.consensus_parameters().await?;\n        let used_base_amount = if asset_id == *consensus_parameters.base_asset_id() {\n            amount.into()\n        } else {\n            0\n        };\n        self.adjust_for_fee(&mut tx_builder, used_base_amount)\n            .await\n            .context(\"failed to adjust inputs to cover for missing base asset\")?;\n\n        let tx = tx_builder.build(provider).await?;\n        let tx_id = tx.id(consensus_parameters.chain_id());\n\n        let tx_status = provider.send_transaction_and_await_commit(tx).await?;\n\n        Ok(TxResponse {\n            tx_status: tx_status.take_success_checked(None)?,\n            tx_id,\n        })\n    }\n\n    /// Unconditionally transfers `balance` of type `asset_id` to\n    /// the contract at `to`.\n    /// Fails if balance for `asset_id` is larger than this account's spendable balance.\n    /// Returns the corresponding transaction ID and the list of receipts.\n    ///\n    /// CAUTION !!!\n    ///\n    /// This will transfer coins to a contract, possibly leading\n    /// to the PERMANENT LOSS OF COINS if not used with care.\n    async fn force_transfer_to_contract(\n        &self,\n        to: ContractId,\n        balance: u64,\n        asset_id: AssetId,\n        tx_policies: TxPolicies,\n    ) -> Result<TxResponse> {\n        let provider = self.try_provider()?;\n\n        let zeroes = Bytes32::zeroed();\n\n        let mut inputs = vec![Input::contract(\n            UtxoId::new(zeroes, 0),\n            zeroes,\n            zeroes,\n            TxPointer::default(),\n            to,\n        )];\n\n        inputs.extend(\n            self.get_asset_inputs_for_amount(asset_id, balance.into(), None)\n                .await?,\n        );\n\n        let outputs = vec![\n            Output::contract(0, zeroes, zeroes),\n            Output::change(self.address(), 0, asset_id),\n        ];\n\n        // Build transaction and sign it\n        let mut tb = ScriptTransactionBuilder::prepare_contract_transfer(\n            to,\n            balance,\n            asset_id,\n            inputs,\n            outputs,\n            tx_policies,\n        );\n\n        let consensus_parameters = provider.consensus_parameters().await?;\n        let used_base_amount = if asset_id == *consensus_parameters.base_asset_id() {\n            balance\n        } else {\n            0\n        };\n\n        self.add_witnesses(&mut tb)?;\n        self.adjust_for_fee(&mut tb, used_base_amount.into())\n            .await\n            .context(\"failed to adjust inputs to cover for missing base asset\")?;\n\n        let tx = tb.build(provider).await?;\n\n        let consensus_parameters = provider.consensus_parameters().await?;\n        let tx_id = tx.id(consensus_parameters.chain_id());\n\n        let tx_status = provider.send_transaction_and_await_commit(tx).await?;\n\n        Ok(TxResponse {\n            tx_status: tx_status.take_success_checked(None)?,\n            tx_id,\n        })\n    }\n\n    /// Withdraws an amount of the base asset to\n    /// an address on the base chain.\n    /// Returns the transaction ID, message ID and the list of receipts.\n    async fn withdraw_to_base_layer(\n        &self,\n        to: Address,\n        amount: u64,\n        tx_policies: TxPolicies,\n    ) -> Result<WithdrawToBaseResponse> {\n        let provider = self.try_provider()?;\n        let consensus_parameters = provider.consensus_parameters().await?;\n\n        let inputs = self\n            .get_asset_inputs_for_amount(*consensus_parameters.base_asset_id(), amount.into(), None)\n            .await?;\n\n        let mut tb = ScriptTransactionBuilder::prepare_message_to_output(\n            to,\n            amount,\n            inputs,\n            tx_policies,\n            *consensus_parameters.base_asset_id(),\n        );\n\n        self.add_witnesses(&mut tb)?;\n        self.adjust_for_fee(&mut tb, amount.into())\n            .await\n            .context(\"failed to adjust inputs to cover for missing base asset\")?;\n\n        let tx = tb.build(provider).await?;\n        let tx_id = tx.id(consensus_parameters.chain_id());\n\n        let tx_status = provider.send_transaction_and_await_commit(tx).await?;\n        let success = tx_status.take_success_checked(None)?;\n\n        let nonce = extract_message_nonce(&success.receipts)\n            .expect(\"MessageId could not be retrieved from tx receipts.\");\n\n        Ok(WithdrawToBaseResponse {\n            tx_status: success,\n            tx_id,\n            nonce,\n        })\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use std::str::FromStr;\n\n    use fuel_crypto::{Message, SecretKey, Signature};\n    use fuel_tx::{Address, ConsensusParameters, Output, Transaction as FuelTransaction};\n    use fuels_core::{\n        traits::Signer,\n        types::{DryRun, DryRunner, transaction::Transaction},\n    };\n\n    use super::*;\n    use crate::signers::private_key::PrivateKeySigner;\n\n    #[derive(Default)]\n    struct MockDryRunner {\n        c_param: ConsensusParameters,\n    }\n\n    #[cfg_attr(not(target_arch = \"wasm32\"), async_trait)]\n    impl DryRunner for MockDryRunner {\n        async fn dry_run(&self, _: FuelTransaction) -> Result<DryRun> {\n            Ok(DryRun {\n                succeeded: true,\n                script_gas: 0,\n                variable_outputs: 0,\n            })\n        }\n\n        async fn consensus_parameters(&self) -> Result<ConsensusParameters> {\n            Ok(self.c_param.clone())\n        }\n\n        async fn estimate_gas_price(&self, _block_header: u32) -> Result<u64> {\n            Ok(0)\n        }\n\n        async fn estimate_predicates(\n            &self,\n            _: &FuelTransaction,\n            _: Option<u32>,\n        ) -> Result<FuelTransaction> {\n            unimplemented!()\n        }\n    }\n\n    #[tokio::test]\n    async fn sign_tx_and_verify() -> std::result::Result<(), Box<dyn std::error::Error>> {\n        // ANCHOR: sign_tb\n        let secret = SecretKey::from_str(\n            \"5f70feeff1f229e4a95e1056e8b4d80d0b24b565674860cc213bdb07127ce1b1\",\n        )?;\n        let signer = PrivateKeySigner::new(secret);\n\n        // Set up a transaction\n        let mut tb = {\n            let input_coin = Input::ResourceSigned {\n                resource: CoinType::Coin(Coin {\n                    amount: 10000000,\n                    owner: signer.address(),\n                    ..Default::default()\n                }),\n            };\n\n            let output_coin = Output::coin(\n                Address::from_str(\n                    \"0xc7862855b418ba8f58878db434b21053a61a2025209889cc115989e8040ff077\",\n                )?,\n                1,\n                Default::default(),\n            );\n            let change = Output::change(signer.address(), 0, Default::default());\n\n            ScriptTransactionBuilder::prepare_transfer(\n                vec![input_coin],\n                vec![output_coin, change],\n                Default::default(),\n            )\n        };\n\n        // Add `Signer` to the transaction builder\n        tb.add_signer(signer.clone())?;\n        // ANCHOR_END: sign_tb\n\n        let tx = tb.build(MockDryRunner::default()).await?; // Resolve signatures and add corresponding witness indexes\n\n        // Extract the signature from the tx witnesses\n        let bytes = <[u8; Signature::LEN]>::try_from(tx.witnesses().first().unwrap().as_ref())?;\n        let tx_signature = Signature::from_bytes(bytes);\n\n        // Sign the transaction manually\n        let message = Message::from_bytes(*tx.id(0.into()));\n        let signature = signer.sign(message).await?;\n\n        // Check if the signatures are the same\n        assert_eq!(signature, tx_signature);\n\n        // Check if the signature is what we expect it to be\n        assert_eq!(\n            signature,\n            Signature::from_str(\n                \"faa616776a1c336ef6257f7cb0cb5cd932180e2d15faba5f17481dae1cbcaf314d94617bd900216a6680bccb1ea62438e4ca93b0d5733d33788ef9d79cc24e9f\"\n            )?\n        );\n\n        // Recover the address that signed the transaction\n        let recovered_address = signature.recover(&message)?;\n\n        assert_eq!(*signer.address(), *recovered_address.hash());\n\n        // Verify signature\n        signature.verify(&recovered_address, &message)?;\n\n        Ok(())\n    }\n}\n"
  },
  {
    "path": "packages/fuels-accounts/src/accounts_utils.rs",
    "content": "use fuel_tx::{AssetId, Output, Receipt, UtxoId};\nuse fuel_types::Nonce;\nuse fuels_core::types::{\n    Address,\n    coin::Coin,\n    coin_type::CoinType,\n    coin_type_id::CoinTypeId,\n    errors::{Error, Result, error},\n    input::Input,\n    transaction_builders::TransactionBuilder,\n};\nuse itertools::{Either, Itertools};\n\nuse crate::provider::Provider;\n\npub fn extract_message_nonce(receipts: &[Receipt]) -> Option<Nonce> {\n    receipts.iter().find_map(|m| m.nonce()).copied()\n}\n\npub async fn calculate_missing_base_amount(\n    tb: &impl TransactionBuilder,\n    available_base_amount: u128,\n    reserved_base_amount: u128,\n    provider: &Provider,\n) -> Result<u128> {\n    let max_fee: u128 = tb.estimate_max_fee(provider).await?.into();\n\n    let total_used = max_fee + reserved_base_amount;\n    let missing_amount = if total_used > available_base_amount {\n        total_used - available_base_amount\n    } else if !is_consuming_utxos(tb) {\n        // A tx needs to have at least 1 spendable input\n        // Enforce a minimum required amount on the base asset if no other inputs are present\n        1\n    } else {\n        0\n    };\n\n    Ok(missing_amount)\n}\n\npub fn available_base_assets_and_amount(\n    tb: &impl TransactionBuilder,\n    base_asset_id: &AssetId,\n) -> (Vec<CoinTypeId>, u128) {\n    let mut sum = 0u128;\n    let iter =\n        tb.inputs()\n            .iter()\n            .filter_map(|input| match input {\n                Input::ResourceSigned { resource, .. }\n                | Input::ResourcePredicate { resource, .. } => match resource {\n                    CoinType::Coin(Coin {\n                        amount, asset_id, ..\n                    }) if asset_id == base_asset_id => {\n                        sum += u128::from(*amount);\n                        resource.id()\n                    }\n                    CoinType::Message(message) => {\n                        if message.data.is_empty() {\n                            sum += u128::from(message.amount);\n\n                            resource.id()\n                        } else {\n                            None\n                        }\n                    }\n                    _ => None,\n                },\n                _ => None,\n            })\n            .collect_vec();\n\n    (iter, sum)\n}\n\npub fn split_into_utxo_ids_and_nonces(\n    excluded_coins: Option<Vec<CoinTypeId>>,\n) -> (Vec<UtxoId>, Vec<Nonce>) {\n    excluded_coins\n        .map(|excluded_coins| {\n            excluded_coins\n                .iter()\n                .partition_map(|coin_id| match coin_id {\n                    CoinTypeId::UtxoId(utxo_id) => Either::Left(*utxo_id),\n                    CoinTypeId::Nonce(nonce) => Either::Right(*nonce),\n                })\n        })\n        .unwrap_or_default()\n}\n\nfn is_consuming_utxos(tb: &impl TransactionBuilder) -> bool {\n    tb.inputs()\n        .iter()\n        .any(|input| !matches!(input, Input::Contract { .. }))\n}\n\npub fn add_base_change_if_needed(\n    tb: &mut impl TransactionBuilder,\n    address: Address,\n    base_asset_id: AssetId,\n) {\n    let is_base_change_present = tb.outputs().iter().any(|output| {\n        matches!(output , Output::Change { asset_id , .. }\n                                        if *asset_id == base_asset_id)\n    });\n\n    if !is_base_change_present {\n        tb.outputs_mut()\n            .push(Output::change(address, 0, base_asset_id));\n    }\n}\n\npub(crate) fn try_provider_error() -> Error {\n    error!(\n        Other,\n        \"no provider available. Make sure to use `set_provider`\"\n    )\n}\n"
  },
  {
    "path": "packages/fuels-accounts/src/coin_cache.rs",
    "content": "use std::{\n    collections::{HashMap, HashSet},\n    hash::{Hash, Hasher},\n};\n\nuse fuel_types::AssetId;\nuse fuels_core::types::{Address, coin_type_id::CoinTypeId};\nuse tokio::time::{Duration, Instant};\n\ntype CoinCacheKey = (Address, AssetId);\n\n#[derive(Debug)]\npub(crate) struct CoinsCache {\n    ttl: Duration,\n    items: HashMap<CoinCacheKey, HashSet<CoinCacheItem>>,\n}\n\nimpl Default for CoinsCache {\n    fn default() -> Self {\n        Self::new(Duration::from_secs(30))\n    }\n}\n\nimpl CoinsCache {\n    pub fn new(ttl: Duration) -> Self {\n        Self {\n            ttl,\n            items: HashMap::default(),\n        }\n    }\n\n    pub fn insert_multiple(\n        &mut self,\n        coin_ids: impl IntoIterator<Item = (CoinCacheKey, Vec<CoinTypeId>)>,\n    ) {\n        for (key, ids) in coin_ids {\n            let new_items = ids.into_iter().map(CoinCacheItem::new);\n\n            let items = self.items.entry(key).or_default();\n            items.extend(new_items);\n        }\n    }\n\n    pub fn get_active(&mut self, key: &CoinCacheKey) -> HashSet<CoinTypeId> {\n        self.remove_expired_entries(key);\n\n        self.items\n            .get(key)\n            .cloned()\n            .unwrap_or_default()\n            .into_iter()\n            .map(|item| item.id)\n            .collect()\n    }\n\n    pub fn remove_items(\n        &mut self,\n        inputs: impl IntoIterator<Item = (CoinCacheKey, Vec<CoinTypeId>)>,\n    ) {\n        for (key, ids) in inputs {\n            for id in ids {\n                self.remove(&key, id);\n            }\n        }\n    }\n\n    fn remove(&mut self, key: &CoinCacheKey, id: CoinTypeId) {\n        if let Some(ids) = self.items.get_mut(key) {\n            let item = CoinCacheItem::new(id);\n            ids.remove(&item);\n        }\n    }\n\n    fn remove_expired_entries(&mut self, key: &CoinCacheKey) {\n        if let Some(entry) = self.items.get_mut(key) {\n            entry.retain(|item| item.is_valid(self.ttl));\n        }\n    }\n}\n\n#[derive(Eq, Debug, Clone)]\nstruct CoinCacheItem {\n    created_at: Instant,\n    pub id: CoinTypeId,\n}\n\nimpl PartialEq for CoinCacheItem {\n    fn eq(&self, other: &Self) -> bool {\n        self.id.eq(&other.id)\n    }\n}\n\nimpl Hash for CoinCacheItem {\n    fn hash<H: Hasher>(&self, state: &mut H) {\n        self.id.hash(state);\n    }\n}\n\nimpl CoinCacheItem {\n    pub fn new(id: CoinTypeId) -> Self {\n        Self {\n            created_at: Instant::now(),\n            id,\n        }\n    }\n\n    pub fn is_valid(&self, ttl: Duration) -> bool {\n        self.created_at + ttl > Instant::now()\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use fuel_tx::UtxoId;\n    use fuel_types::{Bytes32, Nonce};\n\n    use super::*;\n\n    fn get_items() -> (CoinTypeId, CoinTypeId) {\n        let utxo_id = UtxoId::new(Bytes32::from([1u8; 32]), 0);\n        let nonce = Nonce::new([2u8; 32]);\n\n        (CoinTypeId::UtxoId(utxo_id), CoinTypeId::Nonce(nonce))\n    }\n\n    #[test]\n    fn test_insert_and_get_active() {\n        let mut cache = CoinsCache::new(Duration::from_secs(60));\n\n        let key: CoinCacheKey = Default::default();\n        let (item1, item2) = get_items();\n        let items = HashMap::from([(key, vec![item1.clone(), item2.clone()])]);\n\n        cache.insert_multiple(items);\n\n        let active_coins = cache.get_active(&key);\n\n        assert_eq!(active_coins.len(), 2);\n        assert!(active_coins.contains(&item1));\n        assert!(active_coins.contains(&item2));\n    }\n\n    #[tokio::test]\n    async fn test_insert_and_expire_items() {\n        let mut cache = CoinsCache::new(Duration::from_secs(10));\n\n        let key = CoinCacheKey::default();\n        let (item1, _) = get_items();\n        let items = HashMap::from([(key, vec![item1.clone()])]);\n\n        cache.insert_multiple(items);\n\n        // Advance time by more than the cache's TTL\n        tokio::time::pause();\n        tokio::time::advance(Duration::from_secs(12)).await;\n\n        let (_, item2) = get_items();\n        let items = HashMap::from([(key, vec![item2.clone()])]);\n        cache.insert_multiple(items);\n\n        let active_coins = cache.get_active(&key);\n\n        assert_eq!(active_coins.len(), 1);\n        assert!(!active_coins.contains(&item1));\n        assert!(active_coins.contains(&item2));\n    }\n\n    #[test]\n    fn test_get_active_no_items() {\n        let mut cache = CoinsCache::new(Duration::from_secs(60));\n\n        let key = Default::default();\n        let active_coins = cache.get_active(&key);\n\n        assert!(active_coins.is_empty());\n    }\n\n    #[test]\n    fn test_remove_items() {\n        let mut cache = CoinsCache::new(Duration::from_secs(60));\n\n        let key: CoinCacheKey = Default::default();\n        let (item1, item2) = get_items();\n\n        let items_to_insert = [(key, vec![item1.clone(), item2.clone()])];\n        cache.insert_multiple(items_to_insert.iter().cloned());\n\n        let items_to_remove = [(key, vec![item1.clone()])];\n        cache.remove_items(items_to_remove.iter().cloned());\n\n        let active_coins = cache.get_active(&key);\n\n        assert_eq!(active_coins.len(), 1);\n        assert!(!active_coins.contains(&item1));\n        assert!(active_coins.contains(&item2));\n    }\n}\n"
  },
  {
    "path": "packages/fuels-accounts/src/keystore.rs",
    "content": "use std::path::{Path, PathBuf};\n\nuse fuel_crypto::SecretKey;\nuse fuels_core::{error, types::errors::Result};\nuse rand::{CryptoRng, Rng};\nuse zeroize::{Zeroize, ZeroizeOnDrop};\n\n#[derive(Debug, Clone, Zeroize, ZeroizeOnDrop)]\npub struct KeySaved {\n    key: SecretKey,\n    #[zeroize(skip)]\n    uuid: String,\n}\n\nimpl KeySaved {\n    pub fn key(&self) -> &SecretKey {\n        &self.key\n    }\n\n    pub fn uuid(&self) -> &str {\n        &self.uuid\n    }\n}\n\n/// A Keystore encapsulates operations for key management such as creation, loading,\n/// and saving of keys into a specified directory.\npub struct Keystore {\n    dir: PathBuf,\n}\n\nimpl Keystore {\n    /// Creates a new Keystore instance with the provided directory.\n    pub fn new<P: AsRef<Path>>(dir: P) -> Self {\n        Self {\n            dir: dir.as_ref().to_path_buf(),\n        }\n    }\n\n    /// Loads and decrypts a key from the keystore using the given UUID and password.\n    pub fn load_key<S>(&self, uuid: &str, password: S) -> Result<SecretKey>\n    where\n        S: AsRef<[u8]>,\n    {\n        let key_path = self.dir.join(uuid);\n        let secret =\n            eth_keystore::decrypt_key(key_path, password).map_err(|e| error!(Other, \"{e}\"))?;\n        let secret_key = SecretKey::try_from(secret.as_slice())\n            .expect(\"Decrypted key should have a correct size\");\n        Ok(secret_key)\n    }\n\n    /// Encrypts the provided key with the given password and saves it to the keystore.\n    /// Returns the generated UUID for the stored key.\n    pub fn save_key<R, S>(&self, key: SecretKey, password: S, mut rng: R) -> Result<String>\n    where\n        R: Rng + CryptoRng,\n        S: AsRef<[u8]>,\n    {\n        // Note: `*key` is used if SecretKey implements Deref to an inner type.\n        eth_keystore::encrypt_key(&self.dir, &mut rng, *key, password, None)\n            .map_err(|e| error!(Other, \"{e}\"))\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use rand::thread_rng;\n    use tempfile::tempdir;\n\n    use super::*;\n    use crate::signers::private_key::PrivateKeySigner;\n\n    #[tokio::test]\n    async fn wallet_from_mnemonic_phrase() -> Result<()> {\n        let phrase =\n            \"oblige salon price punch saddle immune slogan rare snap desert retire surprise\";\n\n        // Create first key from mnemonic phrase.\n        let key = SecretKey::new_from_mnemonic_phrase_with_path(phrase, \"m/44'/60'/0'/0/0\")?;\n        let signer = PrivateKeySigner::new(key);\n\n        let expected_address = \"df9d0e6c6c5f5da6e82e5e1a77974af6642bdb450a10c43f0c6910a212600185\";\n\n        assert_eq!(signer.address().to_string(), expected_address);\n\n        // Create a second key from the same phrase.\n        let key = SecretKey::new_from_mnemonic_phrase_with_path(phrase, \"m/44'/60'/1'/0/0\")?;\n        let signer2 = PrivateKeySigner::new(key);\n\n        let expected_second_address =\n            \"261191b0164a24fd0fd51566ec5e5b0b9ba8fb2d42dc9cf7dbbd6f23d2742759\";\n\n        assert_eq!(signer2.address().to_string(), expected_second_address);\n\n        Ok(())\n    }\n\n    #[tokio::test]\n    async fn encrypt_and_store_keys_from_mnemonic() -> Result<()> {\n        let dir = tempdir()?;\n        let keystore = Keystore::new(dir.path());\n        let phrase =\n            \"oblige salon price punch saddle immune slogan rare snap desert retire surprise\";\n\n        // Create a key from the mnemonic phrase.\n        let key = SecretKey::new_from_mnemonic_phrase_with_path(phrase, \"m/44'/60'/0'/0/0\")?;\n        let uuid = keystore.save_key(key, \"password\", thread_rng())?;\n\n        let recovered_key = keystore.load_key(&uuid, \"password\")?;\n        assert_eq!(key, recovered_key);\n\n        // Remove the keystore file.\n        let key_path = keystore.dir.join(&uuid);\n        assert!(std::fs::remove_file(key_path).is_ok());\n        Ok(())\n    }\n}\n"
  },
  {
    "path": "packages/fuels-accounts/src/lib.rs",
    "content": "#[cfg(feature = \"std\")]\nmod account;\n#[cfg(feature = \"std\")]\nmod accounts_utils;\n#[cfg(all(feature = \"std\", feature = \"keystore\"))]\npub mod keystore;\n#[cfg(feature = \"std\")]\npub mod provider;\n#[cfg(feature = \"std\")]\npub mod wallet;\n\n#[cfg(feature = \"std\")]\npub use account::*;\n\n#[cfg(feature = \"coin-cache\")]\nmod coin_cache;\n\npub mod predicate;\npub mod signers;\n#[cfg(test)]\nmod test {\n    #[test]\n    fn sdl_is_the_same_as_from_fuel() {\n        let file_sdl = include_str!(\"./schema/schema.sdl\");\n\n        let core_sdl = String::from_utf8(fuel_core_client::SCHEMA_SDL.to_vec()).unwrap();\n\n        assert_eq!(file_sdl, &core_sdl);\n    }\n}\n"
  },
  {
    "path": "packages/fuels-accounts/src/predicate.rs",
    "content": "use std::{fmt::Debug, fs};\n\n#[cfg(feature = \"std\")]\nuse fuels_core::types::{AssetId, coin_type_id::CoinTypeId, input::Input};\nuse fuels_core::{\n    Configurables, error,\n    types::{Address, errors::Result},\n};\n\n#[cfg(feature = \"std\")]\nuse crate::accounts_utils::try_provider_error;\n#[cfg(feature = \"std\")]\nuse crate::{Account, ViewOnlyAccount, provider::Provider};\n\n#[derive(Debug, Clone)]\npub struct Predicate {\n    address: Address,\n    code: Vec<u8>,\n    data: Vec<u8>,\n    #[cfg(feature = \"std\")]\n    provider: Option<Provider>,\n}\n\nimpl Predicate {\n    pub fn address(&self) -> Address {\n        self.address\n    }\n\n    pub fn code(&self) -> &[u8] {\n        &self.code\n    }\n\n    pub fn data(&self) -> &[u8] {\n        &self.data\n    }\n\n    pub fn calculate_address(code: &[u8]) -> Address {\n        fuel_tx::Input::predicate_owner(code)\n    }\n\n    pub fn load_from(file_path: &str) -> Result<Self> {\n        let code = fs::read(file_path).map_err(|e| {\n            error!(\n                IO,\n                \"could not read predicate binary {file_path:?}. Reason: {e}\"\n            )\n        })?;\n        Ok(Self::from_code(code))\n    }\n\n    pub fn from_code(code: Vec<u8>) -> Self {\n        Self {\n            address: Self::calculate_address(&code),\n            code,\n            data: Default::default(),\n            #[cfg(feature = \"std\")]\n            provider: None,\n        }\n    }\n\n    pub fn with_data(mut self, data: Vec<u8>) -> Self {\n        self.data = data;\n        self\n    }\n\n    pub fn with_code(self, code: Vec<u8>) -> Self {\n        let address = Self::calculate_address(&code);\n        Self {\n            code,\n            address,\n            ..self\n        }\n    }\n\n    pub fn with_configurables(mut self, configurables: impl Into<Configurables>) -> Self {\n        let configurables: Configurables = configurables.into();\n        configurables.update_constants_in(&mut self.code);\n        let address = Self::calculate_address(&self.code);\n        self.address = address;\n        self\n    }\n}\n\n#[cfg(feature = \"std\")]\nimpl Predicate {\n    pub fn provider(&self) -> Option<&Provider> {\n        self.provider.as_ref()\n    }\n\n    pub fn set_provider(&mut self, provider: Provider) {\n        self.provider = Some(provider);\n    }\n\n    pub fn with_provider(self, provider: Provider) -> Self {\n        Self {\n            provider: Some(provider),\n            ..self\n        }\n    }\n}\n\n#[cfg(feature = \"std\")]\n#[cfg_attr(not(target_arch = \"wasm32\"), async_trait::async_trait)]\nimpl ViewOnlyAccount for Predicate {\n    fn address(&self) -> Address {\n        self.address()\n    }\n\n    fn try_provider(&self) -> Result<&Provider> {\n        self.provider.as_ref().ok_or_else(try_provider_error)\n    }\n\n    async fn get_asset_inputs_for_amount(\n        &self,\n        asset_id: AssetId,\n        amount: u128,\n        excluded_coins: Option<Vec<CoinTypeId>>,\n    ) -> Result<Vec<Input>> {\n        Ok(self\n            .get_spendable_resources(asset_id, amount, excluded_coins)\n            .await?\n            .into_iter()\n            .map(|resource| {\n                Input::resource_predicate(resource, self.code.clone(), self.data.clone())\n            })\n            .collect::<Vec<Input>>())\n    }\n}\n\n#[cfg(feature = \"std\")]\nimpl Account for Predicate {}\n"
  },
  {
    "path": "packages/fuels-accounts/src/provider/cache.rs",
    "content": "use std::{sync::Arc, time::Duration};\n\nuse async_trait::async_trait;\nuse chrono::{DateTime, Utc};\nuse fuel_core_client::client::types::NodeInfo;\nuse fuel_tx::ConsensusParameters;\nuse fuels_core::types::errors::Result;\nuse tokio::sync::RwLock;\n\n#[cfg_attr(test, mockall::automock)]\n#[async_trait]\npub trait CacheableRpcs {\n    async fn consensus_parameters(&self) -> Result<ConsensusParameters>;\n    async fn node_info(&self) -> Result<NodeInfo>;\n}\n\ntrait Clock {\n    fn now(&self) -> DateTime<Utc>;\n}\n\n#[derive(Debug, Clone)]\npub struct TtlConfig {\n    pub consensus_parameters: Duration,\n}\n\nimpl Default for TtlConfig {\n    fn default() -> Self {\n        TtlConfig {\n            consensus_parameters: Duration::from_secs(60),\n        }\n    }\n}\n\n#[derive(Debug, Clone)]\nstruct Dated<T> {\n    value: T,\n    date: DateTime<Utc>,\n}\n\nimpl<T> Dated<T> {\n    fn is_stale(&self, now: DateTime<Utc>, ttl: Duration) -> bool {\n        self.date + ttl < now\n    }\n}\n\n#[derive(Debug, Clone, Copy)]\npub struct SystemClock;\nimpl Clock for SystemClock {\n    fn now(&self) -> DateTime<Utc> {\n        Utc::now()\n    }\n}\n\n#[derive(Debug, Clone)]\npub struct CachedClient<Client, Clock = SystemClock> {\n    client: Client,\n    ttl_config: TtlConfig,\n    cached_consensus_params: Arc<RwLock<Option<Dated<ConsensusParameters>>>>,\n    cached_node_info: Arc<RwLock<Option<Dated<NodeInfo>>>>,\n    clock: Clock,\n}\n\nimpl<Client, Clock> CachedClient<Client, Clock> {\n    pub fn new(client: Client, ttl: TtlConfig, clock: Clock) -> Self {\n        Self {\n            client,\n            ttl_config: ttl,\n            cached_consensus_params: Default::default(),\n            cached_node_info: Default::default(),\n            clock,\n        }\n    }\n\n    pub fn set_ttl(&mut self, ttl: TtlConfig) {\n        self.ttl_config = ttl\n    }\n\n    pub fn inner(&self) -> &Client {\n        &self.client\n    }\n\n    pub fn inner_mut(&mut self) -> &mut Client {\n        &mut self.client\n    }\n}\n\nimpl<Client, Clk> CachedClient<Client, Clk>\nwhere\n    Client: CacheableRpcs,\n{\n    pub async fn clear(&self) {\n        *self.cached_consensus_params.write().await = None;\n    }\n}\n\n#[async_trait]\nimpl<Client, Clk> CacheableRpcs for CachedClient<Client, Clk>\nwhere\n    Clk: Clock + Send + Sync,\n    Client: CacheableRpcs + Send + Sync,\n{\n    async fn consensus_parameters(&self) -> Result<ConsensusParameters> {\n        {\n            let read_lock = self.cached_consensus_params.read().await;\n            if let Some(entry) = read_lock.as_ref()\n                && !entry.is_stale(self.clock.now(), self.ttl_config.consensus_parameters)\n            {\n                return Ok(entry.value.clone());\n            }\n        }\n\n        let mut write_lock = self.cached_consensus_params.write().await;\n\n        // because it could have been updated since we last checked\n        if let Some(entry) = write_lock.as_ref()\n            && !entry.is_stale(self.clock.now(), self.ttl_config.consensus_parameters)\n        {\n            return Ok(entry.value.clone());\n        }\n\n        let fresh_parameters = self.client.consensus_parameters().await?;\n        *write_lock = Some(Dated {\n            value: fresh_parameters.clone(),\n            date: self.clock.now(),\n        });\n\n        Ok(fresh_parameters)\n    }\n\n    async fn node_info(&self) -> Result<NodeInfo> {\n        // must borrow from consensus_parameters to keep the change non-breaking\n        let ttl = self.ttl_config.consensus_parameters;\n        {\n            let read_lock = self.cached_node_info.read().await;\n            if let Some(entry) = read_lock.as_ref()\n                && !entry.is_stale(self.clock.now(), ttl)\n            {\n                return Ok(entry.value.clone());\n            }\n        }\n\n        let mut write_lock = self.cached_node_info.write().await;\n\n        // because it could have been updated since we last checked\n        if let Some(entry) = write_lock.as_ref()\n            && !entry.is_stale(self.clock.now(), ttl)\n        {\n            return Ok(entry.value.clone());\n        }\n\n        let fresh_node_info = self.client.node_info().await?;\n        *write_lock = Some(Dated {\n            value: fresh_node_info.clone(),\n            date: self.clock.now(),\n        });\n\n        Ok(fresh_node_info)\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use std::sync::Mutex;\n\n    use fuel_core_client::client::schema::{\n        U64,\n        node_info::{IndexationFlags, TxPoolStats},\n    };\n    use fuel_types::ChainId;\n\n    use super::*;\n\n    #[derive(Clone, Default)]\n    struct TestClock {\n        time: Arc<Mutex<DateTime<Utc>>>,\n    }\n\n    impl TestClock {\n        fn update_time(&self, time: DateTime<Utc>) {\n            *self.time.lock().unwrap() = time;\n        }\n    }\n\n    impl Clock for TestClock {\n        fn now(&self) -> DateTime<Utc> {\n            *self.time.lock().unwrap()\n        }\n    }\n\n    #[tokio::test]\n    async fn initial_call_to_consensus_params_fwd_to_api() {\n        // given\n        let mut api = MockCacheableRpcs::new();\n        api.expect_consensus_parameters()\n            .once()\n            .return_once(|| Ok(ConsensusParameters::default()));\n        let sut = CachedClient::new(api, TtlConfig::default(), TestClock::default());\n\n        // when\n        let _consensus_params = sut.consensus_parameters().await.unwrap();\n\n        // then\n        // mock validates the call went through\n    }\n\n    #[tokio::test]\n    async fn new_call_to_consensus_params_cached() {\n        // given\n        let mut api = MockCacheableRpcs::new();\n        api.expect_consensus_parameters()\n            .once()\n            .return_once(|| Ok(ConsensusParameters::default()));\n        let sut = CachedClient::new(\n            api,\n            TtlConfig {\n                consensus_parameters: Duration::from_secs(10),\n            },\n            TestClock::default(),\n        );\n        let consensus_parameters = sut.consensus_parameters().await.unwrap();\n\n        // when\n        let second_call_consensus_params = sut.consensus_parameters().await.unwrap();\n\n        // then\n        // mock validates only one call\n        assert_eq!(consensus_parameters, second_call_consensus_params);\n    }\n\n    #[tokio::test]\n    async fn if_ttl_expired_cache_is_updated() {\n        // given\n        let original_consensus_params = ConsensusParameters::default();\n\n        let changed_consensus_params = {\n            let mut params = original_consensus_params.clone();\n            params.set_chain_id(ChainId::new(99));\n            params\n        };\n\n        let api = {\n            let mut api = MockCacheableRpcs::new();\n            let original_consensus_params = original_consensus_params.clone();\n            let changed_consensus_params = changed_consensus_params.clone();\n            api.expect_consensus_parameters()\n                .once()\n                .return_once(move || Ok(original_consensus_params));\n\n            api.expect_consensus_parameters()\n                .once()\n                .return_once(move || Ok(changed_consensus_params));\n            api\n        };\n\n        let clock = TestClock::default();\n        let start_time = clock.now();\n\n        let sut = CachedClient::new(\n            api,\n            TtlConfig {\n                consensus_parameters: Duration::from_secs(10),\n            },\n            clock.clone(),\n        );\n        let consensus_parameters = sut.consensus_parameters().await.unwrap();\n\n        clock.update_time(start_time + Duration::from_secs(11));\n        // when\n        let second_call_consensus_params = sut.consensus_parameters().await.unwrap();\n\n        // then\n        // mock validates two calls made\n        assert_eq!(consensus_parameters, original_consensus_params);\n        assert_eq!(second_call_consensus_params, changed_consensus_params);\n    }\n\n    #[tokio::test]\n    async fn clear_cache_clears_consensus_params_cache() {\n        // given\n        let first_params = ConsensusParameters::default();\n        let second_params = {\n            let mut params = ConsensusParameters::default();\n            params.set_chain_id(ChainId::new(1234));\n            params\n        };\n\n        let api = {\n            let mut api = MockCacheableRpcs::new();\n            let first_clone = first_params.clone();\n            api.expect_consensus_parameters()\n                .times(1)\n                .return_once(move || Ok(first_clone));\n\n            let second_clone = second_params.clone();\n            api.expect_consensus_parameters()\n                .times(1)\n                .return_once(move || Ok(second_clone));\n            api\n        };\n\n        let clock = TestClock::default();\n        let sut = CachedClient::new(api, TtlConfig::default(), clock.clone());\n\n        let result1 = sut.consensus_parameters().await.unwrap();\n\n        // when\n        sut.clear().await;\n\n        // then\n        let result2 = sut.consensus_parameters().await.unwrap();\n\n        assert_eq!(result1, first_params);\n        assert_eq!(result2, second_params);\n    }\n\n    fn dummy_node_info() -> NodeInfo {\n        NodeInfo {\n            utxo_validation: true,\n            vm_backtrace: false,\n            max_tx: u64::MAX,\n            max_gas: u64::MAX,\n            max_size: u64::MAX,\n            max_depth: u64::MAX,\n            node_version: \"0.0.1\".to_string(),\n            indexation: IndexationFlags {\n                balances: true,\n                coins_to_spend: true,\n                asset_metadata: true,\n            },\n            tx_pool_stats: TxPoolStats {\n                tx_count: U64(1),\n                total_gas: U64(1),\n                total_size: U64(1),\n            },\n        }\n    }\n\n    #[tokio::test]\n    async fn initial_call_to_node_info_fwd_to_api() {\n        // given\n        let mut api = MockCacheableRpcs::new();\n        api.expect_node_info()\n            .once()\n            .return_once(|| Ok(dummy_node_info()));\n        let sut = CachedClient::new(api, TtlConfig::default(), TestClock::default());\n\n        // when\n        let _node_info = sut.node_info().await.unwrap();\n\n        // then\n        // The mock verifies that the API call was made.\n    }\n\n    #[tokio::test]\n    async fn new_call_to_node_info_cached() {\n        // given\n        let mut api = MockCacheableRpcs::new();\n        api.expect_node_info()\n            .once()\n            .return_once(|| Ok(dummy_node_info()));\n        let sut = CachedClient::new(\n            api,\n            TtlConfig {\n                consensus_parameters: Duration::from_secs(10),\n            },\n            TestClock::default(),\n        );\n        let first_node_info = sut.node_info().await.unwrap();\n\n        // when: second call should return the cached value\n        let second_node_info = sut.node_info().await.unwrap();\n\n        // then: only one API call should have been made and the values are equal\n        assert_eq!(first_node_info, second_node_info);\n    }\n\n    #[tokio::test]\n    async fn if_ttl_expired_node_info_cache_is_updated() {\n        // given\n        let original_node_info = dummy_node_info();\n\n        let changed_node_info = NodeInfo {\n            node_version: \"changed\".to_string(),\n            ..dummy_node_info()\n        };\n\n        let api = {\n            let mut api = MockCacheableRpcs::new();\n            let original_clone = original_node_info.clone();\n            api.expect_node_info()\n                .times(1)\n                .return_once(move || Ok(original_clone));\n\n            let changed_clone = changed_node_info.clone();\n            api.expect_node_info()\n                .times(1)\n                .return_once(move || Ok(changed_clone));\n            api\n        };\n\n        let clock = TestClock::default();\n        let start_time = clock.now();\n\n        let sut = CachedClient::new(\n            api,\n            TtlConfig {\n                consensus_parameters: Duration::from_secs(10),\n            },\n            clock.clone(),\n        );\n        let first_call = sut.node_info().await.unwrap();\n\n        // Advance time past the TTL.\n        clock.update_time(start_time + Duration::from_secs(11));\n\n        // when: a new API call should be triggered because the TTL expired\n        let second_call = sut.node_info().await.unwrap();\n\n        // then\n        assert_eq!(first_call, original_node_info);\n        assert_eq!(second_call, changed_node_info);\n    }\n}\n"
  },
  {
    "path": "packages/fuels-accounts/src/provider/retry_util.rs",
    "content": "use std::{fmt::Debug, future::Future, num::NonZeroU32, time::Duration};\n\nuse fuels_core::types::errors::{Result, error};\n\n/// A set of strategies to control retry intervals between attempts.\n///\n/// The `Backoff` enum defines different strategies for managing intervals between retry attempts.\n/// Each strategy allows you to customize the waiting time before a new attempt based on the\n/// number of attempts made.\n///\n/// # Variants\n///\n/// - `Linear(Duration)`: Increases the waiting time linearly with each attempt.\n/// - `Exponential(Duration)`: Doubles the waiting time with each attempt.\n/// - `Fixed(Duration)`: Uses a constant waiting time between attempts.\n///\n/// # Examples\n///\n/// ```rust\n/// use std::time::Duration;\n/// use fuels_accounts::provider::Backoff;\n///\n/// let linear_backoff = Backoff::Linear(Duration::from_secs(2));\n/// let exponential_backoff = Backoff::Exponential(Duration::from_secs(1));\n/// let fixed_backoff = Backoff::Fixed(Duration::from_secs(5));\n/// ```\n//ANCHOR: backoff\n#[derive(Debug, Clone)]\npub enum Backoff {\n    Linear(Duration),\n    Exponential(Duration),\n    Fixed(Duration),\n}\n//ANCHOR_END: backoff\n\nimpl Default for Backoff {\n    fn default() -> Self {\n        Backoff::Linear(Duration::from_millis(10))\n    }\n}\n\nimpl Backoff {\n    pub fn wait_duration(&self, attempt: u32) -> Duration {\n        match self {\n            Backoff::Linear(base_duration) => *base_duration * (attempt + 1),\n            Backoff::Exponential(base_duration) => *base_duration * 2u32.pow(attempt),\n            Backoff::Fixed(interval) => *interval,\n        }\n    }\n}\n\n/// Configuration for controlling retry behavior.\n///\n/// The `RetryConfig` struct encapsulates the configuration parameters for controlling the retry behavior\n/// of asynchronous actions. It includes the maximum number of attempts and the interval strategy from\n/// the `Backoff` enum that determines how much time to wait between retry attempts.\n///\n/// # Fields\n///\n/// - `max_attempts`: The maximum number of attempts before giving up.\n/// - `interval`: The chosen interval strategy from the `Backoff` enum.\n///\n/// # Examples\n///\n/// ```rust\n/// use std::num::NonZeroUsize;\n/// use std::time::Duration;\n/// use fuels_accounts::provider::{Backoff, RetryConfig};\n///\n/// let max_attempts = 5;\n/// let interval_strategy = Backoff::Exponential(Duration::from_secs(1));\n///\n/// let retry_config = RetryConfig::new(max_attempts, interval_strategy).unwrap();\n/// ```\n// ANCHOR: retry_config\n#[derive(Clone, Debug)]\npub struct RetryConfig {\n    max_attempts: NonZeroU32,\n    interval: Backoff,\n}\n// ANCHOR_END: retry_config\n\nimpl RetryConfig {\n    pub fn new(max_attempts: u32, interval: Backoff) -> Result<Self> {\n        let max_attempts = NonZeroU32::new(max_attempts)\n            .ok_or_else(|| error!(Other, \"`max_attempts` must be greater than `0`\"))?;\n\n        Ok(RetryConfig {\n            max_attempts,\n            interval,\n        })\n    }\n}\n\nimpl Default for RetryConfig {\n    fn default() -> Self {\n        Self {\n            max_attempts: NonZeroU32::new(1).expect(\"should not fail\"),\n            interval: Default::default(),\n        }\n    }\n}\n\n/// Retries an asynchronous action with customizable retry behavior.\n///\n/// This function takes an asynchronous action represented by a closure `action`.\n/// The action is executed repeatedly with backoff and retry logic based on the\n/// provided `retry_config` and the `should_retry` condition.\n///\n/// The `action` closure should return a `Future` that resolves to a `Result<T, K>`,\n/// where `T` represents the success type and `K` represents the error type.\n///\n/// # Parameters\n///\n/// - `action`: The asynchronous action to be retried.\n/// - `retry_config`: A reference to the retry configuration.\n/// - `should_retry`: A closure that determines whether to retry based on the result.\n///\n/// # Return\n///\n/// Returns `Ok(T)` if the action succeeds without requiring further retries.\n/// Returns `Err(Error)` if the maximum number of attempts is reached and the action\n/// still fails. If a retryable error occurs during the attempts, the error will\n/// be returned if the `should_retry` condition allows further retries.\npub(crate) async fn retry<Fut, T, ShouldRetry>(\n    mut action: impl FnMut() -> Fut,\n    retry_config: &RetryConfig,\n    should_retry: ShouldRetry,\n) -> T\nwhere\n    Fut: Future<Output = T>,\n    ShouldRetry: Fn(&T) -> bool,\n{\n    let mut last_result = None;\n\n    for attempt in 0..retry_config.max_attempts.into() {\n        let result = action().await;\n\n        if should_retry(&result) {\n            last_result = Some(result)\n        } else {\n            return result;\n        }\n\n        tokio::time::sleep(retry_config.interval.wait_duration(attempt)).await;\n    }\n\n    last_result.expect(\"should not happen\")\n}\n\n#[cfg(test)]\nmod tests {\n    mod retry_until {\n        use std::time::{Duration, Instant};\n\n        use fuels_core::types::errors::{Result, error};\n        use tokio::sync::Mutex;\n\n        use crate::provider::{Backoff, RetryConfig, retry_util};\n\n        #[tokio::test]\n        async fn returns_last_received_response() -> Result<()> {\n            // given\n            let err_msgs = [\"err1\", \"err2\", \"err3\"];\n            let number_of_attempts = Mutex::new(0usize);\n\n            let will_always_fail = || async {\n                let msg = err_msgs[*number_of_attempts.lock().await];\n                *number_of_attempts.lock().await += 1;\n\n                msg\n            };\n\n            let should_retry_fn = |_res: &_| -> bool { true };\n\n            let retry_options = RetryConfig::new(3, Backoff::Linear(Duration::from_millis(10)))?;\n\n            // when\n            let response =\n                retry_util::retry(will_always_fail, &retry_options, should_retry_fn).await;\n\n            // then\n            assert_eq!(response, \"err3\");\n\n            Ok(())\n        }\n\n        #[tokio::test]\n        async fn stops_retrying_when_predicate_is_satisfied() -> Result<()> {\n            // given\n            let values = Mutex::new(vec![1, 2, 3]);\n\n            let will_always_fail = || async { values.lock().await.pop().unwrap() };\n\n            let should_retry_fn = |res: &i32| *res != 2;\n\n            let retry_options = RetryConfig::new(3, Backoff::Linear(Duration::from_millis(10)))?;\n\n            // when\n            let response =\n                retry_util::retry(will_always_fail, &retry_options, should_retry_fn).await;\n\n            // then\n            assert_eq!(response, 2);\n\n            Ok(())\n        }\n\n        #[tokio::test]\n        async fn retry_respects_delay_between_attempts_fixed() -> Result<()> {\n            // given\n            let timestamps: Mutex<Vec<Instant>> = Mutex::new(vec![]);\n\n            let will_fail_and_record_timestamp = || async {\n                timestamps.lock().await.push(Instant::now());\n                Result::<()>::Err(error!(Other, \"error\"))\n            };\n\n            let should_retry_fn = |_res: &_| -> bool { true };\n\n            let retry_options = RetryConfig::new(3, Backoff::Fixed(Duration::from_millis(100)))?;\n\n            // when\n            let _ = retry_util::retry(\n                will_fail_and_record_timestamp,\n                &retry_options,\n                should_retry_fn,\n            )\n            .await;\n\n            // then\n            let timestamps_vec = timestamps.lock().await.clone();\n\n            let timestamps_spaced_out_at_least_100_mills = timestamps_vec\n                .iter()\n                .zip(timestamps_vec.iter().skip(1))\n                .all(|(current_timestamp, the_next_timestamp)| {\n                    the_next_timestamp.duration_since(*current_timestamp)\n                        >= Duration::from_millis(100)\n                });\n\n            assert!(\n                timestamps_spaced_out_at_least_100_mills,\n                \"retry did not wait for the specified time between attempts\"\n            );\n\n            Ok(())\n        }\n\n        #[tokio::test]\n        async fn retry_respects_delay_between_attempts_linear() -> Result<()> {\n            // given\n            let timestamps: Mutex<Vec<Instant>> = Mutex::new(vec![]);\n\n            let will_fail_and_record_timestamp = || async {\n                timestamps.lock().await.push(Instant::now());\n                Result::<()>::Err(error!(Other, \"error\"))\n            };\n\n            let should_retry_fn = |_res: &_| -> bool { true };\n\n            let retry_options = RetryConfig::new(3, Backoff::Linear(Duration::from_millis(100)))?;\n\n            // when\n            let _ = retry_util::retry(\n                will_fail_and_record_timestamp,\n                &retry_options,\n                should_retry_fn,\n            )\n            .await;\n\n            // then\n            let timestamps_vec = timestamps.lock().await.clone();\n\n            let timestamps_spaced_out_at_least_100_mills = timestamps_vec\n                .iter()\n                .zip(timestamps_vec.iter().skip(1))\n                .enumerate()\n                .all(|(attempt, (current_timestamp, the_next_timestamp))| {\n                    the_next_timestamp.duration_since(*current_timestamp)\n                        >= (Duration::from_millis(100) * (attempt + 1) as u32)\n                });\n\n            assert!(\n                timestamps_spaced_out_at_least_100_mills,\n                \"retry did not wait for the specified time between attempts\"\n            );\n\n            Ok(())\n        }\n\n        #[tokio::test]\n        async fn retry_respects_delay_between_attempts_exponential() -> Result<()> {\n            // given\n            let timestamps: Mutex<Vec<Instant>> = Mutex::new(vec![]);\n\n            let will_fail_and_record_timestamp = || async {\n                timestamps.lock().await.push(Instant::now());\n                Result::<()>::Err(error!(Other, \"error\"))\n            };\n\n            let should_retry_fn = |_res: &_| -> bool { true };\n\n            let retry_options =\n                RetryConfig::new(3, Backoff::Exponential(Duration::from_millis(100)))?;\n\n            // when\n            let _ = retry_util::retry(\n                will_fail_and_record_timestamp,\n                &retry_options,\n                should_retry_fn,\n            )\n            .await;\n\n            // then\n            let timestamps_vec = timestamps.lock().await.clone();\n\n            let timestamps_spaced_out_at_least_100_mills = timestamps_vec\n                .iter()\n                .zip(timestamps_vec.iter().skip(1))\n                .enumerate()\n                .all(|(attempt, (current_timestamp, the_next_timestamp))| {\n                    the_next_timestamp.duration_since(*current_timestamp)\n                        >= (Duration::from_millis(100) * (2_usize.pow((attempt) as u32)) as u32)\n                });\n\n            assert!(\n                timestamps_spaced_out_at_least_100_mills,\n                \"retry did not wait for the specified time between attempts\"\n            );\n\n            Ok(())\n        }\n    }\n}\n"
  },
  {
    "path": "packages/fuels-accounts/src/provider/retryable_client.rs",
    "content": "use std::{future::Future, io};\n\nuse async_trait::async_trait;\nuse custom_queries::{ContractExistsQuery, IsUserAccountQuery, IsUserAccountVariables};\nuse cynic::QueryBuilder;\nuse fuel_core_client::client::{\n    FuelClient,\n    pagination::{PaginatedResult, PaginationRequest},\n    schema::contract::ContractByIdArgs,\n    types::{\n        Balance, Blob, Block, ChainInfo, Coin, CoinType, ContractBalance, Message, MessageProof,\n        NodeInfo, TransactionResponse, TransactionStatus,\n        gas_price::{EstimateGasPrice, LatestGasPrice},\n        primitives::{BlockId, TransactionId},\n    },\n};\nuse fuel_core_types::services::executor::TransactionExecutionStatus;\nuse fuel_tx::{BlobId, ConsensusParameters, Transaction, TxId, UtxoId};\nuse fuel_types::{Address, AssetId, BlockHeight, ContractId, Nonce};\nuse fuels_core::types::errors::{Error, Result, error};\nuse futures::Stream;\n\nuse super::{\n    cache::CacheableRpcs,\n    supported_versions::{self, VersionCompatibility},\n};\nuse crate::provider::{RetryConfig, retry_util};\n\n#[derive(Debug, thiserror::Error)]\npub(crate) enum RequestError {\n    #[error(\"io error: {0}\")]\n    IO(String),\n}\n\ntype RequestResult<T> = std::result::Result<T, RequestError>;\n\nimpl From<RequestError> for Error {\n    fn from(e: RequestError) -> Self {\n        Error::Provider(e.to_string())\n    }\n}\n\n#[derive(Debug, Clone)]\npub(crate) struct RetryableClient {\n    client: FuelClient,\n    url: String,\n    retry_config: RetryConfig,\n    prepend_warning: Option<String>,\n}\n\n#[async_trait]\nimpl CacheableRpcs for RetryableClient {\n    async fn consensus_parameters(&self) -> Result<ConsensusParameters> {\n        Ok(self.chain_info().await?.consensus_parameters)\n    }\n\n    async fn node_info(&self) -> Result<NodeInfo> {\n        Ok(self.node_info().await?)\n    }\n}\n\nimpl RetryableClient {\n    pub(crate) async fn connect(url: impl AsRef<str>, retry_config: RetryConfig) -> Result<Self> {\n        let url = url.as_ref().to_string();\n        let client = FuelClient::new(&url).map_err(|e| error!(Provider, \"{e}\"))?;\n\n        let node_info = client.node_info().await?;\n        let warning = Self::version_compatibility_warning(&node_info)?;\n\n        Ok(Self {\n            client,\n            retry_config,\n            url,\n            prepend_warning: warning,\n        })\n    }\n\n    fn version_compatibility_warning(node_info: &NodeInfo) -> Result<Option<String>> {\n        let node_version = node_info\n            .node_version\n            .parse::<semver::Version>()\n            .map_err(|e| error!(Provider, \"could not parse Fuel client version: {}\", e))?;\n\n        let VersionCompatibility {\n            supported_version,\n            is_major_supported,\n            is_minor_supported,\n            ..\n        } = supported_versions::compare_node_compatibility(node_version.clone());\n\n        let msg = if !is_major_supported || !is_minor_supported {\n            Some(format!(\n                \"warning: the fuel node version to which this provider is connected has a semver incompatible version from the one the SDK was developed against. Connected node version: {node_version}, supported version: {supported_version}\",\n            ))\n        } else {\n            None\n        };\n\n        Ok(msg)\n    }\n\n    pub(crate) fn url(&self) -> &str {\n        &self.url\n    }\n\n    pub fn client(&self) -> &FuelClient {\n        &self.client\n    }\n\n    pub(crate) fn set_retry_config(&mut self, retry_config: RetryConfig) {\n        self.retry_config = retry_config;\n    }\n\n    async fn wrap<T, Fut>(&self, action: impl Fn() -> Fut) -> RequestResult<T>\n    where\n        Fut: Future<Output = io::Result<T>>,\n    {\n        retry_util::retry(action, &self.retry_config, |result| result.is_err())\n            .await\n            .map_err(|e| {\n                let msg = if let Some(warning) = &self.prepend_warning {\n                    format!(\"{warning}. {e}\")\n                } else {\n                    e.to_string()\n                };\n                RequestError::IO(msg)\n            })\n    }\n\n    // DELEGATION START\n    pub async fn health(&self) -> RequestResult<bool> {\n        self.wrap(|| self.client.health()).await\n    }\n\n    pub async fn transaction(&self, id: &TxId) -> RequestResult<Option<TransactionResponse>> {\n        self.wrap(|| self.client.transaction(id)).await\n    }\n\n    pub(crate) async fn chain_info(&self) -> RequestResult<ChainInfo> {\n        self.wrap(|| self.client.chain_info()).await\n    }\n\n    pub async fn await_transaction_commit(&self, id: &TxId) -> RequestResult<TransactionStatus> {\n        self.wrap(|| self.client.await_transaction_commit(id)).await\n    }\n\n    pub async fn submit_and_await_commit(\n        &self,\n        tx: &Transaction,\n    ) -> RequestResult<TransactionStatus> {\n        self.wrap(|| self.client.submit_and_await_commit(tx)).await\n    }\n\n    pub async fn submit_and_await_status<'a>(\n        &'a self,\n        tx: &'a Transaction,\n        include_preconfirmation: bool,\n    ) -> RequestResult<impl Stream<Item = io::Result<TransactionStatus>> + 'a> {\n        self.wrap(|| {\n            self.client\n                .submit_and_await_status_opt(tx, None, Some(include_preconfirmation))\n        })\n        .await\n    }\n\n    pub async fn subscribe_transaction_status<'a>(\n        &'a self,\n        id: &'a TxId,\n        include_preconfirmation: bool,\n    ) -> RequestResult<impl Stream<Item = io::Result<TransactionStatus>> + 'a> {\n        self.wrap(|| {\n            self.client\n                .subscribe_transaction_status_opt(id, Some(include_preconfirmation))\n        })\n        .await\n    }\n\n    pub async fn submit(&self, tx: &Transaction) -> RequestResult<TransactionId> {\n        self.wrap(|| self.client.submit(tx)).await\n    }\n\n    pub async fn transaction_status(&self, id: &TxId) -> RequestResult<TransactionStatus> {\n        self.wrap(|| self.client.transaction_status(id)).await\n    }\n\n    pub async fn node_info(&self) -> RequestResult<NodeInfo> {\n        self.wrap(|| self.client.node_info()).await\n    }\n\n    pub async fn blob(&self, blob_id: BlobId) -> RequestResult<Option<Blob>> {\n        self.wrap(|| self.client.blob(blob_id)).await\n    }\n\n    pub async fn blob_exists(&self, blob_id: BlobId) -> RequestResult<bool> {\n        self.wrap(|| self.client.blob_exists(blob_id)).await\n    }\n\n    pub async fn latest_gas_price(&self) -> RequestResult<LatestGasPrice> {\n        self.wrap(|| self.client.latest_gas_price()).await\n    }\n\n    pub async fn estimate_gas_price(&self, block_horizon: u32) -> RequestResult<EstimateGasPrice> {\n        self.wrap(|| self.client.estimate_gas_price(block_horizon))\n            .await\n            .map(Into::into)\n    }\n\n    pub async fn estimate_predicates(&self, tx: &Transaction) -> RequestResult<Transaction> {\n        self.wrap(|| async {\n            let mut new_tx = tx.clone();\n            self.client.estimate_predicates(&mut new_tx).await?;\n            Ok(new_tx)\n        })\n        .await\n    }\n\n    pub async fn dry_run(\n        &self,\n        tx: &[Transaction],\n    ) -> RequestResult<Vec<TransactionExecutionStatus>> {\n        self.wrap(|| self.client.dry_run(tx)).await\n    }\n\n    pub async fn dry_run_opt(\n        &self,\n        tx: &[Transaction],\n        utxo_validation: Option<bool>,\n        gas_price: Option<u64>,\n        at_height: Option<BlockHeight>,\n    ) -> RequestResult<Vec<TransactionExecutionStatus>> {\n        self.wrap(|| {\n            self.client\n                .dry_run_opt(tx, utxo_validation, gas_price, at_height)\n        })\n        .await\n    }\n\n    pub async fn coins(\n        &self,\n        owner: &Address,\n        asset_id: Option<&AssetId>,\n        request: PaginationRequest<String>,\n    ) -> RequestResult<PaginatedResult<Coin, String>> {\n        self.wrap(move || self.client.coins(owner, asset_id, request.clone()))\n            .await\n    }\n\n    pub async fn coins_to_spend(\n        &self,\n        owner: &Address,\n        spend_query: Vec<(AssetId, u128, Option<u16>)>,\n        excluded_ids: Option<(Vec<UtxoId>, Vec<Nonce>)>,\n    ) -> RequestResult<Vec<Vec<CoinType>>> {\n        self.wrap(move || {\n            self.client\n                .coins_to_spend(owner, spend_query.clone(), excluded_ids.clone())\n        })\n        .await\n    }\n\n    pub async fn balance(\n        &self,\n        owner: &Address,\n        asset_id: Option<&AssetId>,\n    ) -> RequestResult<u128> {\n        self.wrap(|| self.client.balance(owner, asset_id)).await\n    }\n\n    pub async fn contract_balance(\n        &self,\n        id: &ContractId,\n        asset: Option<&AssetId>,\n    ) -> RequestResult<u64> {\n        self.wrap(|| self.client.contract_balance(id, asset)).await\n    }\n\n    pub async fn contract_balances(\n        &self,\n        contract: &ContractId,\n        request: PaginationRequest<String>,\n    ) -> RequestResult<PaginatedResult<ContractBalance, String>> {\n        self.wrap(|| self.client.contract_balances(contract, request.clone()))\n            .await\n    }\n\n    pub async fn balances(\n        &self,\n        owner: &Address,\n        request: PaginationRequest<String>,\n    ) -> RequestResult<PaginatedResult<Balance, String>> {\n        self.wrap(|| self.client.balances(owner, request.clone()))\n            .await\n    }\n\n    pub async fn transactions(\n        &self,\n        request: PaginationRequest<String>,\n    ) -> RequestResult<PaginatedResult<TransactionResponse, String>> {\n        self.wrap(|| self.client.transactions(request.clone()))\n            .await\n    }\n\n    pub async fn transactions_by_owner(\n        &self,\n        owner: &Address,\n        request: PaginationRequest<String>,\n    ) -> RequestResult<PaginatedResult<TransactionResponse, String>> {\n        self.wrap(|| self.client.transactions_by_owner(owner, request.clone()))\n            .await\n    }\n\n    pub async fn produce_blocks(\n        &self,\n        blocks_to_produce: u32,\n        start_timestamp: Option<u64>,\n    ) -> RequestResult<BlockHeight> {\n        self.wrap(|| {\n            self.client\n                .produce_blocks(blocks_to_produce, start_timestamp)\n        })\n        .await\n    }\n\n    pub async fn block(&self, id: &BlockId) -> RequestResult<Option<Block>> {\n        self.wrap(|| self.client.block(id)).await\n    }\n\n    pub async fn block_by_height(&self, height: BlockHeight) -> RequestResult<Option<Block>> {\n        self.wrap(|| self.client.block_by_height(height)).await\n    }\n\n    pub async fn blocks(\n        &self,\n        request: PaginationRequest<String>,\n    ) -> RequestResult<PaginatedResult<Block, String>> {\n        self.wrap(|| self.client.blocks(request.clone())).await\n    }\n\n    pub async fn messages(\n        &self,\n        owner: Option<&Address>,\n        request: PaginationRequest<String>,\n    ) -> RequestResult<PaginatedResult<Message, String>> {\n        self.wrap(|| self.client.messages(owner, request.clone()))\n            .await\n    }\n\n    /// Request a merkle proof of an output message.\n    pub async fn message_proof(\n        &self,\n        transaction_id: &TxId,\n        nonce: &Nonce,\n        commit_block_id: Option<&BlockId>,\n        commit_block_height: Option<BlockHeight>,\n    ) -> RequestResult<MessageProof> {\n        self.wrap(|| {\n            self.client\n                .message_proof(transaction_id, nonce, commit_block_id, commit_block_height)\n        })\n        .await\n    }\n\n    pub async fn contract_exists(&self, contract_id: &ContractId) -> RequestResult<bool> {\n        self.wrap(|| {\n            let query = ContractExistsQuery::build(ContractByIdArgs {\n                id: (*contract_id).into(),\n            });\n            self.client.query(query)\n        })\n        .await\n        .map(|query| {\n            query\n                .contract\n                .map(|contract| ContractId::from(contract.id) == *contract_id)\n                .unwrap_or(false)\n        })\n    }\n    // DELEGATION END\n\n    pub async fn is_user_account(&self, address: [u8; 32]) -> Result<bool> {\n        let blob_id = BlobId::from(address);\n        let contract_id = ContractId::from(address);\n        let transaction_id = TransactionId::from(address);\n\n        let query = IsUserAccountQuery::build(IsUserAccountVariables {\n            blob_id: blob_id.into(),\n            contract_id: contract_id.into(),\n            transaction_id: transaction_id.into(),\n        });\n\n        let response = self.client.query(query).await?;\n\n        let is_resource = response.blob.is_some()\n            || response.contract.is_some()\n            || response.transaction.is_some();\n\n        Ok(!is_resource)\n    }\n}\n\nmod custom_queries {\n    use fuel_core_client::client::schema::{\n        BlobId, ContractId, TransactionId,\n        blob::BlobIdFragment,\n        contract::{ContractByIdArgsFields, ContractIdFragment},\n        schema,\n        tx::TransactionIdFragment,\n    };\n\n    #[derive(cynic::QueryVariables, Debug, Clone)]\n    pub struct IsUserAccountVariables {\n        pub blob_id: BlobId,\n        pub contract_id: ContractId,\n        pub transaction_id: TransactionId,\n    }\n\n    #[derive(cynic::QueryFragment, Debug)]\n    #[cynic(\n        graphql_type = \"Query\",\n        variables = \"IsUserAccountVariables\",\n        schema_path = \"./src/schema/schema.sdl\"\n    )]\n    pub struct IsUserAccountQuery {\n        #[arguments(id: $blob_id)]\n        pub blob: Option<BlobIdFragment>,\n        #[arguments(id: $contract_id)]\n        pub contract: Option<ContractIdFragment>,\n        #[arguments(id: $transaction_id)]\n        pub transaction: Option<TransactionIdFragment>,\n    }\n\n    #[derive(cynic::QueryFragment, Clone, Debug)]\n    #[cynic(\n        schema_path = \"./src/schema/schema.sdl\",\n        graphql_type = \"Query\",\n        variables = \"ContractByIdArgs\"\n    )]\n    pub struct ContractExistsQuery {\n        #[arguments(id: $id)]\n        pub contract: Option<ContractIdFragment>,\n    }\n}\n"
  },
  {
    "path": "packages/fuels-accounts/src/provider/supported_fuel_core_version.rs",
    "content": "pub const SUPPORTED_FUEL_CORE_VERSION: semver::Version = semver::Version::new(0, 47, 1);\n"
  },
  {
    "path": "packages/fuels-accounts/src/provider/supported_versions.rs",
    "content": "use semver::Version;\n\nuse crate::provider::supported_fuel_core_version::SUPPORTED_FUEL_CORE_VERSION;\n\n#[derive(Debug, PartialEq, Eq)]\npub(crate) struct VersionCompatibility {\n    pub(crate) supported_version: Version,\n    pub(crate) is_major_supported: bool,\n    pub(crate) is_minor_supported: bool,\n    pub(crate) is_patch_supported: bool,\n}\n\npub(crate) fn compare_node_compatibility(network_version: Version) -> VersionCompatibility {\n    check_version_compatibility(network_version, SUPPORTED_FUEL_CORE_VERSION)\n}\n\nfn check_version_compatibility(\n    actual_version: Version,\n    expected_version: Version,\n) -> VersionCompatibility {\n    let is_major_supported = expected_version.major == actual_version.major;\n    let is_minor_supported = expected_version.minor == actual_version.minor;\n    let is_patch_supported = expected_version.patch == actual_version.patch;\n\n    VersionCompatibility {\n        supported_version: expected_version,\n        is_major_supported,\n        is_minor_supported,\n        is_patch_supported,\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn should_validate_all_possible_version_mismatches() {\n        let expected_version = \"0.1.2\".parse::<Version>().unwrap();\n\n        assert_eq!(\n            check_version_compatibility(\"1.1.2\".parse().unwrap(), expected_version.clone()),\n            VersionCompatibility {\n                is_major_supported: false,\n                is_minor_supported: true,\n                is_patch_supported: true,\n                supported_version: expected_version.clone()\n            }\n        );\n\n        assert_eq!(\n            check_version_compatibility(\"1.2.2\".parse().unwrap(), expected_version.clone()),\n            VersionCompatibility {\n                is_major_supported: false,\n                is_minor_supported: false,\n                is_patch_supported: true,\n                supported_version: expected_version.clone()\n            }\n        );\n\n        assert_eq!(\n            check_version_compatibility(\"1.1.3\".parse().unwrap(), expected_version.clone()),\n            VersionCompatibility {\n                is_major_supported: false,\n                is_minor_supported: true,\n                is_patch_supported: false,\n                supported_version: expected_version.clone()\n            }\n        );\n\n        assert_eq!(\n            check_version_compatibility(\"0.2.2\".parse().unwrap(), expected_version.clone()),\n            VersionCompatibility {\n                is_major_supported: true,\n                is_minor_supported: false,\n                is_patch_supported: true,\n                supported_version: expected_version.clone()\n            }\n        );\n\n        assert_eq!(\n            check_version_compatibility(\"0.2.3\".parse().unwrap(), expected_version.clone()),\n            VersionCompatibility {\n                is_major_supported: true,\n                is_minor_supported: false,\n                is_patch_supported: false,\n                supported_version: expected_version.clone()\n            }\n        );\n\n        assert_eq!(\n            check_version_compatibility(\"0.1.3\".parse().unwrap(), expected_version.clone()),\n            VersionCompatibility {\n                is_major_supported: true,\n                is_minor_supported: true,\n                is_patch_supported: false,\n                supported_version: expected_version.clone()\n            }\n        );\n\n        assert_eq!(\n            check_version_compatibility(\"0.1.2\".parse().unwrap(), expected_version.clone()),\n            VersionCompatibility {\n                is_major_supported: true,\n                is_minor_supported: true,\n                is_patch_supported: true,\n                supported_version: expected_version.clone()\n            }\n        );\n    }\n}\n"
  },
  {
    "path": "packages/fuels-accounts/src/provider.rs",
    "content": "#[cfg(feature = \"coin-cache\")]\nuse std::sync::Arc;\nuse std::{collections::HashMap, fmt::Debug, net::SocketAddr};\n\nmod cache;\nmod retry_util;\nmod retryable_client;\nmod supported_fuel_core_version;\nmod supported_versions;\n\npub use cache::TtlConfig;\nuse cache::{CachedClient, SystemClock};\nuse chrono::{DateTime, Utc};\nuse fuel_core_client::client::{\n    FuelClient,\n    pagination::{PageDirection, PaginatedResult, PaginationRequest},\n    types::{\n        balance::Balance,\n        contract::ContractBalance,\n        gas_price::{EstimateGasPrice, LatestGasPrice},\n    },\n};\nuse fuel_core_types::services::executor::TransactionExecutionResult;\nuse fuel_tx::{\n    AssetId, ConsensusParameters, Receipt, Transaction as FuelTransaction, TxId, UtxoId,\n};\n\n#[cfg(feature = \"coin-cache\")]\nuse fuels_core::types::coin_type_id::CoinTypeId;\nuse fuels_core::{\n    constants::{DEFAULT_GAS_ESTIMATION_BLOCK_HORIZON, DEFAULT_GAS_ESTIMATION_TOLERANCE},\n    types::{\n        Address, BlockHeight, Bytes32, ContractId, DryRun, DryRunner, Nonce,\n        block::{Block, Header},\n        chain_info::ChainInfo,\n        coin::Coin,\n        coin_type::CoinType,\n        errors::Result,\n        message::Message,\n        message_proof::MessageProof,\n        node_info::NodeInfo,\n        transaction::{Transaction, Transactions},\n        transaction_builders::{Blob, BlobId},\n        transaction_response::TransactionResponse,\n        tx_status::TxStatus,\n    },\n};\nuse futures::StreamExt;\npub use retry_util::{Backoff, RetryConfig};\npub use supported_fuel_core_version::SUPPORTED_FUEL_CORE_VERSION;\nuse tai64::Tai64;\n#[cfg(feature = \"coin-cache\")]\nuse tokio::sync::Mutex;\n\n#[cfg(feature = \"coin-cache\")]\nuse crate::coin_cache::CoinsCache;\nuse crate::provider::{cache::CacheableRpcs, retryable_client::RetryableClient};\n\nconst NUM_RESULTS_PER_REQUEST: i32 = 100;\n\n#[derive(Debug, Clone, PartialEq)]\n// ANCHOR: transaction_cost\npub struct TransactionCost {\n    pub gas_price: u64,\n    pub metered_bytes_size: u64,\n    pub total_fee: u64,\n    pub script_gas: u64,\n    pub total_gas: u64,\n}\n// ANCHOR_END: transaction_cost\n\npub(crate) struct ResourceQueries {\n    utxos: Vec<UtxoId>,\n    messages: Vec<Nonce>,\n    asset_id: Option<AssetId>,\n    amount: u128,\n}\n\nimpl ResourceQueries {\n    pub fn exclusion_query(&self) -> Option<(Vec<UtxoId>, Vec<Nonce>)> {\n        if self.utxos.is_empty() && self.messages.is_empty() {\n            return None;\n        }\n\n        Some((self.utxos.clone(), self.messages.clone()))\n    }\n\n    pub fn spend_query(&self, base_asset_id: AssetId) -> Vec<(AssetId, u128, Option<u16>)> {\n        vec![(self.asset_id.unwrap_or(base_asset_id), self.amount, None)]\n    }\n}\n\n#[derive(Default)]\n// ANCHOR: resource_filter\npub struct ResourceFilter {\n    pub from: Address,\n    pub asset_id: Option<AssetId>,\n    pub amount: u128,\n    pub excluded_utxos: Vec<UtxoId>,\n    pub excluded_message_nonces: Vec<Nonce>,\n}\n// ANCHOR_END: resource_filter\n\nimpl ResourceFilter {\n    pub fn owner(&self) -> Address {\n        self.from\n    }\n\n    pub(crate) fn resource_queries(&self) -> ResourceQueries {\n        ResourceQueries {\n            utxos: self.excluded_utxos.clone(),\n            messages: self.excluded_message_nonces.clone(),\n            asset_id: self.asset_id,\n            amount: self.amount,\n        }\n    }\n}\n\n/// Encapsulates common client operations in the SDK.\n/// Note that you may also use `client`, which is an instance\n/// of `FuelClient`, directly, which provides a broader API.\n#[derive(Debug, Clone)]\npub struct Provider {\n    cached_client: CachedClient<RetryableClient>,\n    #[cfg(feature = \"coin-cache\")]\n    coins_cache: Arc<Mutex<CoinsCache>>,\n}\n\nimpl Provider {\n    pub async fn from(addr: impl Into<SocketAddr>) -> Result<Self> {\n        let addr = addr.into();\n        Self::connect(format!(\"http://{addr}\")).await\n    }\n\n    /// Returns the underlying uncached client.\n    pub fn client(&self) -> &FuelClient {\n        self.cached_client.inner().client()\n    }\n\n    pub fn set_cache_ttl(&mut self, ttl: TtlConfig) {\n        self.cached_client.set_ttl(ttl);\n    }\n\n    pub async fn clear_cache(&self) {\n        self.cached_client.clear().await;\n    }\n\n    pub async fn healthy(&self) -> Result<bool> {\n        Ok(self.uncached_client().health().await?)\n    }\n\n    /// Connects to an existing node at the given address.\n    pub async fn connect(url: impl AsRef<str>) -> Result<Provider> {\n        let client = CachedClient::new(\n            RetryableClient::connect(&url, Default::default()).await?,\n            TtlConfig::default(),\n            SystemClock,\n        );\n\n        Ok(Self {\n            cached_client: client,\n            #[cfg(feature = \"coin-cache\")]\n            coins_cache: Default::default(),\n        })\n    }\n\n    pub fn url(&self) -> &str {\n        self.uncached_client().url()\n    }\n\n    pub async fn blob(&self, blob_id: BlobId) -> Result<Option<Blob>> {\n        Ok(self\n            .uncached_client()\n            .blob(blob_id.into())\n            .await?\n            .map(|blob| Blob::new(blob.bytecode)))\n    }\n\n    pub async fn blob_exists(&self, blob_id: BlobId) -> Result<bool> {\n        Ok(self.uncached_client().blob_exists(blob_id.into()).await?)\n    }\n\n    /// Sends a transaction to the underlying Provider's client.\n    pub async fn send_transaction_and_await_commit<T: Transaction>(\n        &self,\n        tx: T,\n    ) -> Result<TxStatus> {\n        #[cfg(feature = \"coin-cache\")]\n        let base_asset_id = *self.consensus_parameters().await?.base_asset_id();\n\n        #[cfg(feature = \"coin-cache\")]\n        self.check_inputs_already_in_cache(&tx.used_coins(&base_asset_id))\n            .await?;\n\n        let tx = self.prepare_transaction_for_sending(tx).await?;\n        let tx_status = self\n            .uncached_client()\n            .submit_and_await_commit(&tx.clone().into())\n            .await?\n            .into();\n\n        #[cfg(feature = \"coin-cache\")]\n        if matches!(\n            tx_status,\n            TxStatus::SqueezedOut { .. } | TxStatus::Failure { .. }\n        ) {\n            self.coins_cache\n                .lock()\n                .await\n                .remove_items(tx.used_coins(&base_asset_id))\n        }\n\n        Ok(tx_status)\n    }\n\n    /// Similar to `send_transaction_and_await_commit`,\n    /// but collect all the status received until a final one and return them.\n    pub async fn send_transaction_and_await_status<T: Transaction>(\n        &self,\n        tx: T,\n        include_preconfirmation: bool,\n    ) -> Result<Vec<Result<TxStatus>>> {\n        #[cfg(feature = \"coin-cache\")]\n        let base_asset_id = *self.consensus_parameters().await?.base_asset_id();\n        #[cfg(feature = \"coin-cache\")]\n        let used_base_coins = tx.used_coins(&base_asset_id);\n\n        #[cfg(feature = \"coin-cache\")]\n        self.check_inputs_already_in_cache(&used_base_coins).await?;\n\n        let tx = self.prepare_transaction_for_sending(tx).await?.into();\n        let mut stream = self\n            .uncached_client()\n            .submit_and_await_status(&tx, include_preconfirmation)\n            .await?;\n\n        let mut statuses = Vec::new();\n\n        // Process stream items until we get a final status\n        while let Some(status) = stream.next().await {\n            let tx_status = status.map(TxStatus::from).map_err(Into::into);\n\n            let is_final = tx_status.as_ref().ok().is_some_and(|s| s.is_final());\n\n            statuses.push(tx_status);\n\n            if is_final {\n                break;\n            }\n        }\n\n        // Handle cache updates for failures\n        #[cfg(feature = \"coin-cache\")]\n        if statuses.iter().any(|status| {\n            matches!(\n                &status,\n                Ok(TxStatus::SqueezedOut { .. }) | Ok(TxStatus::Failure { .. }),\n            )\n        }) {\n            self.coins_cache.lock().await.remove_items(used_base_coins);\n        }\n\n        Ok(statuses)\n    }\n\n    async fn prepare_transaction_for_sending<T: Transaction>(&self, mut tx: T) -> Result<T> {\n        let consensus_parameters = self.consensus_parameters().await?;\n        tx.precompute(&consensus_parameters.chain_id())?;\n\n        let chain_info = self.chain_info().await?;\n        let Header {\n            height: latest_block_height,\n            state_transition_bytecode_version: latest_chain_executor_version,\n            ..\n        } = chain_info.latest_block.header;\n\n        if tx.is_using_predicates() {\n            tx.estimate_predicates(self, Some(latest_chain_executor_version))\n                .await?;\n            tx.clone()\n                .validate_predicates(&consensus_parameters, latest_block_height)?;\n        }\n\n        Ok(tx)\n    }\n\n    pub async fn send_transaction<T: Transaction>(&self, tx: T) -> Result<TxId> {\n        let tx = self.prepare_transaction_for_sending(tx).await?;\n        self.submit(tx).await\n    }\n\n    pub async fn await_transaction_commit<T: Transaction>(&self, id: TxId) -> Result<TxStatus> {\n        Ok(self\n            .uncached_client()\n            .await_transaction_commit(&id)\n            .await?\n            .into())\n    }\n\n    #[cfg(not(feature = \"coin-cache\"))]\n    async fn submit<T: Transaction>(&self, tx: T) -> Result<TxId> {\n        Ok(self.uncached_client().submit(&tx.into()).await?)\n    }\n\n    #[cfg(feature = \"coin-cache\")]\n    async fn find_in_cache<'a>(\n        &self,\n        coin_ids: impl IntoIterator<Item = (&'a (Address, AssetId), &'a Vec<CoinTypeId>)>,\n    ) -> Option<((Address, AssetId), CoinTypeId)> {\n        let mut locked_cache = self.coins_cache.lock().await;\n\n        for (key, ids) in coin_ids {\n            let items = locked_cache.get_active(key);\n\n            if items.is_empty() {\n                continue;\n            }\n\n            for id in ids {\n                if items.contains(id) {\n                    return Some((*key, id.clone()));\n                }\n            }\n        }\n\n        None\n    }\n\n    #[cfg(feature = \"coin-cache\")]\n    async fn check_inputs_already_in_cache<'a>(\n        &self,\n        coin_ids: impl IntoIterator<Item = (&'a (Address, AssetId), &'a Vec<CoinTypeId>)>,\n    ) -> Result<()> {\n        use fuels_core::types::errors::{Error, transaction};\n\n        if let Some(((addr, asset_id), coin_type_id)) = self.find_in_cache(coin_ids).await {\n            let msg = match coin_type_id {\n                CoinTypeId::UtxoId(utxo_id) => format!(\"coin with utxo_id: `{utxo_id:x}`\"),\n                CoinTypeId::Nonce(nonce) => format!(\"message with nonce: `{nonce}`\"),\n            };\n            Err(Error::Transaction(transaction::Reason::Validation(\n                format!(\n                    \"{msg} was submitted recently in a transaction - attempting to spend it again will result in an error. Wallet address: `{addr}`, asset id: `{asset_id}`\"\n                ),\n            )))\n        } else {\n            Ok(())\n        }\n    }\n\n    #[cfg(feature = \"coin-cache\")]\n    async fn submit<T: Transaction>(&self, tx: T) -> Result<TxId> {\n        let consensus_parameters = self.consensus_parameters().await?;\n        let base_asset_id = consensus_parameters.base_asset_id();\n\n        let used_utxos = tx.used_coins(base_asset_id);\n        self.check_inputs_already_in_cache(&used_utxos).await?;\n\n        let tx_id = self.uncached_client().submit(&tx.into()).await?;\n        self.coins_cache.lock().await.insert_multiple(used_utxos);\n\n        Ok(tx_id)\n    }\n\n    pub async fn tx_status(&self, tx_id: &TxId) -> Result<TxStatus> {\n        Ok(self\n            .uncached_client()\n            .transaction_status(tx_id)\n            .await?\n            .into())\n    }\n\n    pub async fn subscribe_transaction_status<'a>(\n        &'a self,\n        tx_id: &'a TxId,\n        include_preconfirmation: bool,\n    ) -> Result<impl futures::Stream<Item = Result<TxStatus>> + 'a> {\n        let stream = self\n            .uncached_client()\n            .subscribe_transaction_status(tx_id, include_preconfirmation)\n            .await?;\n\n        Ok(stream.map(|status| status.map(Into::into).map_err(Into::into)))\n    }\n\n    pub async fn chain_info(&self) -> Result<ChainInfo> {\n        Ok(self.uncached_client().chain_info().await?.into())\n    }\n\n    pub async fn consensus_parameters(&self) -> Result<ConsensusParameters> {\n        self.cached_client.consensus_parameters().await\n    }\n\n    pub async fn node_info(&self) -> Result<NodeInfo> {\n        Ok(self.cached_client.node_info().await?.into())\n    }\n\n    pub async fn latest_gas_price(&self) -> Result<LatestGasPrice> {\n        Ok(self.uncached_client().latest_gas_price().await?)\n    }\n\n    pub async fn estimate_gas_price(&self, block_horizon: u32) -> Result<EstimateGasPrice> {\n        Ok(self\n            .uncached_client()\n            .estimate_gas_price(block_horizon)\n            .await?)\n    }\n\n    pub async fn dry_run(&self, tx: impl Transaction) -> Result<TxStatus> {\n        let [tx_status] = self\n            .uncached_client()\n            .dry_run(Transactions::new().insert(tx).as_slice())\n            .await?\n            .into_iter()\n            .map(Into::into)\n            .collect::<Vec<_>>()\n            .try_into()\n            .expect(\"should have only one element\");\n\n        Ok(tx_status)\n    }\n\n    pub async fn dry_run_multiple(\n        &self,\n        transactions: Transactions,\n    ) -> Result<Vec<(TxId, TxStatus)>> {\n        Ok(self\n            .uncached_client()\n            .dry_run(transactions.as_slice())\n            .await?\n            .into_iter()\n            .map(|execution_status| (execution_status.id, execution_status.into()))\n            .collect())\n    }\n\n    pub async fn dry_run_opt(\n        &self,\n        tx: impl Transaction,\n        utxo_validation: bool,\n        gas_price: Option<u64>,\n        at_height: Option<BlockHeight>,\n    ) -> Result<TxStatus> {\n        let [tx_status] = self\n            .uncached_client()\n            .dry_run_opt(\n                Transactions::new().insert(tx).as_slice(),\n                Some(utxo_validation),\n                gas_price,\n                at_height,\n            )\n            .await?\n            .into_iter()\n            .map(Into::into)\n            .collect::<Vec<_>>()\n            .try_into()\n            .expect(\"should have only one element\");\n\n        Ok(tx_status)\n    }\n\n    pub async fn dry_run_opt_multiple(\n        &self,\n        transactions: Transactions,\n        utxo_validation: bool,\n        gas_price: Option<u64>,\n        at_height: Option<BlockHeight>,\n    ) -> Result<Vec<(TxId, TxStatus)>> {\n        Ok(self\n            .uncached_client()\n            .dry_run_opt(\n                transactions.as_slice(),\n                Some(utxo_validation),\n                gas_price,\n                at_height,\n            )\n            .await?\n            .into_iter()\n            .map(|execution_status| (execution_status.id, execution_status.into()))\n            .collect())\n    }\n\n    /// Gets all unspent coins owned by address `from`, with asset ID `asset_id`.\n    pub async fn get_coins(&self, from: &Address, asset_id: AssetId) -> Result<Vec<Coin>> {\n        let mut coins: Vec<Coin> = vec![];\n        let mut cursor = None;\n\n        loop {\n            let response = self\n                .uncached_client()\n                .coins(\n                    from,\n                    Some(&asset_id),\n                    PaginationRequest {\n                        cursor: cursor.clone(),\n                        results: NUM_RESULTS_PER_REQUEST,\n                        direction: PageDirection::Forward,\n                    },\n                )\n                .await?;\n\n            if response.results.is_empty() {\n                break;\n            }\n\n            coins.extend(response.results.into_iter().map(Into::into));\n            cursor = response.cursor;\n        }\n\n        Ok(coins)\n    }\n\n    async fn request_coins_to_spend(&self, filter: ResourceFilter) -> Result<Vec<CoinType>> {\n        let queries = filter.resource_queries();\n\n        let consensus_parameters = self.consensus_parameters().await?;\n        let base_asset_id = *consensus_parameters.base_asset_id();\n\n        let res = self\n            .uncached_client()\n            .coins_to_spend(\n                &filter.owner(),\n                queries.spend_query(base_asset_id),\n                queries.exclusion_query(),\n            )\n            .await?\n            .into_iter()\n            .flatten()\n            .map(CoinType::from)\n            .collect();\n\n        Ok(res)\n    }\n\n    /// Get some spendable coins of asset `asset_id` for address `from` that add up at least to\n    /// amount `amount`. The returned coins (UTXOs) are actual coins that can be spent. The number\n    /// of coins (UXTOs) is optimized to prevent dust accumulation.\n    #[cfg(not(feature = \"coin-cache\"))]\n    pub async fn get_spendable_resources(&self, filter: ResourceFilter) -> Result<Vec<CoinType>> {\n        self.request_coins_to_spend(filter).await\n    }\n\n    /// Get some spendable coins of asset `asset_id` for address `from` that add up at least to\n    /// amount `amount`. The returned coins (UTXOs) are actual coins that can be spent. The number\n    /// of coins (UXTOs) is optimized to prevent dust accumulation.\n    /// Coins that were recently submitted inside a tx will be ignored from the results.\n    #[cfg(feature = \"coin-cache\")]\n    pub async fn get_spendable_resources(\n        &self,\n        mut filter: ResourceFilter,\n    ) -> Result<Vec<CoinType>> {\n        self.extend_filter_with_cached(&mut filter).await?;\n\n        self.request_coins_to_spend(filter).await\n    }\n\n    #[cfg(feature = \"coin-cache\")]\n    async fn extend_filter_with_cached(&self, filter: &mut ResourceFilter) -> Result<()> {\n        let consensus_parameters = self.consensus_parameters().await?;\n        let mut cache = self.coins_cache.lock().await;\n        let asset_id = filter\n            .asset_id\n            .unwrap_or(*consensus_parameters.base_asset_id());\n        let used_coins = cache.get_active(&(filter.from, asset_id));\n\n        let excluded_utxos = used_coins\n            .iter()\n            .filter_map(|coin_id| match coin_id {\n                CoinTypeId::UtxoId(utxo_id) => Some(utxo_id),\n                _ => None,\n            })\n            .cloned()\n            .collect::<Vec<_>>();\n\n        let excluded_message_nonces = used_coins\n            .iter()\n            .filter_map(|coin_id| match coin_id {\n                CoinTypeId::Nonce(nonce) => Some(nonce),\n                _ => None,\n            })\n            .cloned()\n            .collect::<Vec<_>>();\n\n        filter.excluded_utxos.extend(excluded_utxos);\n        filter\n            .excluded_message_nonces\n            .extend(excluded_message_nonces);\n\n        Ok(())\n    }\n\n    /// Get the balance of all spendable coins `asset_id` for address `address`. This is different\n    /// from getting coins because we are just returning a number (the sum of UTXOs amount) instead\n    /// of the UTXOs.\n    pub async fn get_asset_balance(&self, address: &Address, asset_id: &AssetId) -> Result<u128> {\n        Ok(self\n            .uncached_client()\n            .balance(address, Some(asset_id))\n            .await?)\n    }\n\n    /// Get the balance of all spendable coins `asset_id` for contract with id `contract_id`.\n    pub async fn get_contract_asset_balance(\n        &self,\n        contract_id: &ContractId,\n        asset_id: &AssetId,\n    ) -> Result<u64> {\n        Ok(self\n            .uncached_client()\n            .contract_balance(contract_id, Some(asset_id))\n            .await?)\n    }\n\n    /// Get all the spendable balances of all assets for address `address`. This is different from\n    /// getting the coins because we are only returning the numbers (the sum of UTXOs coins amount\n    /// for each asset id) and not the UTXOs coins themselves\n    pub async fn get_balances(&self, address: &Address) -> Result<HashMap<String, u128>> {\n        let mut balances = HashMap::new();\n\n        let mut register_balances = |results: Vec<_>| {\n            let pairs = results.into_iter().map(\n                |Balance {\n                     owner: _,\n                     amount,\n                     asset_id,\n                 }| (asset_id.to_string(), amount),\n            );\n            balances.extend(pairs);\n        };\n\n        let indexation_flags = self.cached_client.node_info().await?.indexation;\n        if indexation_flags.balances {\n            let mut cursor = None;\n            loop {\n                let pagination = PaginationRequest {\n                    cursor: cursor.clone(),\n                    results: NUM_RESULTS_PER_REQUEST,\n                    direction: PageDirection::Forward,\n                };\n                let response = self.uncached_client().balances(address, pagination).await?;\n\n                if response.results.is_empty() {\n                    break;\n                }\n\n                register_balances(response.results);\n                cursor = response.cursor;\n            }\n        } else {\n            let pagination = PaginationRequest {\n                cursor: None,\n                results: 9999,\n                direction: PageDirection::Forward,\n            };\n            let response = self.uncached_client().balances(address, pagination).await?;\n\n            register_balances(response.results)\n        }\n\n        Ok(balances)\n    }\n\n    /// Get all balances of all assets for the contract with id `contract_id`.\n    pub async fn get_contract_balances(\n        &self,\n        contract_id: &ContractId,\n    ) -> Result<HashMap<AssetId, u64>> {\n        let mut contract_balances = HashMap::new();\n        let mut cursor = None;\n\n        loop {\n            let response = self\n                .uncached_client()\n                .contract_balances(\n                    contract_id,\n                    PaginationRequest {\n                        cursor: cursor.clone(),\n                        results: NUM_RESULTS_PER_REQUEST,\n                        direction: PageDirection::Forward,\n                    },\n                )\n                .await?;\n\n            if response.results.is_empty() {\n                break;\n            }\n\n            contract_balances.extend(response.results.into_iter().map(\n                |ContractBalance {\n                     contract: _,\n                     amount,\n                     asset_id,\n                 }| (asset_id, amount),\n            ));\n            cursor = response.cursor;\n        }\n\n        Ok(contract_balances)\n    }\n\n    pub async fn get_transaction_by_id(&self, tx_id: &TxId) -> Result<Option<TransactionResponse>> {\n        Ok(self\n            .uncached_client()\n            .transaction(tx_id)\n            .await?\n            .map(Into::into))\n    }\n\n    pub async fn get_transactions(\n        &self,\n        request: PaginationRequest<String>,\n    ) -> Result<PaginatedResult<TransactionResponse, String>> {\n        let pr = self.uncached_client().transactions(request).await?;\n\n        Ok(PaginatedResult {\n            cursor: pr.cursor,\n            results: pr.results.into_iter().map(Into::into).collect(),\n            has_next_page: pr.has_next_page,\n            has_previous_page: pr.has_previous_page,\n        })\n    }\n\n    // Get transaction(s) by owner\n    pub async fn get_transactions_by_owner(\n        &self,\n        owner: &Address,\n        request: PaginationRequest<String>,\n    ) -> Result<PaginatedResult<TransactionResponse, String>> {\n        let pr = self\n            .uncached_client()\n            .transactions_by_owner(owner, request)\n            .await?;\n\n        Ok(PaginatedResult {\n            cursor: pr.cursor,\n            results: pr.results.into_iter().map(Into::into).collect(),\n            has_next_page: pr.has_next_page,\n            has_previous_page: pr.has_previous_page,\n        })\n    }\n\n    pub async fn latest_block_height(&self) -> Result<u32> {\n        Ok(self.chain_info().await?.latest_block.header.height)\n    }\n\n    pub async fn latest_block_time(&self) -> Result<Option<DateTime<Utc>>> {\n        Ok(self.chain_info().await?.latest_block.header.time)\n    }\n\n    pub async fn produce_blocks(\n        &self,\n        blocks_to_produce: u32,\n        start_time: Option<DateTime<Utc>>,\n    ) -> Result<u32> {\n        let start_time = start_time.map(|time| Tai64::from_unix(time.timestamp()).0);\n\n        Ok(self\n            .uncached_client()\n            .produce_blocks(blocks_to_produce, start_time)\n            .await?\n            .into())\n    }\n\n    pub async fn block(&self, block_id: &Bytes32) -> Result<Option<Block>> {\n        Ok(self\n            .uncached_client()\n            .block(block_id)\n            .await?\n            .map(Into::into))\n    }\n\n    pub async fn block_by_height(&self, height: BlockHeight) -> Result<Option<Block>> {\n        Ok(self\n            .uncached_client()\n            .block_by_height(height)\n            .await?\n            .map(Into::into))\n    }\n\n    // - Get block(s)\n    pub async fn get_blocks(\n        &self,\n        request: PaginationRequest<String>,\n    ) -> Result<PaginatedResult<Block, String>> {\n        let pr = self.uncached_client().blocks(request).await?;\n\n        Ok(PaginatedResult {\n            cursor: pr.cursor,\n            results: pr.results.into_iter().map(Into::into).collect(),\n            has_next_page: pr.has_next_page,\n            has_previous_page: pr.has_previous_page,\n        })\n    }\n\n    pub async fn estimate_transaction_cost<T: Transaction>(\n        &self,\n        tx: T,\n        tolerance: Option<f64>,\n        block_horizon: Option<u32>,\n    ) -> Result<TransactionCost> {\n        let block_horizon = block_horizon.unwrap_or(DEFAULT_GAS_ESTIMATION_BLOCK_HORIZON);\n        let tolerance = tolerance.unwrap_or(DEFAULT_GAS_ESTIMATION_TOLERANCE);\n\n        let EstimateGasPrice { gas_price, .. } = self.estimate_gas_price(block_horizon).await?;\n        let tx_status = self.dry_run_opt(tx.clone(), false, None, None).await?;\n\n        let total_gas = Self::apply_tolerance(tx_status.total_gas(), tolerance);\n        let total_fee = Self::apply_tolerance(tx_status.total_fee(), tolerance);\n\n        let receipts = tx_status.take_receipts();\n\n        Ok(TransactionCost {\n            gas_price,\n            metered_bytes_size: tx.metered_bytes_size() as u64,\n            total_fee,\n            total_gas,\n            script_gas: Self::get_script_gas_used(&receipts),\n        })\n    }\n\n    fn apply_tolerance(value: u64, tolerance: f64) -> u64 {\n        (value as f64 * (1.0 + tolerance)).ceil() as u64\n    }\n\n    fn get_script_gas_used(receipts: &[Receipt]) -> u64 {\n        receipts\n            .iter()\n            .rfind(|r| matches!(r, Receipt::ScriptResult { .. }))\n            .map(|script_result| {\n                script_result\n                    .gas_used()\n                    .expect(\"could not retrieve gas used from ScriptResult\")\n            })\n            .unwrap_or(0)\n    }\n\n    pub async fn get_messages(&self, from: &Address) -> Result<Vec<Message>> {\n        let mut messages = Vec::new();\n        let mut cursor = None;\n\n        loop {\n            let response = self\n                .uncached_client()\n                .messages(\n                    Some(from),\n                    PaginationRequest {\n                        cursor: cursor.clone(),\n                        results: NUM_RESULTS_PER_REQUEST,\n                        direction: PageDirection::Forward,\n                    },\n                )\n                .await?;\n\n            if response.results.is_empty() {\n                break;\n            }\n\n            messages.extend(response.results.into_iter().map(Into::into));\n            cursor = response.cursor;\n        }\n\n        Ok(messages)\n    }\n\n    pub async fn get_message_proof(\n        &self,\n        tx_id: &TxId,\n        nonce: &Nonce,\n        commit_block_id: Option<&Bytes32>,\n        commit_block_height: Option<u32>,\n    ) -> Result<MessageProof> {\n        self.uncached_client()\n            .message_proof(\n                tx_id,\n                nonce,\n                commit_block_id,\n                commit_block_height.map(Into::into),\n            )\n            .await\n            .map(Into::into)\n            .map_err(Into::into)\n    }\n\n    pub async fn is_user_account(&self, address: impl Into<Bytes32>) -> Result<bool> {\n        self.uncached_client()\n            .is_user_account(*address.into())\n            .await\n    }\n\n    pub fn with_retry_config(mut self, retry_config: RetryConfig) -> Self {\n        self.uncached_client_mut().set_retry_config(retry_config);\n\n        self\n    }\n\n    pub async fn contract_exists(&self, contract_id: &ContractId) -> Result<bool> {\n        Ok(self.uncached_client().contract_exists(contract_id).await?)\n    }\n\n    fn uncached_client(&self) -> &RetryableClient {\n        self.cached_client.inner()\n    }\n\n    fn uncached_client_mut(&mut self) -> &mut RetryableClient {\n        self.cached_client.inner_mut()\n    }\n}\n\n#[cfg_attr(not(target_arch = \"wasm32\"), async_trait::async_trait)]\nimpl DryRunner for Provider {\n    async fn dry_run(&self, tx: FuelTransaction) -> Result<DryRun> {\n        let [tx_execution_status] = self\n            .uncached_client()\n            .dry_run_opt(&[tx], Some(false), Some(0), None)\n            .await?\n            .try_into()\n            .expect(\"should have only one element\");\n\n        let receipts = tx_execution_status.result.receipts();\n        let script_gas = Self::get_script_gas_used(receipts);\n\n        let variable_outputs = receipts\n            .iter()\n            .filter(\n                |receipt| matches!(receipt, Receipt::TransferOut { amount, .. } if *amount != 0),\n            )\n            .count();\n\n        let succeeded = matches!(\n            tx_execution_status.result,\n            TransactionExecutionResult::Success { .. }\n        );\n\n        let dry_run = DryRun {\n            succeeded,\n            script_gas,\n            variable_outputs,\n        };\n\n        Ok(dry_run)\n    }\n\n    async fn estimate_gas_price(&self, block_horizon: u32) -> Result<u64> {\n        Ok(self.estimate_gas_price(block_horizon).await?.gas_price)\n    }\n\n    async fn consensus_parameters(&self) -> Result<ConsensusParameters> {\n        Provider::consensus_parameters(self).await\n    }\n\n    async fn estimate_predicates(\n        &self,\n        tx: &FuelTransaction,\n        _latest_chain_executor_version: Option<u32>,\n    ) -> Result<FuelTransaction> {\n        Ok(self.uncached_client().estimate_predicates(tx).await?)\n    }\n}\n"
  },
  {
    "path": "packages/fuels-accounts/src/schema/schema.sdl",
    "content": "input Account @oneOf {\n\taddress: Address\n\tpredicate: Predicate\n}\n\nscalar Address\n\ntype AssembleTransactionResult {\n\ttransaction: Transaction!\n\tstatus: DryRunTransactionStatus!\n\tgasPrice: U64!\n}\n\nscalar AssetId\n\ntype AssetInfoDetails {\n\tcontractId: ContractId!\n\tsubId: SubId!\n\ttotalSupply: U128!\n}\n\ntype Balance {\n\towner: Address!\n\tamount: U64!\n\tamountU128: U128!\n\tassetId: AssetId!\n}\n\ntype BalanceConnection {\n\t\"\"\"\n\tInformation to aid in pagination.\n\t\"\"\"\n\tpageInfo: PageInfo!\n\t\"\"\"\n\tA list of edges.\n\t\"\"\"\n\tedges: [BalanceEdge!]!\n\t\"\"\"\n\tA list of nodes.\n\t\"\"\"\n\tnodes: [Balance!]!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype BalanceEdge {\n\t\"\"\"\n\tThe item at the end of the edge\n\t\"\"\"\n\tnode: Balance!\n\t\"\"\"\n\tA cursor for use in pagination\n\t\"\"\"\n\tcursor: String!\n}\n\ninput BalanceFilterInput {\n\t\"\"\"\n\tFilter coins based on the `owner` field\n\t\"\"\"\n\towner: Address!\n}\n\ntype Blob {\n\tid: BlobId!\n\tbytecode: HexString!\n}\n\nscalar BlobId\n\ntype Block {\n\tversion: BlockVersion!\n\tid: BlockId!\n\theight: U32!\n\theader: Header!\n\tconsensus: Consensus!\n\ttransactionIds: [TransactionId!]!\n\ttransactions: [Transaction!]!\n}\n\ntype BlockConnection {\n\t\"\"\"\n\tInformation to aid in pagination.\n\t\"\"\"\n\tpageInfo: PageInfo!\n\t\"\"\"\n\tA list of edges.\n\t\"\"\"\n\tedges: [BlockEdge!]!\n\t\"\"\"\n\tA list of nodes.\n\t\"\"\"\n\tnodes: [Block!]!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype BlockEdge {\n\t\"\"\"\n\tThe item at the end of the edge\n\t\"\"\"\n\tnode: Block!\n\t\"\"\"\n\tA cursor for use in pagination\n\t\"\"\"\n\tcursor: String!\n}\n\nscalar BlockId\n\nenum BlockVersion {\n\tV1\n}\n\n\n\"\"\"\nBreakpoint, defined as a tuple of contract ID and relative PC offset inside it\n\"\"\"\ninput Breakpoint {\n\tcontract: ContractId!\n\tpc: U64!\n}\n\nscalar Bytes32\n\ntype ChainInfo {\n\tname: String!\n\tlatestBlock: Block!\n\tdaHeight: U64!\n\tconsensusParameters: ConsensusParameters!\n\tgasCosts: GasCosts!\n}\n\ntype ChangeOutput {\n\tto: Address!\n\tamount: U64!\n\tassetId: AssetId!\n}\n\ninput ChangePolicy @oneOf {\n\t\"\"\"\n\tAdds `Output::Change` to the transaction if it is not already present.\n\tSending remaining assets to the provided address.\n\t\"\"\"\n\tchange: Address\n\t\"\"\"\n\tDestroys the remaining assets by the transaction for provided address.\n\t\"\"\"\n\tdestroy: Destroy\n}\n\ntype Coin {\n\tutxoId: UtxoId!\n\towner: Address!\n\tamount: U64!\n\tassetId: AssetId!\n\t\"\"\"\n\tTxPointer - the height of the block this coin was created in\n\t\"\"\"\n\tblockCreated: U32!\n\t\"\"\"\n\tTxPointer - the index of the transaction that created this coin\n\t\"\"\"\n\ttxCreatedIdx: U16!\n}\n\ntype CoinConnection {\n\t\"\"\"\n\tInformation to aid in pagination.\n\t\"\"\"\n\tpageInfo: PageInfo!\n\t\"\"\"\n\tA list of edges.\n\t\"\"\"\n\tedges: [CoinEdge!]!\n\t\"\"\"\n\tA list of nodes.\n\t\"\"\"\n\tnodes: [Coin!]!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype CoinEdge {\n\t\"\"\"\n\tThe item at the end of the edge\n\t\"\"\"\n\tnode: Coin!\n\t\"\"\"\n\tA cursor for use in pagination\n\t\"\"\"\n\tcursor: String!\n}\n\ninput CoinFilterInput {\n\t\"\"\"\n\tReturns coins owned by the `owner`.\n\t\"\"\"\n\towner: Address!\n\t\"\"\"\n\tReturns coins only with `asset_id`.\n\t\"\"\"\n\tassetId: AssetId\n}\n\ntype CoinOutput {\n\tto: Address!\n\tamount: U64!\n\tassetId: AssetId!\n}\n\n\"\"\"\nThe schema analog of the [`coins::CoinType`].\n\"\"\"\nunion CoinType = Coin | MessageCoin\n\nunion Consensus = Genesis | PoAConsensus\n\ntype ConsensusParameters {\n\tversion: ConsensusParametersVersion!\n\ttxParams: TxParameters!\n\tpredicateParams: PredicateParameters!\n\tscriptParams: ScriptParameters!\n\tcontractParams: ContractParameters!\n\tfeeParams: FeeParameters!\n\tbaseAssetId: AssetId!\n\tblockGasLimit: U64!\n\tblockTransactionSizeLimit: U64!\n\tchainId: U64!\n\tgasCosts: GasCosts!\n\tprivilegedAddress: Address!\n}\n\ntype ConsensusParametersPurpose {\n\twitnessIndex: U16!\n\tchecksum: Bytes32!\n}\n\nenum ConsensusParametersVersion {\n\tV1\n}\n\ntype Contract {\n\tid: ContractId!\n\tbytecode: HexString!\n\tsalt: Salt!\n}\n\ntype ContractBalance {\n\tcontract: ContractId!\n\tamount: U64!\n\tassetId: AssetId!\n}\n\ntype ContractBalanceConnection {\n\t\"\"\"\n\tInformation to aid in pagination.\n\t\"\"\"\n\tpageInfo: PageInfo!\n\t\"\"\"\n\tA list of edges.\n\t\"\"\"\n\tedges: [ContractBalanceEdge!]!\n\t\"\"\"\n\tA list of nodes.\n\t\"\"\"\n\tnodes: [ContractBalance!]!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype ContractBalanceEdge {\n\t\"\"\"\n\tThe item at the end of the edge\n\t\"\"\"\n\tnode: ContractBalance!\n\t\"\"\"\n\tA cursor for use in pagination\n\t\"\"\"\n\tcursor: String!\n}\n\ninput ContractBalanceFilterInput {\n\t\"\"\"\n\tFilter assets based on the `contractId` field\n\t\"\"\"\n\tcontract: ContractId!\n}\n\ntype ContractCreated {\n\tcontract: ContractId!\n\tstateRoot: Bytes32!\n}\n\nscalar ContractId\n\ntype ContractOutput {\n\tinputIndex: U16!\n\tbalanceRoot: Bytes32!\n\tstateRoot: Bytes32!\n}\n\ntype ContractParameters {\n\tversion: ContractParametersVersion!\n\tcontractMaxSize: U64!\n\tmaxStorageSlots: U64!\n}\n\nenum ContractParametersVersion {\n\tV1\n}\n\ntype DaCompressedBlock {\n\tbytes: HexString!\n}\n\nunion DependentCost = LightOperation | HeavyOperation\n\nenum Destroy {\n\tDESTROY\n}\n\ntype DryRunFailureStatus {\n\tprogramState: ProgramState\n\treason: String!\n\treceipts: [Receipt!]!\n\ttotalGas: U64!\n\ttotalFee: U64!\n}\n\ntype DryRunStorageReads {\n\ttxStatuses: [DryRunTransactionExecutionStatus!]!\n\tstorageReads: [StorageReadReplayEvent!]!\n}\n\ntype DryRunSuccessStatus {\n\tprogramState: ProgramState\n\treceipts: [Receipt!]!\n\ttotalGas: U64!\n\ttotalFee: U64!\n}\n\ntype DryRunTransactionExecutionStatus {\n\tid: TransactionId!\n\tstatus: DryRunTransactionStatus!\n\treceipts: [Receipt!]!\n}\n\nunion DryRunTransactionStatus = DryRunSuccessStatus | DryRunFailureStatus\n\ntype EstimateGasPrice {\n\tgasPrice: U64!\n}\n\ninput ExcludeInput {\n\t\"\"\"\n\tUtxos to exclude from the selection.\n\t\"\"\"\n\tutxos: [UtxoId!]!\n\t\"\"\"\n\tMessages to exclude from the selection.\n\t\"\"\"\n\tmessages: [Nonce!]!\n}\n\ntype FailureStatus {\n\ttransactionId: TransactionId!\n\tblockHeight: U32!\n\tblock: Block!\n\ttransaction: Transaction!\n\ttime: Tai64Timestamp!\n\treason: String!\n\tprogramState: ProgramState\n\treceipts: [Receipt!]!\n\ttotalGas: U64!\n\ttotalFee: U64!\n}\n\ntype FeeParameters {\n\tversion: FeeParametersVersion!\n\tgasPriceFactor: U64!\n\tgasPerByte: U64!\n}\n\nenum FeeParametersVersion {\n\tV1\n}\n\n\ntype GasCosts {\n\tversion: GasCostsVersion!\n\tadd: U64!\n\taddi: U64!\n\taloc: U64!\n\tand: U64!\n\tandi: U64!\n\tbal: U64!\n\tbhei: U64!\n\tbhsh: U64!\n\tburn: U64!\n\tcb: U64!\n\tcfei: U64!\n\tcfsi: U64!\n\tdiv: U64!\n\tdivi: U64!\n\tecr1: U64!\n\teck1: U64!\n\ted19: U64!\n\teq: U64!\n\texp: U64!\n\texpi: U64!\n\tflag: U64!\n\tgm: U64!\n\tgt: U64!\n\tgtf: U64!\n\tji: U64!\n\tjmp: U64!\n\tjne: U64!\n\tjnei: U64!\n\tjnzi: U64!\n\tjmpf: U64!\n\tjmpb: U64!\n\tjnzf: U64!\n\tjnzb: U64!\n\tjnef: U64!\n\tjneb: U64!\n\tlb: U64!\n\tlog: U64!\n\tlt: U64!\n\tlw: U64!\n\tmint: U64!\n\tmlog: U64!\n\tmodOp: U64!\n\tmodi: U64!\n\tmoveOp: U64!\n\tmovi: U64!\n\tmroo: U64!\n\tmul: U64!\n\tmuli: U64!\n\tmldv: U64!\n\tniop: U64\n\tnoop: U64!\n\tnot: U64!\n\tor: U64!\n\tori: U64!\n\tpoph: U64!\n\tpopl: U64!\n\tpshh: U64!\n\tpshl: U64!\n\tret: U64!\n\trvrt: U64!\n\tsb: U64!\n\tsll: U64!\n\tslli: U64!\n\tsrl: U64!\n\tsrli: U64!\n\tsrw: U64!\n\tsub: U64!\n\tsubi: U64!\n\tsw: U64!\n\tsww: U64!\n\ttime: U64!\n\ttr: U64!\n\ttro: U64!\n\twdcm: U64!\n\twqcm: U64!\n\twdop: U64!\n\twqop: U64!\n\twdml: U64!\n\twqml: U64!\n\twddv: U64!\n\twqdv: U64!\n\twdmd: U64!\n\twqmd: U64!\n\twdam: U64!\n\twqam: U64!\n\twdmm: U64!\n\twqmm: U64!\n\txor: U64!\n\txori: U64!\n\tecop: U64\n\talocDependentCost: DependentCost!\n\tbldd: DependentCost\n\tbsiz: DependentCost\n\tcfe: DependentCost!\n\tcfeiDependentCost: DependentCost!\n\tcall: DependentCost!\n\tccp: DependentCost!\n\tcroo: DependentCost!\n\tcsiz: DependentCost!\n\ted19DependentCost: DependentCost!\n\tk256: DependentCost!\n\tldc: DependentCost!\n\tlogd: DependentCost!\n\tmcl: DependentCost!\n\tmcli: DependentCost!\n\tmcp: DependentCost!\n\tmcpi: DependentCost!\n\tmeq: DependentCost!\n\tretd: DependentCost!\n\ts256: DependentCost!\n\tscwq: DependentCost!\n\tsmo: DependentCost!\n\tsrwq: DependentCost!\n\tswwq: DependentCost!\n\tepar: DependentCost\n\tcontractRoot: DependentCost!\n\tstateRoot: DependentCost!\n\tvmInitialization: DependentCost!\n\tnewStoragePerByte: U64!\n}\n\nenum GasCostsVersion {\n\tV1\n}\n\ntype Genesis {\n\t\"\"\"\n\tThe chain configs define what consensus type to use, what settlement layer to use,\n\trules of block validity, etc.\n\t\"\"\"\n\tchainConfigHash: Bytes32!\n\t\"\"\"\n\tThe Binary Merkle Tree root of all genesis coins.\n\t\"\"\"\n\tcoinsRoot: Bytes32!\n\t\"\"\"\n\tThe Binary Merkle Tree root of state, balances, contracts code hash of each contract.\n\t\"\"\"\n\tcontractsRoot: Bytes32!\n\t\"\"\"\n\tThe Binary Merkle Tree root of all genesis messages.\n\t\"\"\"\n\tmessagesRoot: Bytes32!\n\t\"\"\"\n\tThe Binary Merkle Tree root of all processed transaction ids.\n\t\"\"\"\n\ttransactionsRoot: Bytes32!\n}\n\ntype Header {\n\t\"\"\"\n\tVersion of the header\n\t\"\"\"\n\tversion: HeaderVersion!\n\t\"\"\"\n\tHash of the header\n\t\"\"\"\n\tid: BlockId!\n\t\"\"\"\n\tThe layer 1 height of messages and events to include since the last layer 1 block number.\n\t\"\"\"\n\tdaHeight: U64!\n\t\"\"\"\n\tThe version of the consensus parameters used to create this block.\n\t\"\"\"\n\tconsensusParametersVersion: U32!\n\t\"\"\"\n\tThe version of the state transition bytecode used to create this block.\n\t\"\"\"\n\tstateTransitionBytecodeVersion: U32!\n\t\"\"\"\n\tNumber of transactions in this block.\n\t\"\"\"\n\ttransactionsCount: U16!\n\t\"\"\"\n\tNumber of message receipts in this block.\n\t\"\"\"\n\tmessageReceiptCount: U32!\n\t\"\"\"\n\tMerkle root of transactions.\n\t\"\"\"\n\ttransactionsRoot: Bytes32!\n\t\"\"\"\n\tMerkle root of message receipts in this block.\n\t\"\"\"\n\tmessageOutboxRoot: Bytes32!\n\t\"\"\"\n\tMerkle root of inbox events in this block.\n\t\"\"\"\n\teventInboxRoot: Bytes32!\n\t\"\"\"\n\tFuel block height.\n\t\"\"\"\n\theight: U32!\n\t\"\"\"\n\tMerkle root of all previous block header hashes.\n\t\"\"\"\n\tprevRoot: Bytes32!\n\t\"\"\"\n\tThe block producer time.\n\t\"\"\"\n\ttime: Tai64Timestamp!\n\t\"\"\"\n\tHash of the application header.\n\t\"\"\"\n\tapplicationHash: Bytes32!\n\t\"\"\"\n\tTransaction ID Commitment\n\t\"\"\"\n\ttxIdCommitment: Bytes32\n}\n\nenum HeaderVersion {\n\tV1\n\tV2\n}\n\ntype HeavyOperation {\n\tbase: U64!\n\tgasPerUnit: U64!\n}\n\nscalar HexString\n\n\ntype IndexationFlags {\n\t\"\"\"\n\tIs balances indexation enabled\n\t\"\"\"\n\tbalances: Boolean!\n\t\"\"\"\n\tIs coins to spend indexation enabled\n\t\"\"\"\n\tcoinsToSpend: Boolean!\n\t\"\"\"\n\tIs asset metadata indexation enabled\n\t\"\"\"\n\tassetMetadata: Boolean!\n}\n\nunion Input = InputCoin | InputContract | InputMessage\n\ntype InputCoin {\n\tutxoId: UtxoId!\n\towner: Address!\n\tamount: U64!\n\tassetId: AssetId!\n\ttxPointer: TxPointer!\n\twitnessIndex: U16!\n\tpredicateGasUsed: U64!\n\tpredicate: HexString!\n\tpredicateData: HexString!\n}\n\ntype InputContract {\n\tutxoId: UtxoId!\n\tbalanceRoot: Bytes32!\n\tstateRoot: Bytes32!\n\ttxPointer: TxPointer!\n\tcontractId: ContractId!\n}\n\ntype InputMessage {\n\tsender: Address!\n\trecipient: Address!\n\tamount: U64!\n\tnonce: Nonce!\n\twitnessIndex: U16!\n\tpredicateGasUsed: U64!\n\tdata: HexString!\n\tpredicate: HexString!\n\tpredicateData: HexString!\n}\n\n\ntype LatestGasPrice {\n\tgasPrice: U64!\n\tblockHeight: U32!\n}\n\ntype LightOperation {\n\tbase: U64!\n\tunitsPerGas: U64!\n}\n\ntype MerkleProof {\n\tproofSet: [Bytes32!]!\n\tproofIndex: U64!\n}\n\ntype Message {\n\tamount: U64!\n\tsender: Address!\n\trecipient: Address!\n\tnonce: Nonce!\n\tdata: HexString!\n\tdaHeight: U64!\n}\n\ntype MessageCoin {\n\tsender: Address!\n\trecipient: Address!\n\tnonce: Nonce!\n\tamount: U64!\n\tassetId: AssetId!\n\tdaHeight: U64!\n}\n\ntype MessageConnection {\n\t\"\"\"\n\tInformation to aid in pagination.\n\t\"\"\"\n\tpageInfo: PageInfo!\n\t\"\"\"\n\tA list of edges.\n\t\"\"\"\n\tedges: [MessageEdge!]!\n\t\"\"\"\n\tA list of nodes.\n\t\"\"\"\n\tnodes: [Message!]!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype MessageEdge {\n\t\"\"\"\n\tThe item at the end of the edge\n\t\"\"\"\n\tnode: Message!\n\t\"\"\"\n\tA cursor for use in pagination\n\t\"\"\"\n\tcursor: String!\n}\n\ntype MessageProof {\n\tmessageProof: MerkleProof!\n\tblockProof: MerkleProof!\n\tmessageBlockHeader: Header!\n\tcommitBlockHeader: Header!\n\tsender: Address!\n\trecipient: Address!\n\tnonce: Nonce!\n\tamount: U64!\n\tdata: HexString!\n}\n\nenum MessageState {\n\tUNSPENT\n\tSPENT\n\tNOT_FOUND\n}\n\ntype MessageStatus {\n\tstate: MessageState!\n}\n\ntype Mutation {\n\t\"\"\"\n\tInitialize a new debugger session, returning its ID.\n\tA new VM instance is spawned for each session.\n\tThe session is run in a separate database transaction,\n\ton top of the most recent node state.\n\t\"\"\"\n\tstartSession: ID!\n\t\"\"\"\n\tEnd debugger session.\n\t\"\"\"\n\tendSession(id: ID!): Boolean!\n\t\"\"\"\n\tReset the VM instance to the initial state.\n\t\"\"\"\n\treset(id: ID!): Boolean!\n\t\"\"\"\n\tExecute a single fuel-asm instruction.\n\t\"\"\"\n\texecute(id: ID!, op: String!): Boolean!\n\t\"\"\"\n\tSet single-stepping mode for the VM instance.\n\t\"\"\"\n\tsetSingleStepping(id: ID!, enable: Boolean!): Boolean!\n\t\"\"\"\n\tSet a breakpoint for a VM instance.\n\t\"\"\"\n\tsetBreakpoint(id: ID!, breakpoint: Breakpoint!): Boolean!\n\t\"\"\"\n\tRun a single transaction in given session until it\n\thits a breakpoint or completes.\n\t\"\"\"\n\tstartTx(id: ID!, txJson: String!): RunResult!\n\t\"\"\"\n\tResume execution of the VM instance after a breakpoint.\n\tRuns until the next breakpoint or until the transaction completes.\n\t\"\"\"\n\tcontinueTx(id: ID!): RunResult!\n\t\"\"\"\n\tExecute a dry-run of multiple transactions using a fork of current state, no changes are committed.\n\t\"\"\"\n\tdryRun(txs: [HexString!]!, utxoValidation: Boolean, gasPrice: U64, blockHeight: U32): [DryRunTransactionExecutionStatus!]! @deprecated(reason: \"This doesn't need to be a mutation. Use query of the same name instead.\")\n\t\"\"\"\n\tSubmits transaction to the `TxPool`.\n\t\n\tReturns submitted transaction if the transaction is included in the `TxPool` without problems.\n\t\"\"\"\n\tsubmit(tx: HexString!, estimatePredicates: Boolean): Transaction!\n\t\"\"\"\n\tSequentially produces `blocks_to_produce` blocks. The first block starts with\n\t`start_timestamp`. If the block production in the [`crate::service::Config`] is\n\t`Trigger::Interval { block_time }`, produces blocks with `block_time ` intervals between\n\tthem. The `start_timestamp` is the timestamp in seconds.\n\t\"\"\"\n\tproduceBlocks(startTimestamp: Tai64Timestamp, blocksToProduce: U32!): U32!\n}\n\ntype NodeInfo {\n\tutxoValidation: Boolean!\n\tvmBacktrace: Boolean!\n\tmaxTx: U64!\n\tmaxGas: U64!\n\tmaxSize: U64!\n\tmaxDepth: U64!\n\tnodeVersion: String!\n\tindexation: IndexationFlags!\n\ttxPoolStats: TxPoolStats!\n\tpeers: [PeerInfo!]!\n}\n\nscalar Nonce\n\nunion Output = CoinOutput | ContractOutput | ChangeOutput | VariableOutput | ContractCreated\n\n\"\"\"\nA separate `Breakpoint` type to be used as an output, as a single\ntype cannot act as both input and output type in async-graphql\n\"\"\"\ntype OutputBreakpoint {\n\tcontract: ContractId!\n\tpc: U64!\n}\n\n\"\"\"\nInformation about pagination in a connection\n\"\"\"\ntype PageInfo {\n\t\"\"\"\n\tWhen paginating backwards, are there more items?\n\t\"\"\"\n\thasPreviousPage: Boolean!\n\t\"\"\"\n\tWhen paginating forwards, are there more items?\n\t\"\"\"\n\thasNextPage: Boolean!\n\t\"\"\"\n\tWhen paginating backwards, the cursor to continue.\n\t\"\"\"\n\tstartCursor: String\n\t\"\"\"\n\tWhen paginating forwards, the cursor to continue.\n\t\"\"\"\n\tendCursor: String\n}\n\ntype PeerInfo {\n\t\"\"\"\n\tThe libp2p peer id\n\t\"\"\"\n\tid: String!\n\t\"\"\"\n\tThe advertised multi-addrs that can be used to connect to this peer\n\t\"\"\"\n\taddresses: [String!]!\n\t\"\"\"\n\tThe self-reported version of the client the peer is using\n\t\"\"\"\n\tclientVersion: String\n\t\"\"\"\n\tThe last reported height of the peer\n\t\"\"\"\n\tblockHeight: U32\n\t\"\"\"\n\tThe last heartbeat from this peer in unix epoch time ms\n\t\"\"\"\n\tlastHeartbeatMs: U64!\n\t\"\"\"\n\tThe internal fuel p2p reputation of this peer\n\t\"\"\"\n\tappScore: Float!\n}\n\ntype PoAConsensus {\n\t\"\"\"\n\tGets the signature of the block produced by `PoA` consensus.\n\t\"\"\"\n\tsignature: Signature!\n}\n\ntype Policies {\n\ttip: U64\n\twitnessLimit: U64\n\tmaturity: U32\n\tmaxFee: U64\n}\n\ntype PreconfirmationFailureStatus {\n\treason: String!\n\ttxPointer: TxPointer!\n\ttotalGas: U64!\n\ttotalFee: U64!\n\ttransactionId: TransactionId!\n\ttransaction: Transaction\n\treceipts: [Receipt!]\n\tresolvedOutputs: [ResolvedOutput!]\n}\n\ntype PreconfirmationSuccessStatus {\n\ttxPointer: TxPointer!\n\ttotalGas: U64!\n\ttotalFee: U64!\n\ttransactionId: TransactionId!\n\ttransaction: Transaction\n\treceipts: [Receipt!]\n\tresolvedOutputs: [ResolvedOutput!]\n}\n\ninput Predicate {\n\tpredicateAddress: Address!\n\tpredicate: HexString!\n\tpredicateData: HexString!\n}\n\ntype PredicateParameters {\n\tversion: PredicateParametersVersion!\n\tmaxPredicateLength: U64!\n\tmaxPredicateDataLength: U64!\n\tmaxGasPerPredicate: U64!\n\tmaxMessageDataLength: U64!\n}\n\nenum PredicateParametersVersion {\n\tV1\n}\n\ntype ProgramState {\n\treturnType: ReturnType!\n\tdata: HexString!\n}\n\ntype Query {\n\tassetDetails(\n\t\t\"\"\"\n\t\tID of the Asset\n\t\t\"\"\"\n\t\tid: AssetId!\n\t): AssetInfoDetails\n\t\"\"\"\n\tRead register value by index.\n\t\"\"\"\n\tregister(id: ID!, register: U32!): U64!\n\t\"\"\"\n\tRead read a range of memory bytes.\n\t\"\"\"\n\tmemory(id: ID!, start: U32!, size: U32!): String!\n\tbalance(\n\t\t\"\"\"\n\t\taddress of the owner\n\t\t\"\"\"\n\t\towner: Address!,\n\t\t\"\"\"\n\t\tasset_id of the coin\n\t\t\"\"\"\n\t\tassetId: AssetId!\n\t): Balance!\n\tbalances(filter: BalanceFilterInput!, first: Int, after: String, last: Int, before: String): BalanceConnection!\n\tblob(\n\t\t\"\"\"\n\t\tID of the Blob\n\t\t\"\"\"\n\t\tid: BlobId!\n\t): Blob\n\tblock(\n\t\t\"\"\"\n\t\tID of the block\n\t\t\"\"\"\n\t\tid: BlockId,\n\t\t\"\"\"\n\t\tHeight of the block\n\t\t\"\"\"\n\t\theight: U32\n\t): Block\n\tblocks(first: Int, after: String, last: Int, before: String): BlockConnection!\n\tchain: ChainInfo!\n\ttransaction(\n\t\t\"\"\"\n\t\tThe ID of the transaction\n\t\t\"\"\"\n\t\tid: TransactionId!\n\t): Transaction\n\ttransactions(first: Int, after: String, last: Int, before: String): TransactionConnection!\n\ttransactionsByOwner(owner: Address!, first: Int, after: String, last: Int, before: String): TransactionConnection!\n\t\"\"\"\n\tAssembles the transaction based on the provided requirements.\n\tThe return transaction contains:\n\t- Input coins to cover `required_balances`\n\t- Input coins to cover the fee of the transaction based on the gas price from `block_horizon`\n\t- `Change` or `Destroy` outputs for all assets from the inputs\n\t- `Variable` outputs in the case they are required during the execution\n\t- `Contract` inputs and outputs in the case they are required during the execution\n\t- Reserved witness slots for signed coins filled with `64` zeroes\n\t- Set script gas limit(unless `script` is empty)\n\t- Estimated predicates, if `estimate_predicates == true`\n\t\n\tReturns an error if:\n\t- The number of required balances exceeds the maximum number of inputs allowed.\n\t- The fee address index is out of bounds.\n\t- The same asset has multiple change policies(either the receiver of\n\tthe change is different, or one of the policies states about the destruction\n\tof the token while the other does not). The `Change` output from the transaction\n\talso count as a `ChangePolicy`.\n\t- The number of excluded coin IDs exceeds the maximum number of inputs allowed.\n\t- Required assets have multiple entries.\n\t- If accounts don't have sufficient amounts to cover the transaction requirements in assets.\n\t- If a constructed transaction breaks the rules defined by consensus parameters.\n\t\"\"\"\n\tassembleTx(\n\t\t\"\"\"\n\t\tThe original transaction that contains application level logic only\n\t\t\"\"\"\n\t\ttx: HexString!,\n\t\t\"\"\"\n\t\tNumber of blocks into the future to estimate the gas price for\n\t\t\"\"\"\n\t\tblockHorizon: U32!,\n\t\t\"\"\"\n\t\tThe list of required balances for the transaction to include as inputs. The list should be created based on the application-required assets. The base asset requirement should not require assets to cover the transaction fee, which will be calculated and added automatically at the end of the assembly process.\n\t\t\"\"\"\n\t\trequiredBalances: [RequiredBalance!]!,\n\t\t\"\"\"\n\t\tThe index from the `required_balances` list that points to the address who pays fee for the transaction. If you only want to cover the fee of transaction, you can set the required balance to 0, set base asset and point to this required address.\n\t\t\"\"\"\n\t\tfeeAddressIndex: U16!,\n\t\t\"\"\"\n\t\tThe list of resources to exclude from the selection for the inputs\n\t\t\"\"\"\n\t\texcludeInput: ExcludeInput,\n\t\t\"\"\"\n\t\tPerform the estimation of the predicates before cover fee of the transaction\n\t\t\"\"\"\n\t\testimatePredicates: Boolean,\n\t\t\"\"\"\n\t\tDuring the phase of the fee calculation, adds `reserve_gas` to the total gas used by the transaction and fetch assets to cover the fee.\n\t\t\"\"\"\n\t\treserveGas: U64\n\t): AssembleTransactionResult!\n\t\"\"\"\n\tEstimate the predicate gas for the provided transaction\n\t\"\"\"\n\testimatePredicates(tx: HexString!): Transaction!\n\t\"\"\"\n\tReturns all possible receipts for test purposes.\n\t\"\"\"\n\tallReceipts: [Receipt!]!\n\t\"\"\"\n\tExecute a dry-run of multiple transactions using a fork of current state, no changes are committed.\n\t\"\"\"\n\tdryRun(txs: [HexString!]!, utxoValidation: Boolean, gasPrice: U64, blockHeight: U32): [DryRunTransactionExecutionStatus!]!\n\t\"\"\"\n\tExecute a dry-run of multiple transactions using a fork of current state, no changes are committed.\n\tAlso records accesses, so the execution can be replicated locally.\n\t\"\"\"\n\tdryRunRecordStorageReads(txs: [HexString!]!, utxoValidation: Boolean, gasPrice: U64, blockHeight: U32): DryRunStorageReads!\n\t\"\"\"\n\tGet execution trace for an already-executed block.\n\t\"\"\"\n\tstorageReadReplay(height: U32!): [StorageReadReplayEvent!]!\n\t\"\"\"\n\tReturns true when the GraphQL API is serving requests.\n\t\"\"\"\n\thealth: Boolean!\n\t\"\"\"\n\tGets the coin by `utxo_id`.\n\t\"\"\"\n\tcoin(\n\t\t\"\"\"\n\t\tThe ID of the coin\n\t\t\"\"\"\n\t\tutxoId: UtxoId!\n\t): Coin\n\t\"\"\"\n\tGets all unspent coins of some `owner` maybe filtered with by `asset_id` per page.\n\t\"\"\"\n\tcoins(filter: CoinFilterInput!, first: Int, after: String, last: Int, before: String): CoinConnection!\n\t\"\"\"\n\tFor each `query_per_asset`, get some spendable coins(of asset specified by the query) owned by\n\t`owner` that add up at least the query amount. The returned coins can be spent.\n\tThe number of coins is optimized to prevent dust accumulation.\n\t\n\tThe query supports excluding and maximum the number of coins.\n\t\n\tReturns:\n\tThe list of spendable coins per asset from the query. The length of the result is\n\tthe same as the length of `query_per_asset`. The ordering of assets and `query_per_asset`\n\tis the same.\n\t\"\"\"\n\tcoinsToSpend(\n\t\t\"\"\"\n\t\tThe `Address` of the coins owner.\n\t\t\"\"\"\n\t\towner: Address!,\n\t\t\"\"\"\n\t\tThe list of requested assets` coins with asset ids, `target` amount the user wants to reach, and the `max` number of coins in the selection. Several entries with the same asset id are not allowed. The result can't contain more coins than `max_inputs`.\n\t\t\"\"\"\n\t\tqueryPerAsset: [SpendQueryElementInput!]!,\n\t\t\"\"\"\n\t\tThe excluded coins from the selection.\n\t\t\"\"\"\n\t\texcludedIds: ExcludeInput\n\t): [[CoinType!]!]!\n\tdaCompressedBlock(\n\t\t\"\"\"\n\t\tHeight of the block\n\t\t\"\"\"\n\t\theight: U32!\n\t): DaCompressedBlock\n\tcontract(\n\t\t\"\"\"\n\t\tID of the Contract\n\t\t\"\"\"\n\t\tid: ContractId!\n\t): Contract\n\tcontractBalance(contract: ContractId!, asset: AssetId!): ContractBalance!\n\tcontractBalances(filter: ContractBalanceFilterInput!, first: Int, after: String, last: Int, before: String): ContractBalanceConnection!\n\tnodeInfo: NodeInfo!\n\tlatestGasPrice: LatestGasPrice!\n\testimateGasPrice(\n\t\t\"\"\"\n\t\tNumber of blocks into the future to estimate the gas price for\n\t\t\"\"\"\n\t\tblockHorizon: U32\n\t): EstimateGasPrice!\n\tmessage(\n\t\t\"\"\"\n\t\tThe Nonce of the message\n\t\t\"\"\"\n\t\tnonce: Nonce!\n\t): Message\n\tmessages(\n\t\t\"\"\"\n\t\taddress of the owner\n\t\t\"\"\"\n\t\towner: Address,\t\tfirst: Int,\t\tafter: String,\t\tlast: Int,\t\tbefore: String\n\t): MessageConnection!\n\tmessageProof(transactionId: TransactionId!, nonce: Nonce!, commitBlockId: BlockId, commitBlockHeight: U32): MessageProof!\n\tmessageStatus(nonce: Nonce!): MessageStatus!\n\trelayedTransactionStatus(\n\t\t\"\"\"\n\t\tThe id of the relayed tx\n\t\t\"\"\"\n\t\tid: RelayedTransactionId!\n\t): RelayedTransactionStatus\n\tconsensusParameters(version: Int!): ConsensusParameters!\n\tstateTransitionBytecodeByVersion(version: Int!): StateTransitionBytecode\n\tstateTransitionBytecodeByRoot(root: HexString!): StateTransitionBytecode!\n\t\"\"\"\n\tGet storage slot values for a contract at a specific block height.\n\tUse the latest block height if not provided.\n\tRequires historical execution config to be enabled.\n\t\"\"\"\n\tcontractSlotValues(contractId: ContractId!, blockHeight: U32, storageSlots: [Bytes32!]!): [StorageSlot!]!\n\t\"\"\"\n\tGet balance values for a contract at a specific block height.\n\tUse the latest block height if not provided.\n\tRequires historical execution config to be enabled.\n\t\"\"\"\n\tcontractBalanceValues(contractId: ContractId!, blockHeight: U32, assets: [AssetId!]!): [ContractBalance!]!\n}\n\ntype Receipt {\n\tid: ContractId\n\tpc: U64\n\tis: U64\n\tto: ContractId\n\ttoAddress: Address\n\tamount: U64\n\tassetId: AssetId\n\tgas: U64\n\tparam1: U64\n\tparam2: U64\n\tval: U64\n\tptr: U64\n\tdigest: Bytes32\n\treason: U64\n\tra: U64\n\trb: U64\n\trc: U64\n\trd: U64\n\tlen: U64\n\treceiptType: ReceiptType!\n\tresult: U64\n\tgasUsed: U64\n\tdata: HexString\n\tsender: Address\n\trecipient: Address\n\tnonce: Nonce\n\t\"\"\"\n\tSet in the case of a Panic receipt to indicate a missing contract input id\n\t\"\"\"\n\tcontractId: ContractId\n\tsubId: SubId\n}\n\nenum ReceiptType {\n\tCALL\n\tRETURN\n\tRETURN_DATA\n\tPANIC\n\tREVERT\n\tLOG\n\tLOG_DATA\n\tTRANSFER\n\tTRANSFER_OUT\n\tSCRIPT_RESULT\n\tMESSAGE_OUT\n\tMINT\n\tBURN\n}\n\ntype RelayedTransactionFailed {\n\tblockHeight: U32!\n\tfailure: String!\n}\n\nscalar RelayedTransactionId\n\nunion RelayedTransactionStatus = RelayedTransactionFailed\n\ninput RequiredBalance {\n\tassetId: AssetId!\n\tamount: U64!\n\taccount: Account!\n\tchangePolicy: ChangePolicy!\n}\n\ntype ResolvedOutput {\n\tutxoId: UtxoId!\n\toutput: Output!\n}\n\nenum ReturnType {\n\tRETURN\n\tRETURN_DATA\n\tREVERT\n}\n\ntype RunResult {\n\tstate: RunState!\n\tbreakpoint: OutputBreakpoint\n\tjsonReceipts: [String!]!\n}\n\nenum RunState {\n\t\"\"\"\n\tAll breakpoints have been processed, and the program has terminated\n\t\"\"\"\n\tCOMPLETED\n\t\"\"\"\n\tStopped on a breakpoint\n\t\"\"\"\n\tBREAKPOINT\n}\n\nscalar Salt\n\ntype ScriptParameters {\n\tversion: ScriptParametersVersion!\n\tmaxScriptLength: U64!\n\tmaxScriptDataLength: U64!\n}\n\nenum ScriptParametersVersion {\n\tV1\n}\n\nscalar Signature\n\ninput SpendQueryElementInput {\n\t\"\"\"\n\tIdentifier of the asset to spend.\n\t\"\"\"\n\tassetId: AssetId!\n\t\"\"\"\n\tTarget amount for the query.\n\t\"\"\"\n\tamount: U128!\n\t\"\"\"\n\tThe maximum number of currencies for selection.\n\t\"\"\"\n\tmax: U16\n\t\"\"\"\n\tIf true, returns available coins instead of failing when the requested amount is unavailable.\n\t\"\"\"\n\tallowPartial: Boolean\n}\n\ntype SqueezedOutStatus {\n\ttransactionId: TransactionId!\n\treason: String!\n}\n\ntype StateTransitionBytecode {\n\troot: HexString!\n\tbytecode: UploadedBytecode!\n}\n\ntype StateTransitionPurpose {\n\troot: Bytes32!\n}\n\ntype StorageReadReplayEvent {\n\tcolumn: U32!\n\tkey: HexString!\n\tvalue: HexString\n}\n\ntype StorageSlot {\n\tkey: Bytes32!\n\tvalue: HexString!\n}\n\n\nscalar SubId\n\ntype SubmittedStatus {\n\ttime: Tai64Timestamp!\n}\n\ntype Subscription {\n\t\"\"\"\n\tReturns a stream of status updates for the given transaction id.\n\tIf the current status is [`TransactionStatus::Success`], [`TransactionStatus::Failed`],\n\tor [`TransactionStatus::SqueezedOut`] the stream will return that and end immediately.\n\tOther, intermediate statuses will also be returned but the stream will remain active\n\tand wait for a future updates.\n\t\n\tThis stream will wait forever so it's advised to use within a timeout.\n\t\n\tIt is possible for the stream to miss an update if it is polled slower\n\tthen the updates arrive. In such a case the stream will close without\n\ta status. If this occurs the stream can simply be restarted to return\n\tthe latest status.\n\t\"\"\"\n\tstatusChange(\n\t\t\"\"\"\n\t\tThe ID of the transaction\n\t\t\"\"\"\n\t\tid: TransactionId!,\n\t\t\"\"\"\n\t\tIf true, accept to receive the preconfirmation status\n\t\t\"\"\"\n\t\tincludePreconfirmation: Boolean\n\t): TransactionStatus!\n\talpha__preconfirmations: TransactionStatus!\n\t\"\"\"\n\tSubmits transaction to the `TxPool` and await either success or failure.\n\t\"\"\"\n\tsubmitAndAwait(tx: HexString!, estimatePredicates: Boolean): TransactionStatus!\n\t\"\"\"\n\tSubmits the transaction to the `TxPool` and returns a stream of events.\n\tCompared to the `submitAndAwait`, the stream also contains\n\t`SubmittedStatus` and potentially preconfirmation as an intermediate state.\n\t\"\"\"\n\tsubmitAndAwaitStatus(tx: HexString!, estimatePredicates: Boolean, includePreconfirmation: Boolean): TransactionStatus!\n\tcontractStorageSlots(contractId: ContractId!): StorageSlot!\n\tcontractStorageBalances(contractId: ContractId!): ContractBalance!\n\talpha__new_blocks: HexString!\n}\n\ntype SuccessStatus {\n\ttransactionId: TransactionId!\n\tblockHeight: U32!\n\tblock: Block!\n\ttransaction: Transaction!\n\ttime: Tai64Timestamp!\n\tprogramState: ProgramState\n\treceipts: [Receipt!]!\n\ttotalGas: U64!\n\ttotalFee: U64!\n}\n\nscalar Tai64Timestamp\n\ntype Transaction {\n\tid: TransactionId!\n\tinputAssetIds: [AssetId!]\n\tinputContracts: [ContractId!]\n\tinputContract: InputContract\n\tpolicies: Policies\n\tscriptGasLimit: U64\n\tmaturity: U32\n\tmintAmount: U64\n\tmintAssetId: AssetId\n\tmintGasPrice: U64\n\ttxPointer: TxPointer\n\tisScript: Boolean!\n\tisCreate: Boolean!\n\tisMint: Boolean!\n\tisUpgrade: Boolean!\n\tisUpload: Boolean!\n\tisBlob: Boolean!\n\tinputs: [Input!]\n\toutputs: [Output!]!\n\toutputContract: ContractOutput\n\twitnesses: [HexString!]\n\treceiptsRoot: Bytes32\n\tstatus(includePreconfirmation: Boolean): TransactionStatus\n\tscript: HexString\n\tscriptData: HexString\n\tbytecodeWitnessIndex: U16\n\tblobId: BlobId\n\tsalt: Salt\n\tstorageSlots: [HexString!]\n\tbytecodeRoot: Bytes32\n\tsubsectionIndex: U16\n\tsubsectionsNumber: U16\n\tproofSet: [Bytes32!]\n\tupgradePurpose: UpgradePurpose\n\t\"\"\"\n\tReturn the transaction bytes using canonical encoding\n\t\"\"\"\n\trawPayload: HexString!\n}\n\ntype TransactionConnection {\n\t\"\"\"\n\tInformation to aid in pagination.\n\t\"\"\"\n\tpageInfo: PageInfo!\n\t\"\"\"\n\tA list of edges.\n\t\"\"\"\n\tedges: [TransactionEdge!]!\n\t\"\"\"\n\tA list of nodes.\n\t\"\"\"\n\tnodes: [Transaction!]!\n}\n\n\"\"\"\nAn edge in a connection.\n\"\"\"\ntype TransactionEdge {\n\t\"\"\"\n\tThe item at the end of the edge\n\t\"\"\"\n\tnode: Transaction!\n\t\"\"\"\n\tA cursor for use in pagination\n\t\"\"\"\n\tcursor: String!\n}\n\nscalar TransactionId\n\nunion TransactionStatus = SubmittedStatus | SuccessStatus | PreconfirmationSuccessStatus | SqueezedOutStatus | FailureStatus | PreconfirmationFailureStatus\n\ntype TxParameters {\n\tversion: TxParametersVersion!\n\tmaxInputs: U16!\n\tmaxOutputs: U16!\n\tmaxWitnesses: U32!\n\tmaxGasPerTx: U64!\n\tmaxSize: U64!\n\tmaxBytecodeSubsections: U16!\n}\n\nenum TxParametersVersion {\n\tV1\n}\n\nscalar TxPointer\n\ntype TxPoolStats {\n\t\"\"\"\n\tThe number of transactions in the pool\n\t\"\"\"\n\ttxCount: U64!\n\t\"\"\"\n\tThe total size of the transactions in the pool\n\t\"\"\"\n\ttotalSize: U64!\n\t\"\"\"\n\tThe total gas of the transactions in the pool\n\t\"\"\"\n\ttotalGas: U64!\n}\n\nscalar U128\n\nscalar U16\n\nscalar U32\n\nscalar U64\n\nunion UpgradePurpose = ConsensusParametersPurpose | StateTransitionPurpose\n\ntype UploadedBytecode {\n\t\"\"\"\n\tCombined bytecode of all uploaded subsections.\n\t\"\"\"\n\tbytecode: HexString!\n\t\"\"\"\n\tNumber of uploaded subsections (if incomplete).\n\t\"\"\"\n\tuploadedSubsectionsNumber: Int\n\t\"\"\"\n\tIndicates if the bytecode upload is complete.\n\t\"\"\"\n\tcompleted: Boolean!\n}\n\nscalar UtxoId\n\ntype VariableOutput {\n\tto: Address!\n\tamount: U64!\n\tassetId: AssetId!\n}\n\ndirective @deprecated(reason: String = \"No longer supported\") on FIELD_DEFINITION | ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION | ENUM_VALUE\ndirective @include(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT\ndirective @oneOf on INPUT_OBJECT\ndirective @skip(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT\nschema {\n\tquery: Query\n\tmutation: Mutation\n\tsubscription: Subscription\n}\n"
  },
  {
    "path": "packages/fuels-accounts/src/signers/fake.rs",
    "content": "use async_trait::async_trait;\nuse fuel_crypto::{Message, Signature};\nuse fuels_core::{\n    traits::Signer,\n    types::{Address, errors::Result},\n};\n\nuse super::private_key::PrivateKeySigner;\n\n#[derive(Clone, Debug, PartialEq, Eq)]\npub struct FakeSigner {\n    address: Address,\n}\n\nimpl From<PrivateKeySigner> for FakeSigner {\n    fn from(signer: PrivateKeySigner) -> Self {\n        Self {\n            address: signer.address(),\n        }\n    }\n}\n\nimpl FakeSigner {\n    pub fn new(address: Address) -> Self {\n        Self { address }\n    }\n}\n\n#[cfg_attr(target_arch = \"wasm32\", async_trait(?Send))]\n#[cfg_attr(not(target_arch = \"wasm32\"), async_trait)]\nimpl Signer for FakeSigner {\n    async fn sign(&self, _message: Message) -> Result<Signature> {\n        Ok(Signature::default())\n    }\n\n    fn address(&self) -> Address {\n        self.address\n    }\n}\n"
  },
  {
    "path": "packages/fuels-accounts/src/signers/kms/aws.rs",
    "content": "use async_trait::async_trait;\npub use aws_config;\npub use aws_sdk_kms;\nuse aws_sdk_kms::{\n    Client,\n    primitives::Blob,\n    types::{KeySpec, MessageType, SigningAlgorithmSpec},\n};\nuse fuel_crypto::{Message, PublicKey, Signature};\nuse fuels_core::{\n    traits::Signer,\n    types::{\n        Address,\n        errors::{Error, Result},\n    },\n};\nuse k256::{PublicKey as K256PublicKey, pkcs8::DecodePublicKey};\n\nuse super::signature_utils;\n\nconst AWS_KMS_ERROR_PREFIX: &str = \"AWS KMS Error\";\n\nconst EXPECTED_KEY_SPEC: KeySpec = KeySpec::EccSecgP256K1;\n\n#[derive(Clone, Debug)]\npub struct AwsKmsSigner {\n    key_id: String,\n    client: Client,\n    public_key_der: Vec<u8>,\n    fuel_address: Address,\n}\n\nimpl AwsKmsSigner {\n    pub async fn new(key_id: impl Into<String>, client: &Client) -> Result<Self> {\n        let key_id: String = key_id.into();\n        Self::validate_key_spec(client, &key_id).await?;\n        let public_key = Self::retrieve_public_key(client, &key_id).await?;\n        let fuel_address = Self::derive_fuel_address(&public_key)?;\n\n        Ok(Self {\n            key_id,\n            client: client.clone(),\n            public_key_der: public_key,\n            fuel_address,\n        })\n    }\n\n    async fn validate_key_spec(client: &Client, key_id: &str) -> Result<()> {\n        let response = client\n            .get_public_key()\n            .key_id(key_id)\n            .send()\n            .await\n            .map_err(format_aws_error)?;\n\n        let key_spec = response.key_spec;\n\n        match key_spec {\n            Some(EXPECTED_KEY_SPEC) => Ok(()),\n            other => Err(Error::Other(format!(\n                \"{AWS_KMS_ERROR_PREFIX}: Invalid key type {other:?}, expected {EXPECTED_KEY_SPEC:?}\"\n            ))),\n        }\n    }\n\n    async fn retrieve_public_key(client: &Client, key_id: &str) -> Result<Vec<u8>> {\n        let response = client\n            .get_public_key()\n            .key_id(key_id)\n            .send()\n            .await\n            .map_err(format_aws_error)?;\n\n        response\n            .public_key()\n            .map(|blob| blob.as_ref().to_vec())\n            .ok_or_else(|| {\n                Error::Other(format!(\"{AWS_KMS_ERROR_PREFIX}: Empty public key response\"))\n            })\n    }\n\n    fn derive_fuel_address(public_key: &[u8]) -> Result<Address> {\n        let k256_key = K256PublicKey::from_public_key_der(public_key)\n            .map_err(|_| Error::Other(format!(\"{AWS_KMS_ERROR_PREFIX}: Invalid DER encoding\")))?;\n\n        let fuel_public_key = PublicKey::from(k256_key);\n\n        Ok(Address::from(*fuel_public_key.hash()))\n    }\n\n    async fn request_kms_signature(&self, message: Message) -> Result<Vec<u8>> {\n        let response = self\n            .client\n            .sign()\n            .key_id(&self.key_id)\n            .signing_algorithm(SigningAlgorithmSpec::EcdsaSha256)\n            .message_type(MessageType::Digest)\n            .message(Blob::new(message.as_ref().to_vec()))\n            .send()\n            .await\n            .map_err(|err| {\n                Error::Other(format!(\"{AWS_KMS_ERROR_PREFIX}: Signing failed - {err}\"))\n            })?;\n\n        response\n            .signature\n            .map(|blob| blob.into_inner())\n            .ok_or_else(|| {\n                Error::Other(format!(\"{AWS_KMS_ERROR_PREFIX}: Empty signature response\"))\n            })\n    }\n\n    pub fn key_id(&self) -> &String {\n        &self.key_id\n    }\n\n    pub fn public_key(&self) -> &Vec<u8> {\n        &self.public_key_der\n    }\n}\n\n#[async_trait]\nimpl Signer for AwsKmsSigner {\n    async fn sign(&self, message: Message) -> Result<Signature> {\n        let signature_der = self.request_kms_signature(message).await?;\n\n        let k256_key = K256PublicKey::from_public_key_der(&self.public_key_der).map_err(|_| {\n            Error::Other(format!(\"{AWS_KMS_ERROR_PREFIX}: Invalid cached public key\"))\n        })?;\n\n        let (normalized_sig, recovery_id) = signature_utils::normalize_signature(\n            &signature_der,\n            message,\n            &k256_key,\n            AWS_KMS_ERROR_PREFIX,\n        )?;\n\n        Ok(signature_utils::convert_to_fuel_signature(\n            normalized_sig,\n            recovery_id,\n        ))\n    }\n\n    fn address(&self) -> Address {\n        self.fuel_address\n    }\n}\n\nfn format_aws_error(err: impl std::fmt::Display) -> Error {\n    Error::Other(format!(\"{AWS_KMS_ERROR_PREFIX}: {err}\"))\n}\n"
  },
  {
    "path": "packages/fuels-accounts/src/signers/kms/google.rs",
    "content": "use async_trait::async_trait;\nuse fuel_crypto::{Message, PublicKey, Signature};\nuse fuels_core::{\n    traits::Signer,\n    types::{\n        Address,\n        errors::{Error, Result},\n    },\n};\npub use google_cloud_kms;\nuse google_cloud_kms::{\n    client::Client,\n    grpc::kms::v1::{\n        AsymmetricSignRequest, Digest, GetPublicKeyRequest,\n        crypto_key_version::CryptoKeyVersionAlgorithm::EcSignSecp256k1Sha256,\n        digest::Digest::Sha256,\n    },\n};\nuse k256::{PublicKey as K256PublicKey, pkcs8::DecodePublicKey};\n\nuse super::signature_utils;\n\nconst GOOGLE_KMS_ERROR_PREFIX: &str = \"Google KMS Error\";\n\n#[derive(Clone, Debug)]\npub struct GoogleKmsSigner {\n    key_path: String,\n    client: Client,\n    public_key_pem: String,\n    fuel_address: Address,\n}\n\n#[derive(Debug, Clone)]\npub struct CryptoKeyVersionName {\n    pub project_id: String,\n    pub location: String,\n    pub key_ring: String,\n    pub key_id: String,\n    pub key_version: String,\n}\n\nimpl CryptoKeyVersionName {\n    pub fn new(\n        project_id: impl Into<String>,\n        location: impl Into<String>,\n        key_ring: impl Into<String>,\n        key_id: impl Into<String>,\n        key_version: impl Into<String>,\n    ) -> Self {\n        Self {\n            project_id: project_id.into(),\n            location: location.into(),\n            key_ring: key_ring.into(),\n            key_id: key_id.into(),\n            key_version: key_version.into(),\n        }\n    }\n}\n\nimpl std::fmt::Display for CryptoKeyVersionName {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        write!(\n            f,\n            \"projects/{}/locations/{}/keyRings/{}/cryptoKeys/{}/cryptoKeyVersions/{}\",\n            self.project_id, self.location, self.key_ring, self.key_id, self.key_version\n        )\n    }\n}\n\nimpl GoogleKmsSigner {\n    pub async fn new(key_path: impl Into<String>, client: &Client) -> Result<Self> {\n        let key_path: String = key_path.into();\n        let public_key_pem = Self::retrieve_public_key(client, &key_path).await?;\n        let fuel_address = Self::derive_fuel_address(&public_key_pem)?;\n\n        Ok(Self {\n            key_path,\n            client: client.clone(),\n            public_key_pem,\n            fuel_address,\n        })\n    }\n\n    async fn retrieve_public_key(client: &Client, key_path: &str) -> Result<String> {\n        let request = GetPublicKeyRequest {\n            name: key_path.to_string(),\n        };\n\n        let response = client\n            .get_public_key(request, None)\n            .await\n            .map_err(|e| format_gcp_error(format!(\"Failed to get public key: {}\", e)))?;\n\n        if response.algorithm != EcSignSecp256k1Sha256 as i32 {\n            return Err(Error::Other(format!(\n                \"{GOOGLE_KMS_ERROR_PREFIX}: Invalid key algorithm: {}, expected EC_SIGN_SECP256K1_SHA256\",\n                response.algorithm\n            )));\n        }\n\n        Ok(response.pem)\n    }\n\n    fn derive_fuel_address(pem: &str) -> Result<Address> {\n        let k256_key = K256PublicKey::from_public_key_pem(pem).map_err(|_| {\n            Error::Other(format!(\"{GOOGLE_KMS_ERROR_PREFIX}: Invalid PEM encoding\"))\n        })?;\n\n        let fuel_public_key = PublicKey::from(k256_key);\n\n        Ok(Address::from(*fuel_public_key.hash()))\n    }\n\n    async fn request_gcp_signature(&self, message: Message) -> Result<Vec<u8>> {\n        let digest = Digest {\n            digest: Some(Sha256(message.as_ref().to_vec())),\n        };\n\n        let request = AsymmetricSignRequest {\n            name: self.key_path.clone(),\n            digest: Some(digest),\n            digest_crc32c: None,\n            ..AsymmetricSignRequest::default()\n        };\n\n        let response = self\n            .client\n            .asymmetric_sign(request, None)\n            .await\n            .map_err(|e| format_gcp_error(format!(\"Signing failed: {}\", e)))?;\n\n        if response.signature.is_empty() {\n            return Err(Error::Other(format!(\n                \"{GOOGLE_KMS_ERROR_PREFIX}: Empty signature response\"\n            )));\n        }\n\n        Ok(response.signature)\n    }\n\n    pub fn key_path(&self) -> &String {\n        &self.key_path\n    }\n\n    pub fn public_key(&self) -> &String {\n        &self.public_key_pem\n    }\n}\n\n#[async_trait]\nimpl Signer for GoogleKmsSigner {\n    async fn sign(&self, message: Message) -> Result<Signature> {\n        let signature_der = self.request_gcp_signature(message).await?;\n\n        let k256_key = K256PublicKey::from_public_key_pem(&self.public_key_pem).map_err(|_| {\n            Error::Other(format!(\n                \"{GOOGLE_KMS_ERROR_PREFIX}: Invalid cached public key\"\n            ))\n        })?;\n\n        let (normalized_sig, recovery_id) = signature_utils::normalize_signature(\n            &signature_der,\n            message,\n            &k256_key,\n            GOOGLE_KMS_ERROR_PREFIX,\n        )?;\n\n        Ok(signature_utils::convert_to_fuel_signature(\n            normalized_sig,\n            recovery_id,\n        ))\n    }\n\n    fn address(&self) -> Address {\n        self.fuel_address\n    }\n}\n\nfn format_gcp_error(err: impl std::fmt::Display) -> Error {\n    Error::Other(format!(\"{GOOGLE_KMS_ERROR_PREFIX}: {err}\"))\n}\n"
  },
  {
    "path": "packages/fuels-accounts/src/signers/kms.rs",
    "content": "#[cfg(feature = \"signer-aws-kms\")]\npub mod aws;\n#[cfg(feature = \"signer-google-kms\")]\npub mod google;\n\nmod signature_utils {\n    use fuel_crypto::{Message, Signature};\n    use fuels_core::types::errors::{Error, Result};\n    use k256::{\n        PublicKey as K256PublicKey,\n        ecdsa::{RecoveryId, Signature as K256Signature, VerifyingKey},\n    };\n\n    pub fn normalize_signature(\n        signature_der: &[u8],\n        message: Message,\n        expected_pubkey: &K256PublicKey,\n        error_prefix: &str,\n    ) -> Result<(K256Signature, RecoveryId)> {\n        let signature = K256Signature::from_der(signature_der)\n            .map_err(|_| Error::Other(format!(\"{error_prefix}: Invalid DER signature\")))?;\n\n        let normalized_sig = signature.normalize_s().unwrap_or(signature);\n\n        let recovery_id =\n            determine_recovery_id(&normalized_sig, message, expected_pubkey, error_prefix)?;\n\n        Ok((normalized_sig, recovery_id))\n    }\n\n    pub fn determine_recovery_id(\n        sig: &K256Signature,\n        message: Message,\n        expected_pubkey: &K256PublicKey,\n        error_prefix: &str,\n    ) -> Result<RecoveryId> {\n        let recid_even = RecoveryId::new(false, false);\n        let recid_odd = RecoveryId::new(true, false);\n\n        let expected_verifying_key: VerifyingKey = expected_pubkey.into();\n\n        let recovered_even = VerifyingKey::recover_from_prehash(&*message, sig, recid_even);\n        let recovered_odd = VerifyingKey::recover_from_prehash(&*message, sig, recid_odd);\n\n        if recovered_even\n            .map(|r| r == expected_verifying_key)\n            .unwrap_or(false)\n        {\n            Ok(recid_even)\n        } else if recovered_odd\n            .map(|r| r == expected_verifying_key)\n            .unwrap_or(false)\n        {\n            Ok(recid_odd)\n        } else {\n            Err(Error::Other(format!(\n                \"{error_prefix}: Invalid signature (could not recover correct public key)\"\n            )))\n        }\n    }\n\n    pub fn convert_to_fuel_signature(\n        signature: K256Signature,\n        recovery_id: RecoveryId,\n    ) -> Signature {\n        let recovery_byte = recovery_id.is_y_odd() as u8;\n\n        let mut bytes: [u8; 64] = signature.to_bytes().into();\n\n        bytes[32] = (recovery_byte << 7) | (bytes[32] & 0x7F);\n\n        Signature::from_bytes(bytes)\n    }\n}\n"
  },
  {
    "path": "packages/fuels-accounts/src/signers/private_key.rs",
    "content": "use async_trait::async_trait;\nuse fuel_crypto::{Message, PublicKey, SecretKey, Signature};\nuse fuels_core::{\n    traits::Signer,\n    types::{Address, errors::Result},\n};\nuse rand::{CryptoRng, Rng, RngCore};\nuse zeroize::{Zeroize, ZeroizeOnDrop};\n\n/// Generates a random mnemonic phrase given a random number generator and the number of words to\n/// generate, `count`.\npub fn generate_mnemonic_phrase<R: Rng>(rng: &mut R, count: usize) -> Result<String> {\n    Ok(fuel_crypto::generate_mnemonic_phrase(rng, count)?)\n}\n\n#[derive(Clone, Zeroize, ZeroizeOnDrop)]\npub struct PrivateKeySigner {\n    private_key: SecretKey,\n    #[zeroize(skip)]\n    address: Address,\n}\n\nimpl std::fmt::Debug for PrivateKeySigner {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        f.debug_struct(\"PrivateKeySigner\")\n            .field(\"private_key\", &\"REDACTED\")\n            .field(\"address\", &self.address)\n            .finish()\n    }\n}\n\nimpl PrivateKeySigner {\n    pub fn new(private_key: SecretKey) -> Self {\n        let public = PublicKey::from(&private_key);\n        let address = Address::from(*public.hash());\n\n        Self {\n            private_key,\n            address,\n        }\n    }\n\n    pub fn random(rng: &mut (impl CryptoRng + RngCore)) -> Self {\n        Self::new(SecretKey::random(rng))\n    }\n\n    pub fn address(&self) -> Address {\n        self.address\n    }\n\n    pub fn secret_key(&self) -> SecretKey {\n        self.private_key\n    }\n}\n\n#[cfg_attr(target_arch = \"wasm32\", async_trait(?Send))]\n#[cfg_attr(not(target_arch = \"wasm32\"), async_trait)]\nimpl Signer for PrivateKeySigner {\n    async fn sign(&self, message: Message) -> Result<Signature> {\n        let sig = Signature::sign(&self.private_key, &message);\n\n        Ok(sig)\n    }\n\n    fn address(&self) -> Address {\n        self.address\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use std::str::FromStr;\n\n    use rand::{SeedableRng, rngs::StdRng};\n\n    use super::*;\n    use crate::signers::derivation::DEFAULT_DERIVATION_PATH;\n\n    #[tokio::test]\n    async fn mnemonic_generation() -> Result<()> {\n        let mnemonic = generate_mnemonic_phrase(&mut rand::thread_rng(), 12)?;\n        let _wallet = PrivateKeySigner::new(SecretKey::new_from_mnemonic_phrase_with_path(\n            &mnemonic,\n            DEFAULT_DERIVATION_PATH,\n        )?);\n\n        Ok(())\n    }\n\n    #[tokio::test]\n    async fn sign_and_verify() -> Result<()> {\n        // ANCHOR: sign_message\n        let mut rng = StdRng::seed_from_u64(2322u64);\n        let mut secret_seed = [0u8; 32];\n        rng.fill_bytes(&mut secret_seed);\n\n        let secret = secret_seed.as_slice().try_into()?;\n\n        // Create a signer using the private key created above.\n        let signer = PrivateKeySigner::new(secret);\n\n        let message = Message::new(\"my message\".as_bytes());\n        let signature = signer.sign(message).await?;\n\n        // Check if signature is what we expect it to be\n        assert_eq!(\n            signature,\n            Signature::from_str(\n                \"0x8eeb238db1adea4152644f1cd827b552dfa9ab3f4939718bb45ca476d167c6512a656f4d4c7356bfb9561b14448c230c6e7e4bd781df5ee9e5999faa6495163d\"\n            )?\n        );\n\n        // Recover the public key that signed the message\n        let recovered_pub_key: PublicKey = signature.recover(&message)?;\n\n        assert_eq!(*signer.address, *recovered_pub_key.hash());\n\n        // Verify signature\n        signature.verify(&recovered_pub_key, &message)?;\n        // ANCHOR_END: sign_message\n\n        Ok(())\n    }\n}\n"
  },
  {
    "path": "packages/fuels-accounts/src/signers.rs",
    "content": "pub mod derivation {\n    pub const BIP44_PURPOSE: &str = \"44'\";\n    pub const COIN_TYPE: &str = \"1179993420'\";\n    pub const DEFAULT_DERIVATION_PATH: &str = \"m/44'/1179993420'/0'/0/0\";\n}\n\n#[cfg(any(feature = \"signer-aws-kms\", feature = \"signer-google-kms\"))]\npub mod kms;\n\npub mod fake;\npub mod private_key;\n"
  },
  {
    "path": "packages/fuels-accounts/src/wallet.rs",
    "content": "use crate::{provider::Provider, signers::private_key::PrivateKeySigner};\n\n#[derive(Debug, Clone)]\npub struct Wallet<S = Unlocked<PrivateKeySigner>> {\n    state: S,\n    provider: Provider,\n}\n\nimpl<S> Wallet<S> {\n    pub fn set_provider(&mut self, provider: Provider) {\n        self.provider = provider;\n    }\n\n    pub fn provider(&self) -> &Provider {\n        &self.provider\n    }\n}\n\nmod unlocked {\n    use async_trait::async_trait;\n    use fuels_core::{\n        traits::Signer,\n        types::{\n            Address, AssetId, coin_type_id::CoinTypeId, errors::Result, input::Input,\n            transaction_builders::TransactionBuilder,\n        },\n    };\n    use rand::{CryptoRng, RngCore};\n\n    use super::{Locked, Wallet};\n    use crate::{\n        Account, ViewOnlyAccount, provider::Provider, signers::private_key::PrivateKeySigner,\n    };\n\n    #[derive(Debug, Clone)]\n    pub struct Unlocked<S> {\n        signer: S,\n    }\n\n    impl<S> Unlocked<S> {\n        fn new(signer: S) -> Self {\n            Self { signer }\n        }\n    }\n\n    impl<S> Wallet<Unlocked<S>> {\n        pub fn new(signer: S, provider: Provider) -> Self {\n            Wallet {\n                state: Unlocked::new(signer),\n                provider,\n            }\n        }\n\n        pub fn signer(&self) -> &S {\n            &self.state.signer\n        }\n    }\n\n    impl Wallet<Unlocked<PrivateKeySigner>> {\n        pub fn random(rng: &mut (impl CryptoRng + RngCore), provider: Provider) -> Self {\n            Self::new(PrivateKeySigner::random(rng), provider)\n        }\n    }\n\n    impl<S> Wallet<Unlocked<S>>\n    where\n        S: Signer,\n    {\n        pub fn lock(&self) -> Wallet<Locked> {\n            Wallet::new_locked(self.state.signer.address(), self.provider.clone())\n        }\n    }\n\n    #[async_trait]\n    impl<S> ViewOnlyAccount for Wallet<Unlocked<S>>\n    where\n        S: Signer + Clone + Send + Sync + std::fmt::Debug + 'static,\n    {\n        fn address(&self) -> Address {\n            self.state.signer.address()\n        }\n\n        fn try_provider(&self) -> Result<&Provider> {\n            Ok(&self.provider)\n        }\n\n        async fn get_asset_inputs_for_amount(\n            &self,\n            asset_id: AssetId,\n            amount: u128,\n            excluded_coins: Option<Vec<CoinTypeId>>,\n        ) -> Result<Vec<Input>> {\n            Ok(self\n                .get_spendable_resources(asset_id, amount, excluded_coins)\n                .await?\n                .into_iter()\n                .map(Input::resource_signed)\n                .collect::<Vec<Input>>())\n        }\n    }\n\n    #[async_trait]\n    impl<S> Account for Wallet<Unlocked<S>>\n    where\n        S: Signer + Clone + Send + Sync + std::fmt::Debug + 'static,\n    {\n        fn add_witnesses<Tb: TransactionBuilder>(&self, tb: &mut Tb) -> Result<()> {\n            tb.add_signer(self.state.signer.clone())?;\n\n            Ok(())\n        }\n    }\n}\npub use unlocked::*;\n\nmod locked {\n    use async_trait::async_trait;\n    use fuels_core::types::{\n        Address, AssetId, coin_type_id::CoinTypeId, errors::Result, input::Input,\n    };\n\n    use super::Wallet;\n    use crate::{ViewOnlyAccount, provider::Provider};\n\n    #[derive(Debug, Clone)]\n    pub struct Locked {\n        address: Address,\n    }\n\n    impl Locked {\n        fn new(address: Address) -> Self {\n            Self { address }\n        }\n    }\n\n    impl Wallet<Locked> {\n        pub fn new_locked(addr: Address, provider: Provider) -> Self {\n            Self {\n                state: Locked::new(addr),\n                provider,\n            }\n        }\n    }\n\n    #[async_trait]\n    impl ViewOnlyAccount for Wallet<Locked> {\n        fn address(&self) -> Address {\n            self.state.address\n        }\n\n        fn try_provider(&self) -> Result<&Provider> {\n            Ok(&self.provider)\n        }\n\n        async fn get_asset_inputs_for_amount(\n            &self,\n            asset_id: AssetId,\n            amount: u128,\n            excluded_coins: Option<Vec<CoinTypeId>>,\n        ) -> Result<Vec<Input>> {\n            Ok(self\n                .get_spendable_resources(asset_id, amount, excluded_coins)\n                .await?\n                .into_iter()\n                .map(Input::resource_signed)\n                .collect::<Vec<Input>>())\n        }\n    }\n}\npub use locked::*;\n"
  },
  {
    "path": "packages/fuels-code-gen/Cargo.toml",
    "content": "[package]\nname = \"fuels-code-gen\"\nversion = { workspace = true }\nauthors = { workspace = true }\nedition = { workspace = true }\nhomepage = { workspace = true }\nlicense = { workspace = true }\nrepository = { workspace = true }\nrust-version = { workspace = true }\ndescription = \"Used for code generation in the Fuel Rust SDK\"\n\n[dependencies]\nInflector = { workspace = true }\nfuel-abi-types = { workspace = true }\nitertools = { workspace = true }\nproc-macro2 = { workspace = true }\nquote = { workspace = true }\nregex = { workspace = true }\nserde_json = { workspace = true }\nsyn = { workspace = true }\n\n[dev-dependencies]\npretty_assertions = { workspace = true, features = [\"alloc\"] }\n\n[package.metadata.cargo-machete]\nignored = [\"Inflector\"]\n"
  },
  {
    "path": "packages/fuels-code-gen/src/error.rs",
    "content": "use std::{\n    fmt::{Debug, Display, Formatter},\n    io,\n};\n\npub struct Error(pub String);\n\nimpl Error {\n    pub fn combine<T: Into<Self>>(self, err: T) -> Self {\n        error!(\"{} {}\", self.0, err.into().0)\n    }\n}\n\n#[macro_export]\nmacro_rules! error {\n   ($fmt_str: literal $(,$arg: expr)*) => {$crate::error::Error(format!($fmt_str,$($arg),*))}\n}\n\npub use error;\n\npub type Result<T> = std::result::Result<T, Error>;\n\nimpl Debug for Error {\n    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {\n        write!(f, \"{:?}\", self.0)\n    }\n}\n\nimpl Display for Error {\n    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {\n        write!(f, \"{}\", self.0)\n    }\n}\n\nimpl std::error::Error for Error {}\n\nmacro_rules! impl_from {\n    ($($err_type:ty),*) => {\n        $(\n            impl From<$err_type> for self::Error {\n                fn from(err: $err_type) -> Self {\n                    Self(err.to_string())\n                }\n            }\n        )*\n    }\n}\n\nimpl_from!(\n    serde_json::Error,\n    io::Error,\n    proc_macro2::LexError,\n    fuel_abi_types::error::Error\n);\n"
  },
  {
    "path": "packages/fuels-code-gen/src/lib.rs",
    "content": "pub use program_bindings::*;\n\npub mod error;\nmod program_bindings;\npub mod utils;\n"
  },
  {
    "path": "packages/fuels-code-gen/src/program_bindings/abigen/abigen_target.rs",
    "content": "use std::{\n    convert::TryFrom,\n    env, fs,\n    path::{Path, PathBuf},\n    str::FromStr,\n};\n\nuse fuel_abi_types::abi::full_program::FullProgramABI;\nuse proc_macro2::Ident;\n\nuse crate::error::{Error, Result, error};\n\n#[derive(Debug, Clone)]\npub struct AbigenTarget {\n    pub(crate) name: String,\n    pub(crate) source: Abi,\n    pub(crate) program_type: ProgramType,\n}\n\nimpl AbigenTarget {\n    pub fn new(name: String, source: Abi, program_type: ProgramType) -> Self {\n        Self {\n            name,\n            source,\n            program_type,\n        }\n    }\n\n    pub fn name(&self) -> &str {\n        &self.name\n    }\n\n    pub fn source(&self) -> &Abi {\n        &self.source\n    }\n\n    pub fn program_type(&self) -> ProgramType {\n        self.program_type\n    }\n}\n\n#[derive(Debug, Clone)]\npub struct Abi {\n    pub(crate) path: Option<PathBuf>,\n    pub(crate) abi: FullProgramABI,\n}\n\nimpl Abi {\n    pub fn load_from(path: impl AsRef<Path>) -> Result<Abi> {\n        let path = Self::canonicalize_path(path.as_ref())?;\n\n        let json_abi = fs::read_to_string(&path).map_err(|e| {\n            error!(\n                \"failed to read `abi` file with path {}: {}\",\n                path.display(),\n                e\n            )\n        })?;\n        let abi = Self::parse_from_json(&json_abi)?;\n\n        Ok(Abi {\n            path: Some(path),\n            abi,\n        })\n    }\n\n    fn canonicalize_path(path: &Path) -> Result<PathBuf> {\n        let current_dir = env::current_dir()\n            .map_err(|e| error!(\"unable to get current directory: \").combine(e))?;\n\n        let root = current_dir.canonicalize().map_err(|e| {\n            error!(\n                \"unable to canonicalize current directory {}: \",\n                current_dir.display()\n            )\n            .combine(e)\n        })?;\n\n        let path = root.join(path);\n\n        if path.is_relative() {\n            path.canonicalize().map_err(|e| {\n                error!(\n                    \"unable to canonicalize file from working dir {} with path {}: {}\",\n                    env::current_dir()\n                        .map(|cwd| cwd.display().to_string())\n                        .unwrap_or_else(|err| format!(\"??? ({err})\")),\n                    path.display(),\n                    e\n                )\n            })\n        } else {\n            Ok(path)\n        }\n    }\n\n    fn parse_from_json(json_abi: &str) -> Result<FullProgramABI> {\n        FullProgramABI::from_json_abi(json_abi)\n            .map_err(|e| error!(\"malformed `abi`. Did you use `forc` to create it?: \").combine(e))\n    }\n\n    pub fn path(&self) -> Option<&PathBuf> {\n        self.path.as_ref()\n    }\n\n    pub fn abi(&self) -> &FullProgramABI {\n        &self.abi\n    }\n}\n\nimpl FromStr for Abi {\n    type Err = Error;\n\n    fn from_str(json_abi: &str) -> Result<Self> {\n        let abi = Abi::parse_from_json(json_abi)?;\n\n        Ok(Abi { path: None, abi })\n    }\n}\n\n#[derive(Debug, Clone, Copy, PartialEq, Eq)]\npub enum ProgramType {\n    Script,\n    Contract,\n    Predicate,\n}\n\nimpl FromStr for ProgramType {\n    type Err = Error;\n\n    fn from_str(string: &str) -> std::result::Result<Self, Self::Err> {\n        let program_type = match string {\n            \"Script\" => ProgramType::Script,\n            \"Contract\" => ProgramType::Contract,\n            \"Predicate\" => ProgramType::Predicate,\n            _ => {\n                return Err(error!(\n                    \"`{string}` is not a valid program type. Expected one of: `Script`, `Contract`, `Predicate`\"\n                ));\n            }\n        };\n\n        Ok(program_type)\n    }\n}\n\nimpl TryFrom<Ident> for ProgramType {\n    type Error = syn::Error;\n\n    fn try_from(ident: Ident) -> std::result::Result<Self, Self::Error> {\n        ident\n            .to_string()\n            .as_str()\n            .parse()\n            .map_err(|e| Self::Error::new(ident.span(), e))\n    }\n}\n"
  },
  {
    "path": "packages/fuels-code-gen/src/program_bindings/abigen/bindings/contract.rs",
    "content": "use fuel_abi_types::abi::full_program::{FullABIFunction, FullProgramABI};\nuse itertools::Itertools;\nuse proc_macro2::{Ident, TokenStream};\nuse quote::{TokenStreamExt, quote};\n\nuse crate::{\n    error::Result,\n    program_bindings::{\n        abigen::{\n            bindings::function_generator::FunctionGenerator,\n            configurables::generate_code_for_configurable_constants,\n            logs::{generate_id_error_codes_pairs, log_formatters_instantiation_code},\n        },\n        generated_code::GeneratedCode,\n    },\n    utils::{TypePath, ident},\n};\n\npub(crate) fn contract_bindings(\n    name: &Ident,\n    abi: FullProgramABI,\n    no_std: bool,\n) -> Result<GeneratedCode> {\n    if no_std {\n        return Ok(GeneratedCode::default());\n    }\n\n    let log_formatters =\n        log_formatters_instantiation_code(quote! {contract_id.clone().into()}, &abi.logged_types);\n\n    let error_codes = generate_id_error_codes_pairs(abi.error_codes);\n    let error_codes = quote! {::std::collections::HashMap::from([#(#error_codes),*])};\n\n    let methods_name = ident(&format!(\"{name}Methods\"));\n    let contract_methods_name = ident(&format!(\"{name}MethodVariants\"));\n\n    let contract_functions = expand_functions(&abi.functions)?;\n    let constant_methods_code =\n        generate_constant_methods_pattern(&abi.functions, &contract_methods_name)?;\n\n    let configuration_struct_name = ident(&format!(\"{name}Configurables\"));\n    let constant_configuration_code =\n        generate_code_for_configurable_constants(&configuration_struct_name, &abi.configurables)?;\n\n    let code = quote! {\n        #[derive(Debug, Clone)]\n        pub struct #name<A = ()> {\n            contract_id: ::fuels::types::ContractId,\n            account: A,\n            log_decoder: ::fuels::core::codec::LogDecoder,\n            encoder_config: ::fuels::core::codec::EncoderConfig,\n        }\n\n        impl #name {\n            pub const METHODS: #contract_methods_name = #contract_methods_name;\n        }\n\n        impl<A> #name<A>\n        {\n            pub fn new(\n                contract_id: ::fuels::types::ContractId,\n                account: A,\n            ) -> Self {\n                let log_decoder = ::fuels::core::codec::LogDecoder::new(#log_formatters, #error_codes);\n                let encoder_config = ::fuels::core::codec::EncoderConfig::default();\n                Self { contract_id, account, log_decoder, encoder_config }\n            }\n\n            pub fn contract_id(&self) -> ::fuels::types::ContractId {\n                self.contract_id\n            }\n\n            pub fn account(&self) -> &A {\n                &self.account\n            }\n\n            pub fn with_account<U: ::fuels::accounts::Account>(self, account: U)\n            -> #name<U> {\n                #name {\n                        contract_id: self.contract_id,\n                        account,\n                        log_decoder: self.log_decoder,\n                        encoder_config: self.encoder_config\n                }\n            }\n\n            pub fn with_encoder_config(mut self, encoder_config: ::fuels::core::codec::EncoderConfig)\n            -> #name::<A> {\n                self.encoder_config = encoder_config;\n\n                self\n            }\n\n            pub async fn get_balances(&self) -> ::fuels::types::errors::Result<::std::collections::HashMap<::fuels::types::AssetId, u64>> where A: ::fuels::accounts::ViewOnlyAccount {\n                ::fuels::accounts::ViewOnlyAccount::try_provider(&self.account)?\n                                  .get_contract_balances(&self.contract_id)\n                                  .await\n                                  .map_err(::std::convert::Into::into)\n            }\n\n            pub fn methods(&self) -> #methods_name<A> where A: Clone {\n                #methods_name {\n                    contract_id: self.contract_id.clone(),\n                    account: self.account.clone(),\n                    log_decoder: self.log_decoder.clone(),\n                    encoder_config: self.encoder_config.clone(),\n                }\n            }\n        }\n\n        // Implement struct that holds the contract methods\n        pub struct #methods_name<A> {\n            contract_id: ::fuels::types::ContractId,\n            account: A,\n            log_decoder: ::fuels::core::codec::LogDecoder,\n            encoder_config: ::fuels::core::codec::EncoderConfig,\n        }\n\n        impl<A: ::fuels::accounts::Account + Clone> #methods_name<A> {\n            #contract_functions\n        }\n\n        impl<A>\n            ::fuels::programs::calls::ContractDependency for #name<A>\n        {\n            fn id(&self) -> ::fuels::types::ContractId {\n                self.contract_id\n            }\n\n            fn log_decoder(&self) -> ::fuels::core::codec::LogDecoder {\n                self.log_decoder.clone()\n            }\n        }\n\n        #constant_configuration_code\n\n        #constant_methods_code\n    };\n\n    // All publicly available types generated above should be listed here.\n    let type_paths = [\n        name,\n        &methods_name,\n        &configuration_struct_name,\n        &contract_methods_name,\n    ]\n    .map(|type_name| TypePath::new(type_name).expect(\"We know the given types are not empty\"))\n    .into_iter()\n    .collect();\n\n    Ok(GeneratedCode::new(code, type_paths, no_std))\n}\n\nfn expand_functions(functions: &[FullABIFunction]) -> Result<TokenStream> {\n    functions\n        .iter()\n        .map(expand_fn)\n        .fold_ok(TokenStream::default(), |mut all_code, code| {\n            all_code.append_all(code);\n            all_code\n        })\n}\n\n/// Transforms a function defined in [`FullABIFunction`] into a [`TokenStream`]\n/// that represents that same function signature as a Rust-native function\n/// declaration.\npub(crate) fn expand_fn(abi_fun: &FullABIFunction) -> Result<TokenStream> {\n    let mut generator = FunctionGenerator::new(abi_fun)?;\n\n    generator.set_docs(abi_fun.doc_strings()?);\n\n    let original_output = generator.output_type();\n    generator.set_output_type(\n        quote! {::fuels::programs::calls::CallHandler<A, ::fuels::programs::calls::ContractCall, #original_output> },\n    );\n\n    let fn_selector = generator.fn_selector();\n    let arg_tokens = generator.tokenized_args();\n    let is_payable = abi_fun.is_payable();\n    let body = quote! {\n            ::fuels::programs::calls::CallHandler::new_contract_call(\n                self.contract_id.clone(),\n                self.account.clone(),\n                #fn_selector,\n                &#arg_tokens,\n                self.log_decoder.clone(),\n                #is_payable,\n                self.encoder_config.clone(),\n            )\n    };\n    generator.set_body(body);\n\n    Ok(generator.generate())\n}\n\nfn generate_constant_methods_pattern(\n    functions: &[FullABIFunction],\n    contract_methods_name: &Ident,\n) -> Result<TokenStream> {\n    let method_descriptors = functions.iter().map(|func| {\n        let method_name = ident(func.name());\n        let fn_name = func.name();\n        let fn_selector =\n            proc_macro2::Literal::byte_string(&crate::utils::encode_fn_selector(fn_name));\n\n        quote! {\n            pub const fn #method_name(&self) -> ::fuels::types::MethodDescriptor {\n                ::fuels::types::MethodDescriptor {\n                    name: #fn_name,\n                    fn_selector: #fn_selector,\n                }\n            }\n        }\n    });\n\n    let all_methods = functions.iter().map(|func| {\n        let method_name = ident(func.name());\n        quote! { Self.#method_name() }\n    });\n\n    let method_count = functions.len();\n\n    let code = quote! {\n        #[derive(Debug, Clone, Copy)]\n        pub struct #contract_methods_name;\n\n        impl #contract_methods_name {\n            #(#method_descriptors)*\n\n            pub const fn iter(&self) -> [::fuels::types::MethodDescriptor; #method_count] {\n                [#(#all_methods),*]\n            }\n        }\n    };\n\n    Ok(code)\n}\n\n#[cfg(test)]\nmod tests {\n    use std::collections::HashMap;\n\n    use fuel_abi_types::abi::{\n        full_program::FullABIFunction,\n        program::Attribute,\n        unified_program::{UnifiedABIFunction, UnifiedTypeApplication, UnifiedTypeDeclaration},\n    };\n    use pretty_assertions::assert_eq;\n    use quote::quote;\n\n    use crate::{error::Result, program_bindings::abigen::bindings::contract::expand_fn};\n\n    #[test]\n    fn expand_contract_method_simple() -> Result<()> {\n        let the_function = UnifiedABIFunction {\n            inputs: vec![UnifiedTypeApplication {\n                name: String::from(\"bimbam\"),\n                type_id: 1,\n                ..Default::default()\n            }],\n            name: \"hello_world\".to_string(),\n            attributes: Some(vec![Attribute {\n                name: \"doc-comment\".to_string(),\n                arguments: vec![\"This is a doc string\".to_string()],\n            }]),\n            ..Default::default()\n        };\n        let types = [\n            (\n                0,\n                UnifiedTypeDeclaration {\n                    type_id: 0,\n                    type_field: String::from(\"()\"),\n                    ..Default::default()\n                },\n            ),\n            (\n                1,\n                UnifiedTypeDeclaration {\n                    type_id: 1,\n                    type_field: String::from(\"bool\"),\n                    ..Default::default()\n                },\n            ),\n        ]\n        .into_iter()\n        .collect::<HashMap<_, _>>();\n        let result = expand_fn(&FullABIFunction::from_counterpart(&the_function, &types)?);\n\n        let expected = quote! {\n            #[doc = \"This is a doc string\"]\n            pub fn hello_world(&self, bimbam: ::core::primitive::bool) -> ::fuels::programs::calls::CallHandler<A, ::fuels::programs::calls::ContractCall, ()> {\n                ::fuels::programs::calls::CallHandler::new_contract_call(\n                    self.contract_id.clone(),\n                    self.account.clone(),\n                    ::fuels::core::codec::encode_fn_selector(\"hello_world\"),\n                    &[::fuels::core::traits::Tokenizable::into_token(bimbam)],\n                    self.log_decoder.clone(),\n                    false,\n                    self.encoder_config.clone(),\n                )\n            }\n        };\n\n        assert_eq!(result?.to_string(), expected.to_string());\n\n        Ok(())\n    }\n\n    #[test]\n    fn expand_contract_method_complex() -> Result<()> {\n        // given\n        let the_function = UnifiedABIFunction {\n            inputs: vec![UnifiedTypeApplication {\n                name: String::from(\"the_only_allowed_input\"),\n                type_id: 4,\n                ..Default::default()\n            }],\n            name: \"hello_world\".to_string(),\n            output: UnifiedTypeApplication {\n                name: String::from(\"stillnotused\"),\n                type_id: 1,\n                ..Default::default()\n            },\n            attributes: Some(vec![\n                Attribute {\n                    name: \"doc-comment\".to_string(),\n                    arguments: vec![\"This is a doc string\".to_string()],\n                },\n                Attribute {\n                    name: \"doc-comment\".to_string(),\n                    arguments: vec![\"This is another doc string\".to_string()],\n                },\n            ]),\n        };\n        let types = [\n            (\n                1,\n                UnifiedTypeDeclaration {\n                    type_id: 1,\n                    type_field: String::from(\"enum EntropyCirclesEnum\"),\n                    components: Some(vec![\n                        UnifiedTypeApplication {\n                            name: String::from(\"Postcard\"),\n                            type_id: 2,\n                            ..Default::default()\n                        },\n                        UnifiedTypeApplication {\n                            name: String::from(\"Teacup\"),\n                            type_id: 3,\n                            ..Default::default()\n                        },\n                    ]),\n                    ..Default::default()\n                },\n            ),\n            (\n                2,\n                UnifiedTypeDeclaration {\n                    type_id: 2,\n                    type_field: String::from(\"bool\"),\n                    ..Default::default()\n                },\n            ),\n            (\n                3,\n                UnifiedTypeDeclaration {\n                    type_id: 3,\n                    type_field: String::from(\"u64\"),\n                    ..Default::default()\n                },\n            ),\n            (\n                4,\n                UnifiedTypeDeclaration {\n                    type_id: 4,\n                    type_field: String::from(\"struct SomeWeirdFrenchCuisine\"),\n                    components: Some(vec![\n                        UnifiedTypeApplication {\n                            name: String::from(\"Beef\"),\n                            type_id: 2,\n                            ..Default::default()\n                        },\n                        UnifiedTypeApplication {\n                            name: String::from(\"BurgundyWine\"),\n                            type_id: 3,\n                            ..Default::default()\n                        },\n                    ]),\n                    ..Default::default()\n                },\n            ),\n        ]\n        .into_iter()\n        .collect::<HashMap<_, _>>();\n\n        // when\n        let result = expand_fn(&FullABIFunction::from_counterpart(&the_function, &types)?);\n\n        // then\n\n        // Some more editing was required because it is not rustfmt-compatible (adding/removing parentheses or commas)\n        let expected = quote! {\n            #[doc = \"This is a doc string\"]\n            #[doc = \"This is another doc string\"]\n            pub fn hello_world(\n                &self,\n                the_only_allowed_input: self::SomeWeirdFrenchCuisine\n            ) -> ::fuels::programs::calls::CallHandler<A, ::fuels::programs::calls::ContractCall, self::EntropyCirclesEnum> {\n                ::fuels::programs::calls::CallHandler::new_contract_call(\n                    self.contract_id.clone(),\n                    self.account.clone(),\n                    ::fuels::core::codec::encode_fn_selector( \"hello_world\"),\n                    &[::fuels::core::traits::Tokenizable::into_token(\n                        the_only_allowed_input\n                    )],\n                    self.log_decoder.clone(),\n                    false,\n                    self.encoder_config.clone(),\n                )\n            }\n        };\n\n        assert_eq!(result?.to_string(), expected.to_string());\n\n        Ok(())\n    }\n}\n"
  },
  {
    "path": "packages/fuels-code-gen/src/program_bindings/abigen/bindings/function_generator.rs",
    "content": "use fuel_abi_types::abi::full_program::FullABIFunction;\nuse proc_macro2::TokenStream;\nuse quote::{ToTokens, quote};\n\nuse crate::{\n    error::Result,\n    program_bindings::{\n        resolved_type::TypeResolver,\n        utils::{Component, Components},\n    },\n    utils::{TypePath, safe_ident},\n};\n\n#[derive(Debug)]\npub(crate) struct FunctionGenerator {\n    name: String,\n    args: Components,\n    output_type: TokenStream,\n    body: TokenStream,\n    docs: Vec<String>,\n}\n\nimpl FunctionGenerator {\n    pub fn new(fun: &FullABIFunction) -> Result<Self> {\n        // All abi-method-calling Rust functions are currently generated at the top-level-mod of\n        // the Program in question (e.g. abigen_bindings::my_contract_mod`). If we ever nest\n        // these functions in a deeper mod we would need to propagate the mod to here instead of\n        // just hard-coding the default path.\n        let args = Components::new(fun.inputs(), true, TypePath::default())?;\n\n        // We are not checking that the ABI contains non-SDK supported types so that the user can\n        // still interact with an ABI even if some methods will fail at runtime.\n        let output_type = TypeResolver::default().resolve(fun.output())?;\n        Ok(Self {\n            name: fun.name().to_string(),\n            args,\n            output_type: output_type.to_token_stream(),\n            body: Default::default(),\n            docs: vec![],\n        })\n    }\n\n    pub fn set_name(&mut self, name: String) -> &mut Self {\n        self.name = name;\n        self\n    }\n\n    pub fn set_body(&mut self, body: TokenStream) -> &mut Self {\n        self.body = body;\n        self\n    }\n\n    pub fn set_docs(&mut self, docs: Vec<String>) -> &mut Self {\n        self.docs = docs;\n        self\n    }\n\n    pub fn fn_selector(&self) -> TokenStream {\n        let name = &self.name;\n        quote! {::fuels::core::codec::encode_fn_selector(#name)}\n    }\n\n    pub fn tokenized_args(&self) -> TokenStream {\n        let arg_names = self.args.iter().map(|Component { ident, .. }| {\n            quote! {#ident}\n        });\n\n        quote! {[#(::fuels::core::traits::Tokenizable::into_token(#arg_names)),*]}\n    }\n\n    pub fn set_output_type(&mut self, output_type: TokenStream) -> &mut Self {\n        self.output_type = output_type;\n        self\n    }\n\n    pub fn output_type(&self) -> &TokenStream {\n        &self.output_type\n    }\n\n    pub fn generate(&self) -> TokenStream {\n        let name = safe_ident(&self.name);\n        let docs: Vec<TokenStream> = self\n            .docs\n            .iter()\n            .map(|doc| {\n                quote! { #[doc = #doc] }\n            })\n            .collect();\n\n        let arg_declarations = self.args.iter().map(\n            |Component {\n                 ident,\n                 resolved_type,\n                 ..\n             }| {\n                quote! { #ident: #resolved_type }\n            },\n        );\n\n        let output_type = self.output_type();\n        let body = &self.body;\n\n        let params = quote! { &self, #(#arg_declarations),* };\n\n        quote! {\n            #(#docs)*\n            pub fn #name(#params) -> #output_type {\n                #body\n            }\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use fuel_abi_types::abi::full_program::{FullTypeApplication, FullTypeDeclaration};\n    use pretty_assertions::assert_eq;\n\n    use super::*;\n\n    #[test]\n    fn correct_fn_selector_resolving_code() -> Result<()> {\n        let function = given_a_fun();\n        let sut = FunctionGenerator::new(&function)?;\n\n        let fn_selector_code = sut.fn_selector();\n\n        let expected = quote! {\n            ::fuels::core::codec::encode_fn_selector(\"test_function\")\n        };\n        assert_eq!(fn_selector_code.to_string(), expected.to_string());\n\n        Ok(())\n    }\n\n    #[test]\n    fn correct_tokenized_args() -> Result<()> {\n        let function = given_a_fun();\n        let sut = FunctionGenerator::new(&function)?;\n\n        let tokenized_args = sut.tokenized_args();\n\n        assert_eq!(\n            tokenized_args.to_string(),\n            \"[:: fuels :: core :: traits :: Tokenizable :: into_token (arg_0)]\"\n        );\n\n        Ok(())\n    }\n\n    #[test]\n    fn tokenizes_correctly() -> Result<()> {\n        // given\n        let function = given_a_fun();\n        let mut sut = FunctionGenerator::new(&function)?;\n\n        sut.set_docs(vec![\n            \" This is a doc\".to_string(),\n            \" This is another doc\".to_string(),\n        ])\n        .set_body(quote! {this is ze body});\n\n        // when\n        let tokenized: TokenStream = sut.generate();\n\n        // then\n        let expected = quote! {\n            #[doc = \" This is a doc\"]\n            #[doc = \" This is another doc\"]\n            pub fn test_function(&self, arg_0: self::CustomStruct<::core::primitive::u8>) -> self::CustomStruct<::core::primitive::u64> {\n                this is ze body\n            }\n        };\n\n        // then\n        assert_eq!(tokenized.to_string(), expected.to_string());\n\n        Ok(())\n    }\n\n    fn given_a_fun() -> FullABIFunction {\n        let generic_type_t = FullTypeDeclaration {\n            type_field: \"generic T\".to_string(),\n            components: vec![],\n            type_parameters: vec![],\n            alias_of: None,\n        };\n        let custom_struct_type = FullTypeDeclaration {\n            type_field: \"struct CustomStruct\".to_string(),\n            components: vec![FullTypeApplication {\n                name: \"field_a\".to_string(),\n                type_decl: generic_type_t.clone(),\n                type_arguments: vec![],\n                error_message: None,\n            }],\n            type_parameters: vec![generic_type_t],\n            alias_of: None,\n        };\n\n        let fn_output = FullTypeApplication {\n            name: \"\".to_string(),\n            type_decl: custom_struct_type.clone(),\n            type_arguments: vec![FullTypeApplication {\n                name: \"\".to_string(),\n                type_decl: FullTypeDeclaration {\n                    type_field: \"u64\".to_string(),\n                    components: vec![],\n                    type_parameters: vec![],\n                    alias_of: None,\n                },\n                type_arguments: vec![],\n                error_message: None,\n            }],\n            error_message: None,\n        };\n        let fn_inputs = vec![FullTypeApplication {\n            name: \"arg_0\".to_string(),\n            type_decl: custom_struct_type,\n            type_arguments: vec![FullTypeApplication {\n                name: \"\".to_string(),\n                type_decl: FullTypeDeclaration {\n                    type_field: \"u8\".to_string(),\n                    components: vec![],\n                    type_parameters: vec![],\n                    alias_of: None,\n                },\n                type_arguments: vec![],\n                error_message: None,\n            }],\n            error_message: None,\n        }];\n\n        FullABIFunction::new(\"test_function\".to_string(), fn_inputs, fn_output, vec![])\n            .expect(\"Hand crafted function known to be correct\")\n    }\n}\n"
  },
  {
    "path": "packages/fuels-code-gen/src/program_bindings/abigen/bindings/predicate.rs",
    "content": "use fuel_abi_types::abi::full_program::{FullABIFunction, FullProgramABI};\nuse proc_macro2::{Ident, TokenStream};\nuse quote::quote;\n\nuse crate::{\n    error::Result,\n    program_bindings::{\n        abigen::{\n            bindings::{function_generator::FunctionGenerator, utils::extract_main_fn},\n            configurables::generate_code_for_configurable_constants,\n        },\n        generated_code::GeneratedCode,\n    },\n    utils::{TypePath, ident},\n};\n\npub(crate) fn predicate_bindings(\n    name: &Ident,\n    abi: FullProgramABI,\n    no_std: bool,\n) -> Result<GeneratedCode> {\n    let main_function_abi = extract_main_fn(&abi.functions)?;\n    let encode_function = expand_fn(main_function_abi)?;\n    let encoder_struct_name = ident(&format!(\"{name}Encoder\"));\n\n    let configuration_struct_name = ident(&format!(\"{name}Configurables\"));\n    let constant_configuration_code =\n        generate_code_for_configurable_constants(&configuration_struct_name, &abi.configurables)?;\n\n    let code = quote! {\n        #[derive(Default)]\n        pub struct #encoder_struct_name{\n            encoder: ::fuels::core::codec::ABIEncoder,\n        }\n\n        impl #encoder_struct_name {\n           #encode_function\n\n            pub fn new(encoder_config: ::fuels::core::codec::EncoderConfig) -> Self {\n                Self {\n                    encoder: ::fuels::core::codec::ABIEncoder::new(encoder_config)\n                }\n            }\n        }\n\n        #constant_configuration_code\n    };\n    // All publicly available types generated above should be listed here.\n    let type_paths = [&encoder_struct_name, &configuration_struct_name]\n        .map(|type_name| TypePath::new(type_name).expect(\"We know the given types are not empty\"))\n        .into_iter()\n        .collect();\n\n    Ok(GeneratedCode::new(code, type_paths, no_std))\n}\n\nfn expand_fn(fn_abi: &FullABIFunction) -> Result<TokenStream> {\n    let mut generator = FunctionGenerator::new(fn_abi)?;\n\n    let arg_tokens = generator.tokenized_args();\n    let body = quote! {\n        self.encoder.encode(&#arg_tokens)\n    };\n    let output_type = quote! {\n        ::fuels::types::errors::Result<::std::vec::Vec<u8>>\n    };\n\n    generator\n        .set_docs(vec![\"Encode the predicate arguments\".to_string()])\n        .set_name(\"encode_data\".to_string())\n        .set_output_type(output_type)\n        .set_body(body);\n\n    Ok(generator.generate())\n}\n"
  },
  {
    "path": "packages/fuels-code-gen/src/program_bindings/abigen/bindings/script.rs",
    "content": "use std::default::Default;\n\nuse fuel_abi_types::abi::full_program::{FullABIFunction, FullProgramABI};\nuse proc_macro2::{Ident, TokenStream};\nuse quote::quote;\n\nuse crate::{\n    error::Result,\n    program_bindings::{\n        abigen::{\n            bindings::{function_generator::FunctionGenerator, utils::extract_main_fn},\n            configurables::generate_code_for_configurable_constants,\n            logs::{generate_id_error_codes_pairs, log_formatters_instantiation_code},\n        },\n        generated_code::GeneratedCode,\n    },\n    utils::{TypePath, ident},\n};\n\npub(crate) fn script_bindings(\n    name: &Ident,\n    abi: FullProgramABI,\n    no_std: bool,\n) -> Result<GeneratedCode> {\n    if no_std {\n        return Ok(GeneratedCode::default());\n    }\n\n    let main_function_abi = extract_main_fn(&abi.functions)?;\n    let main_function = expand_fn(main_function_abi)?;\n\n    let log_formatters = log_formatters_instantiation_code(\n        quote! {::fuels::types::ContractId::zeroed()},\n        &abi.logged_types,\n    );\n\n    let error_codes = generate_id_error_codes_pairs(abi.error_codes);\n    let error_codes = quote! {vec![#(#error_codes),*].into_iter().collect()};\n\n    let configuration_struct_name = ident(&format!(\"{name}Configurables\"));\n    let constant_configuration_code =\n        generate_code_for_configurable_constants(&configuration_struct_name, &abi.configurables)?;\n\n    let code = quote! {\n        #[derive(Debug,Clone)]\n        pub struct #name<A>{\n            account: A,\n            unconfigured_binary: ::std::vec::Vec<u8>,\n            configurables: ::fuels::core::Configurables,\n            converted_into_loader: bool,\n            log_decoder: ::fuels::core::codec::LogDecoder,\n            encoder_config: ::fuels::core::codec::EncoderConfig,\n        }\n\n        impl<A> #name<A>\n        {\n            pub fn new(account: A, binary_filepath: &str) -> Self {\n                let binary = ::std::fs::read(binary_filepath)\n                                            .expect(&format!(\"could not read script binary {binary_filepath:?}\"));\n                Self {\n                    account,\n                    unconfigured_binary: binary,\n                    configurables: ::core::default::Default::default(),\n                    converted_into_loader: false,\n                    log_decoder: ::fuels::core::codec::LogDecoder::new(#log_formatters, #error_codes),\n                    encoder_config: ::fuels::core::codec::EncoderConfig::default(),\n                }\n            }\n\n            pub fn with_account<U>(self, account: U) -> #name<U> {\n                    #name {\n                        account,\n                        unconfigured_binary: self.unconfigured_binary,\n                        log_decoder: self.log_decoder,\n                        encoder_config: self.encoder_config,\n                        configurables: self.configurables,\n                        converted_into_loader: self.converted_into_loader,\n                    }\n            }\n\n            pub fn with_configurables(mut self, configurables: impl Into<::fuels::core::Configurables>)\n                -> Self\n            {\n                self.configurables = configurables.into();\n                self\n            }\n\n            pub fn code(&self) -> ::std::vec::Vec<u8> {\n                let regular = ::fuels::programs::executable::Executable::from_bytes(self.unconfigured_binary.clone()).with_configurables(self.configurables.clone());\n\n                if self.converted_into_loader {\n                    let loader = regular.convert_to_loader().expect(\"cannot fail since we already converted to the loader successfully\");\n                    loader.code()\n                } else {\n                    regular.code()\n                }\n            }\n\n            pub fn account(&self) -> &A {\n                &self.account\n            }\n\n            pub fn with_encoder_config(mut self, encoder_config: ::fuels::core::codec::EncoderConfig)\n                -> Self\n            {\n                self.encoder_config = encoder_config;\n\n                self\n            }\n\n            pub fn log_decoder(&self) -> ::fuels::core::codec::LogDecoder {\n                self.log_decoder.clone()\n            }\n\n            /// Will upload the script code as a blob to the network and change the script code\n            /// into a loader that will fetch the blob and load it into memory before executing the\n            /// code inside. Allows you to optimize fees by paying for most of the code once and\n            /// then just running a small loader.\n            pub async fn convert_into_loader(&mut self) -> ::fuels::types::errors::Result<&mut Self> where A: ::fuels::accounts::Account + Clone {\n                if !self.converted_into_loader {\n                    let regular = ::fuels::programs::executable::Executable::from_bytes(self.unconfigured_binary.clone()).with_configurables(self.configurables.clone());\n                    let loader = regular.convert_to_loader()?;\n\n                    loader.upload_blob(self.account.clone()).await?;\n\n                    self.converted_into_loader = true;\n                }\n                ::fuels::types::errors::Result::Ok(self)\n\n            }\n\n        }\n        impl<A: ::fuels::accounts::Account + Clone> #name<A> {\n            #main_function\n        }\n\n        #constant_configuration_code\n    };\n\n    // All publicly available types generated above should be listed here.\n    let type_paths = [name, &configuration_struct_name]\n        .map(|type_name| TypePath::new(type_name).expect(\"We know the given types are not empty\"))\n        .into_iter()\n        .collect();\n\n    Ok(GeneratedCode::new(code, type_paths, no_std))\n}\n\nfn expand_fn(fn_abi: &FullABIFunction) -> Result<TokenStream> {\n    let mut generator = FunctionGenerator::new(fn_abi)?;\n\n    let arg_tokens = generator.tokenized_args();\n    let original_output_type = generator.output_type();\n    let body = quote! {\n            let encoded_args = ::fuels::core::codec::ABIEncoder::new(self.encoder_config).encode(&#arg_tokens);\n\n            ::fuels::programs::calls::CallHandler::new_script_call(\n                self.code(),\n                encoded_args,\n                self.account.clone(),\n                self.log_decoder.clone()\n            )\n    };\n\n    generator\n        .set_output_type(quote! {::fuels::programs::calls::CallHandler<A, ::fuels::programs::calls::ScriptCall, #original_output_type> })\n        .set_docs(fn_abi.doc_strings()?)\n        .set_body(body);\n\n    Ok(generator.generate())\n}\n\n#[cfg(test)]\nmod tests {\n    use std::collections::HashMap;\n\n    use fuel_abi_types::abi::{\n        full_program::FullABIFunction,\n        program::Attribute,\n        unified_program::{UnifiedABIFunction, UnifiedTypeApplication, UnifiedTypeDeclaration},\n    };\n    use pretty_assertions::assert_eq;\n    use quote::quote;\n\n    use crate::{error::Result, program_bindings::abigen::bindings::script::expand_fn};\n\n    #[test]\n    fn expand_script_main_function() -> Result<()> {\n        let the_function = UnifiedABIFunction {\n            inputs: vec![UnifiedTypeApplication {\n                name: String::from(\"bimbam\"),\n                type_id: 1,\n                ..Default::default()\n            }],\n            name: \"main\".to_string(),\n            attributes: Some(vec![\n                Attribute {\n                    name: \"doc-comment\".to_string(),\n                    arguments: vec![\"This is a doc string\".to_string()],\n                },\n                Attribute {\n                    name: \"doc-comment\".to_string(),\n                    arguments: vec![\"This is another doc string\".to_string()],\n                },\n            ]),\n            ..Default::default()\n        };\n        let types = [\n            (\n                0,\n                UnifiedTypeDeclaration {\n                    type_id: 0,\n                    type_field: String::from(\"()\"),\n                    ..Default::default()\n                },\n            ),\n            (\n                1,\n                UnifiedTypeDeclaration {\n                    type_id: 1,\n                    type_field: String::from(\"bool\"),\n                    ..Default::default()\n                },\n            ),\n        ]\n        .into_iter()\n        .collect::<HashMap<_, _>>();\n        let result = expand_fn(&FullABIFunction::from_counterpart(&the_function, &types)?);\n\n        let expected = quote! {\n            #[doc = \"This is a doc string\"]\n            #[doc = \"This is another doc string\"]\n            pub fn main(&self, bimbam: ::core::primitive::bool) -> ::fuels::programs::calls::CallHandler<A, ::fuels::programs::calls::ScriptCall, ()> {\n                let encoded_args=::fuels::core::codec::ABIEncoder::new(self.encoder_config)\n                    .encode(&[::fuels::core::traits::Tokenizable::into_token(bimbam)]);\n                 ::fuels::programs::calls::CallHandler::new_script_call(\n                    self.code(),\n                    encoded_args,\n                    self.account.clone(),\n                    self.log_decoder.clone()\n                )\n            }\n        };\n\n        assert_eq!(result?.to_string(), expected.to_string());\n\n        Ok(())\n    }\n}\n"
  },
  {
    "path": "packages/fuels-code-gen/src/program_bindings/abigen/bindings/utils.rs",
    "content": "use fuel_abi_types::abi::full_program::FullABIFunction;\n\nuse crate::error::{Result, error};\n\npub(crate) fn extract_main_fn(abi: &[FullABIFunction]) -> Result<&FullABIFunction> {\n    let candidates = abi\n        .iter()\n        .filter(|function| function.name() == \"main\")\n        .collect::<Vec<_>>();\n\n    match candidates.as_slice() {\n        [single_main_fn] => Ok(single_main_fn),\n        _ => {\n            let fn_names = abi\n                .iter()\n                .map(|candidate| candidate.name())\n                .collect::<Vec<_>>();\n            Err(error!(\n                \"`abi` must have only one function with the name 'main'. Got: {fn_names:?}\"\n            ))\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use fuel_abi_types::abi::full_program::{FullTypeApplication, FullTypeDeclaration};\n\n    use super::*;\n\n    #[test]\n    fn correctly_extracts_the_main_fn() {\n        let functions = [\"fn_1\", \"main\", \"fn_2\"].map(given_a_fun_named);\n\n        let fun = extract_main_fn(&functions).expect(\"should have succeeded\");\n\n        assert_eq!(*fun, functions[1]);\n    }\n\n    #[test]\n    fn fails_if_there_is_more_than_one_main_fn() {\n        let functions = [\"main\", \"another\", \"main\"].map(given_a_fun_named);\n\n        let err = extract_main_fn(&functions).expect_err(\"should have failed\");\n\n        assert_eq!(\n            err.to_string(),\n            r#\"`abi` must have only one function with the name 'main'. Got: [\"main\", \"another\", \"main\"]\"#\n        );\n    }\n\n    fn given_a_fun_named(fn_name: &str) -> FullABIFunction {\n        FullABIFunction::new(\n            fn_name.to_string(),\n            vec![],\n            FullTypeApplication {\n                name: \"\".to_string(),\n                type_decl: FullTypeDeclaration {\n                    type_field: \"\".to_string(),\n                    components: vec![],\n                    type_parameters: vec![],\n                    alias_of: None,\n                },\n                type_arguments: vec![],\n                error_message: None,\n            },\n            vec![],\n        )\n        .expect(\"hand-crafted, should not fail!\")\n    }\n}\n"
  },
  {
    "path": "packages/fuels-code-gen/src/program_bindings/abigen/bindings.rs",
    "content": "use crate::{\n    error::Result,\n    program_bindings::{\n        abigen::{\n            ProgramType,\n            abigen_target::AbigenTarget,\n            bindings::{\n                contract::contract_bindings, predicate::predicate_bindings, script::script_bindings,\n            },\n        },\n        generated_code::GeneratedCode,\n    },\n    utils::ident,\n};\n\nmod contract;\nmod function_generator;\nmod predicate;\nmod script;\nmod utils;\n\npub(crate) fn generate_bindings(target: AbigenTarget, no_std: bool) -> Result<GeneratedCode> {\n    let bindings_generator = match target.program_type {\n        ProgramType::Script => script_bindings,\n        ProgramType::Contract => contract_bindings,\n        ProgramType::Predicate => predicate_bindings,\n    };\n\n    let name = ident(&target.name);\n    let abi = target.source.abi;\n    bindings_generator(&name, abi, no_std)\n}\n"
  },
  {
    "path": "packages/fuels-code-gen/src/program_bindings/abigen/configurables.rs",
    "content": "use fuel_abi_types::abi::full_program::FullConfigurable;\nuse proc_macro2::{Ident, TokenStream};\nuse quote::quote;\n\nuse crate::{\n    error::Result,\n    program_bindings::resolved_type::{ResolvedType, TypeResolver},\n    utils::safe_ident,\n};\n\n#[derive(Debug)]\npub(crate) struct ResolvedConfigurable {\n    pub name: Ident,\n    pub ttype: ResolvedType,\n    pub offset: u64,\n}\n\nimpl ResolvedConfigurable {\n    pub fn new(configurable: &FullConfigurable) -> Result<ResolvedConfigurable> {\n        let type_application = &configurable.application;\n        Ok(ResolvedConfigurable {\n            name: safe_ident(&format!(\"with_{}\", configurable.name)),\n            ttype: TypeResolver::default().resolve(type_application)?,\n            offset: configurable.offset,\n        })\n    }\n}\n\npub(crate) fn generate_code_for_configurable_constants(\n    configurable_struct_name: &Ident,\n    configurables: &[FullConfigurable],\n) -> Result<TokenStream> {\n    let resolved_configurables = configurables\n        .iter()\n        .map(ResolvedConfigurable::new)\n        .collect::<Result<Vec<_>>>()?;\n\n    let struct_decl = generate_struct_decl(configurable_struct_name);\n    let struct_impl = generate_struct_impl(configurable_struct_name, &resolved_configurables);\n    let from_impl = generate_from_impl(configurable_struct_name);\n\n    Ok(quote! {\n        #struct_decl\n        #struct_impl\n        #from_impl\n    })\n}\n\nfn generate_struct_decl(configurable_struct_name: &Ident) -> TokenStream {\n    quote! {\n        #[derive(Clone, Debug, Default)]\n        pub struct #configurable_struct_name {\n            offsets_with_data: ::std::vec::Vec<::fuels::core::Configurable>,\n            encoder: ::fuels::core::codec::ABIEncoder,\n        }\n    }\n}\n\nfn generate_struct_impl(\n    configurable_struct_name: &Ident,\n    resolved_configurables: &[ResolvedConfigurable],\n) -> TokenStream {\n    let builder_methods = generate_builder_methods(resolved_configurables);\n\n    quote! {\n        impl #configurable_struct_name {\n            pub fn new(encoder_config: ::fuels::core::codec::EncoderConfig) -> Self {\n                Self {\n                    encoder: ::fuels::core::codec::ABIEncoder::new(encoder_config),\n                    ..::std::default::Default::default()\n                }\n            }\n\n            #builder_methods\n        }\n    }\n}\n\nfn generate_builder_methods(resolved_configurables: &[ResolvedConfigurable]) -> TokenStream {\n    let methods = resolved_configurables.iter().map(\n        |ResolvedConfigurable {\n             name,\n             ttype,\n             offset,\n         }| {\n            let encoder_code = generate_encoder_code(ttype);\n            quote! {\n                #[allow(non_snake_case)]\n                // Generate the `with_XXX` methods for setting the configurables\n                pub fn #name(mut self, value: #ttype) -> ::fuels::prelude::Result<Self> {\n                    let encoded = #encoder_code?;\n                    self.offsets_with_data.push(::fuels::core::Configurable {\n                        offset: #offset,\n                        data: encoded,\n                    });\n                    ::fuels::prelude::Result::Ok(self)\n                }\n            }\n        },\n    );\n\n    quote! {\n        #(#methods)*\n    }\n}\n\nfn generate_encoder_code(ttype: &ResolvedType) -> TokenStream {\n    quote! {\n        self.encoder.encode(&[\n                <#ttype as ::fuels::core::traits::Tokenizable>::into_token(value)\n            ])\n    }\n}\n\nfn generate_from_impl(configurable_struct_name: &Ident) -> TokenStream {\n    quote! {\n        impl From<#configurable_struct_name> for ::fuels::core::Configurables {\n            fn from(config: #configurable_struct_name) -> Self {\n                ::fuels::core::Configurables::new(config.offsets_with_data)\n            }\n        }\n        impl From<#configurable_struct_name> for ::std::vec::Vec<::fuels::core::Configurable> {\n            fn from(config: #configurable_struct_name) -> ::std::vec::Vec<::fuels::core::Configurable> {\n                config.offsets_with_data\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "packages/fuels-code-gen/src/program_bindings/abigen/logs.rs",
    "content": "use fuel_abi_types::abi::full_program::FullLoggedType;\nuse proc_macro2::TokenStream;\nuse quote::quote;\n\nuse crate::program_bindings::resolved_type::TypeResolver;\n\npub(crate) fn log_formatters_instantiation_code(\n    contract_id: TokenStream,\n    logged_types: &[FullLoggedType],\n) -> TokenStream {\n    let resolved_logs = resolve_logs(logged_types);\n    let log_id_log_formatter_pairs = generate_log_id_log_formatter_pairs(&resolved_logs);\n    quote! {::fuels::core::codec::log_formatters_lookup(vec![#(#log_id_log_formatter_pairs),*], #contract_id)}\n}\n\n#[derive(Debug)]\nstruct ResolvedLog {\n    log_id: String,\n    log_formatter: TokenStream,\n}\n\n/// Reads the parsed logged types from the ABI and creates ResolvedLogs\nfn resolve_logs(logged_types: &[FullLoggedType]) -> Vec<ResolvedLog> {\n    logged_types\n        .iter()\n        .map(|l| {\n            let resolved_type = TypeResolver::default()\n                .resolve(&l.application)\n                .expect(\"Failed to resolve log type\");\n\n            let is_error_type = l\n                .application\n                .type_decl\n                .components\n                .iter()\n                .any(|component| component.error_message.is_some());\n\n            let log_formatter = if is_error_type {\n                quote! {\n                    ::fuels::core::codec::LogFormatter::new_error::<#resolved_type>()\n                }\n            } else {\n                quote! {\n                    ::fuels::core::codec::LogFormatter::new_log::<#resolved_type>()\n                }\n            };\n\n            ResolvedLog {\n                log_id: l.log_id.clone(),\n                log_formatter,\n            }\n        })\n        .collect()\n}\n\nfn generate_log_id_log_formatter_pairs(\n    resolved_logs: &[ResolvedLog],\n) -> impl Iterator<Item = TokenStream> {\n    resolved_logs.iter().map(|r| {\n        let id = &r.log_id;\n        let log_formatter = &r.log_formatter;\n\n        quote! {\n            (#id.to_string(), #log_formatter)\n        }\n    })\n}\n\npub(crate) fn generate_id_error_codes_pairs(\n    error_codes: impl IntoIterator<Item = (u64, fuel_abi_types::abi::program::ErrorDetails)>,\n) -> impl Iterator<Item = TokenStream> {\n    error_codes.into_iter().map(|(id, ed)| {\n        let pkg = ed.pos.pkg;\n        let file = ed.pos.file;\n        let line = ed.pos.line;\n        let column = ed.pos.column;\n\n        let log_id = ed.log_id.map_or(\n            quote! {::core::option::Option::None},\n            |l| quote! {::core::option::Option::Some(#l.to_string())},\n        );\n        let msg = ed.msg.map_or(\n            quote! {::core::option::Option::None},\n            |m| quote! {::core::option::Option::Some(#m.to_string())},\n        );\n\n        quote! {\n            (#id,\n             ::fuels::core::codec::ErrorDetails::new(\n                    #pkg.to_string(), #file.to_string(), #line, #column, #log_id, #msg\n                )\n             )\n        }\n    })\n}\n"
  },
  {
    "path": "packages/fuels-code-gen/src/program_bindings/abigen.rs",
    "content": "use std::{collections::HashSet, path::PathBuf};\n\npub use abigen_target::{Abi, AbigenTarget, ProgramType};\nuse fuel_abi_types::abi::full_program::{FullLoggedType, FullTypeDeclaration};\nuse inflector::Inflector;\nuse itertools::Itertools;\nuse proc_macro2::TokenStream;\nuse quote::quote;\nuse regex::Regex;\n\nuse crate::{\n    error::Result,\n    program_bindings::{\n        abigen::bindings::generate_bindings, custom_types::generate_types,\n        generated_code::GeneratedCode,\n    },\n    utils::ident,\n};\n\nmod abigen_target;\nmod bindings;\nmod configurables;\nmod logs;\n\npub struct Abigen;\n\nimpl Abigen {\n    /// Generate code which can be used to interact with the underlying\n    /// contract, script or predicate in a type-safe manner.\n    ///\n    /// # Arguments\n    ///\n    /// * `targets`: `AbigenTargets` detailing which ABI to generate bindings\n    ///   for, and of what nature (Contract, Script or Predicate).\n    /// * `no_std`: don't use the Rust std library.\n    pub fn generate(targets: Vec<AbigenTarget>, no_std: bool) -> Result<TokenStream> {\n        let generated_code = Self::generate_code(no_std, targets)?;\n\n        let use_statements = generated_code.use_statements_for_uniquely_named_types();\n\n        let code = if no_std {\n            Self::wasm_paths_hotfix(&generated_code.code())\n        } else {\n            generated_code.code()\n        };\n\n        Ok(quote! {\n            #code\n            #use_statements\n        })\n    }\n    fn wasm_paths_hotfix(code: &TokenStream) -> TokenStream {\n        [\n            (r\"::\\s*std\\s*::\\s*string\", \"::alloc::string\"),\n            (r\"::\\s*std\\s*::\\s*format\", \"::alloc::format\"),\n            (r\"::\\s*std\\s*::\\s*vec\", \"::alloc::vec\"),\n            (r\"::\\s*std\\s*::\\s*boxed\", \"::alloc::boxed\"),\n        ]\n        .map(|(reg_expr_str, substitute)| (Regex::new(reg_expr_str).unwrap(), substitute))\n        .into_iter()\n        .fold(code.to_string(), |code, (regex, wasm_include)| {\n            regex.replace_all(&code, wasm_include).to_string()\n        })\n        .parse()\n        .expect(\"Wasm hotfix failed!\")\n    }\n\n    fn generate_code(no_std: bool, parsed_targets: Vec<AbigenTarget>) -> Result<GeneratedCode> {\n        let custom_types = Self::filter_custom_types(&parsed_targets);\n        let shared_types = Self::filter_shared_types(custom_types);\n\n        let logged_types = parsed_targets\n            .iter()\n            .flat_map(|abi| abi.source.abi.logged_types.clone())\n            .collect_vec();\n        let bindings = Self::generate_all_bindings(parsed_targets, no_std, &shared_types)?;\n\n        let shared_types = Self::generate_shared_types(shared_types, &logged_types, no_std)?;\n\n        let mod_name = ident(\"abigen_bindings\");\n        Ok(shared_types.merge(bindings).wrap_in_mod(mod_name))\n    }\n\n    fn generate_all_bindings(\n        targets: Vec<AbigenTarget>,\n        no_std: bool,\n        shared_types: &HashSet<FullTypeDeclaration>,\n    ) -> Result<GeneratedCode> {\n        targets\n            .into_iter()\n            .map(|target| Self::generate_binding(target, no_std, shared_types))\n            .fold_ok(GeneratedCode::default(), |acc, generated_code| {\n                acc.merge(generated_code)\n            })\n    }\n\n    fn generate_binding(\n        target: AbigenTarget,\n        no_std: bool,\n        shared_types: &HashSet<FullTypeDeclaration>,\n    ) -> Result<GeneratedCode> {\n        let mod_name = ident(&format!(\"{}_mod\", &target.name.to_snake_case()));\n\n        let recompile_trigger =\n            Self::generate_macro_recompile_trigger(target.source.path.as_ref(), no_std);\n        let types = generate_types(\n            &target.source.abi.types,\n            shared_types,\n            &target.source.abi.logged_types,\n            no_std,\n        )?;\n        let bindings = generate_bindings(target, no_std)?;\n        Ok(recompile_trigger\n            .merge(types)\n            .merge(bindings)\n            .wrap_in_mod(mod_name))\n    }\n\n    /// Any changes to the file pointed to by `path` will cause the reevaluation of the current\n    /// procedural macro. This is a hack until <https://github.com/rust-lang/rust/issues/99515>\n    /// lands.\n    fn generate_macro_recompile_trigger(path: Option<&PathBuf>, no_std: bool) -> GeneratedCode {\n        let code = path\n            .as_ref()\n            .map(|path| {\n                let stringified_path = path.display().to_string();\n                quote! {\n                    const _: &[u8] = include_bytes!(#stringified_path);\n                }\n            })\n            .unwrap_or_default();\n        GeneratedCode::new(code, Default::default(), no_std)\n    }\n\n    fn generate_shared_types(\n        shared_types: HashSet<FullTypeDeclaration>,\n        logged_types: &Vec<FullLoggedType>,\n        no_std: bool,\n    ) -> Result<GeneratedCode> {\n        let types = generate_types(&shared_types, &HashSet::default(), logged_types, no_std)?;\n\n        if types.is_empty() {\n            Ok(Default::default())\n        } else {\n            let mod_name = ident(\"shared_types\");\n            Ok(types.wrap_in_mod(mod_name))\n        }\n    }\n\n    fn filter_custom_types(\n        all_types: &[AbigenTarget],\n    ) -> impl Iterator<Item = &FullTypeDeclaration> {\n        all_types\n            .iter()\n            .flat_map(|target| &target.source.abi.types)\n            .filter(|ttype| ttype.is_custom_type())\n    }\n\n    /// A type is considered \"shared\" if it appears at least twice in\n    /// `all_custom_types`.\n    ///\n    /// # Arguments\n    ///\n    /// * `all_custom_types`: types from all ABIs whose bindings are being\n    ///   generated.\n    fn filter_shared_types<'a>(\n        all_custom_types: impl IntoIterator<Item = &'a FullTypeDeclaration>,\n    ) -> HashSet<FullTypeDeclaration> {\n        all_custom_types.into_iter().duplicates().cloned().collect()\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn correctly_determines_shared_types() {\n        let types = [\"type_0\", \"type_1\", \"type_0\"].map(|type_field| FullTypeDeclaration {\n            type_field: type_field.to_string(),\n            components: vec![],\n            type_parameters: vec![],\n            alias_of: None,\n        });\n\n        let shared_types = Abigen::filter_shared_types(&types);\n\n        assert_eq!(shared_types, HashSet::from([types[0].clone()]))\n    }\n}\n"
  },
  {
    "path": "packages/fuels-code-gen/src/program_bindings/custom_types/enums.rs",
    "content": "use std::collections::HashSet;\n\nuse fuel_abi_types::abi::full_program::FullTypeDeclaration;\nuse proc_macro2::{Ident, TokenStream};\nuse quote::quote;\n\nuse crate::{\n    error::{Result, error},\n    program_bindings::{\n        custom_types::utils::extract_generic_parameters,\n        generated_code::GeneratedCode,\n        resolved_type::ResolvedType,\n        utils::{Component, Components, tokenize_generics},\n    },\n};\n\n/// Returns a TokenStream containing the declaration, `Parameterize`,\n/// `Tokenizable` and `TryFrom` implementations for the enum described by the\n/// given TypeDeclaration.\npub(crate) fn expand_custom_enum(\n    type_decl: &FullTypeDeclaration,\n    no_std: bool,\n    log_id: Option<&String>,\n) -> Result<GeneratedCode> {\n    let enum_type_path = type_decl.custom_type_path()?;\n    let enum_ident = enum_type_path.ident().unwrap();\n\n    let components = Components::new(&type_decl.components, false, enum_type_path.parent())?;\n    if components.is_empty() {\n        return Err(error!(\"enum must have at least one component\"));\n    }\n    let generics = extract_generic_parameters(type_decl);\n\n    let code = enum_decl(enum_ident, &components, &generics, no_std, log_id);\n\n    let enum_code = GeneratedCode::new(code, HashSet::from([enum_ident.into()]), no_std);\n\n    Ok(enum_code.wrap_in_mod(enum_type_path.parent()))\n}\n\nfn maybe_impl_error(enum_ident: &Ident, components: &Components) -> Option<TokenStream> {\n    components.has_error_messages().then(|| {\n        let display_match_branches = components.iter().map(|Component{ident, resolved_type, error_message}| {\n            let error_msg = error_message.as_deref().expect(\"error message is there - checked above\");\n            if let ResolvedType::Unit = resolved_type {\n                quote! {#enum_ident::#ident =>  ::std::write!(f, \"{}\", #error_msg)}\n            } else {\n                quote! {#enum_ident::#ident(val) => ::std::write!(f, \"{}: {:?}\", #error_msg, val)}\n            }\n        });\n\n        let custom_display_impl = quote! {\n            impl ::std::fmt::Display for #enum_ident {\n                fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {\n                   match &self {\n                    #(#display_match_branches,)*\n                   }\n                }\n            }\n        };\n\n        quote! {\n            #custom_display_impl\n            impl ::std::error::Error for #enum_ident{}\n        }\n    })\n}\n\nfn enum_decl(\n    enum_ident: &Ident,\n    components: &Components,\n    generics: &[Ident],\n    no_std: bool,\n    log_id: Option<&String>,\n) -> TokenStream {\n    let maybe_disable_std = no_std.then(|| quote! {#[NoStd]});\n\n    let enum_variants = components.as_enum_variants();\n    let unused_generics_variant = components.generate_variant_for_unused_generics(generics);\n    let (generics_wo_bounds, generics_w_bounds) = tokenize_generics(generics);\n    let maybe_impl_error = maybe_impl_error(enum_ident, components);\n\n    let log_impl = log_id.map(|log_id| {\n        let log_id_u64: u64 = log_id\n            .parse::<u64>()\n            .expect(\"log id should be a valid u64 string\");\n\n        quote! {\n            impl #generics_w_bounds ::fuels::core::codec::Log for #enum_ident #generics_wo_bounds {\n                const LOG_ID: &'static str = #log_id;\n                const LOG_ID_U64: u64 = #log_id_u64;\n            }\n        }\n    });\n\n    quote! {\n        #[allow(clippy::enum_variant_names)]\n        #[derive(\n            Clone,\n            Debug,\n            Eq,\n            PartialEq,\n            ::fuels::macros::Parameterize,\n            ::fuels::macros::Tokenizable,\n            ::fuels::macros::TryFrom,\n        )]\n        #maybe_disable_std\n        pub enum #enum_ident #generics_w_bounds {\n            #(#enum_variants,)*\n            #unused_generics_variant\n        }\n        #maybe_impl_error\n        #log_impl\n    }\n}\n"
  },
  {
    "path": "packages/fuels-code-gen/src/program_bindings/custom_types/structs.rs",
    "content": "use std::collections::HashSet;\n\nuse fuel_abi_types::abi::full_program::FullTypeDeclaration;\nuse proc_macro2::{Ident, TokenStream};\nuse quote::quote;\n\nuse crate::{\n    error::Result,\n    program_bindings::{\n        custom_types::utils::extract_generic_parameters,\n        generated_code::GeneratedCode,\n        resolved_type::ResolvedType,\n        utils::{Component, Components, tokenize_generics},\n    },\n};\n\n/// Returns a TokenStream containing the declaration, `Parameterize`,\n/// `Tokenizable` and `TryFrom` implementations for the struct described by the\n/// given TypeDeclaration.\npub(crate) fn expand_custom_struct(\n    type_decl: &FullTypeDeclaration,\n    no_std: bool,\n    log_id: Option<&String>,\n) -> Result<GeneratedCode> {\n    let struct_type_path = type_decl.custom_type_path()?;\n    let struct_ident = struct_type_path.ident().unwrap();\n\n    let components = Components::new(&type_decl.components, true, struct_type_path.parent())?;\n    let generic_parameters = extract_generic_parameters(type_decl);\n\n    let code = struct_decl(\n        struct_ident,\n        &components,\n        &generic_parameters,\n        no_std,\n        log_id,\n    );\n\n    let struct_code = GeneratedCode::new(code, HashSet::from([struct_ident.into()]), no_std);\n\n    Ok(struct_code.wrap_in_mod(struct_type_path.parent()))\n}\n\nfn unzip_field_names_and_types(components: &Components) -> (Vec<&Ident>, Vec<&ResolvedType>) {\n    components\n        .iter()\n        .map(\n            |Component {\n                 ident,\n                 resolved_type,\n                 ..\n             }| (ident, resolved_type),\n        )\n        .unzip()\n}\n\nfn struct_decl(\n    struct_ident: &Ident,\n    components: &Components,\n    generics: &[Ident],\n    no_std: bool,\n    log_id: Option<&String>,\n) -> TokenStream {\n    let derive_default = components\n        .is_empty()\n        .then(|| quote!(::core::default::Default,));\n\n    let maybe_disable_std = no_std.then(|| quote! {#[NoStd]});\n\n    let (generics_wo_bounds, generics_w_bounds) = tokenize_generics(generics);\n    let (field_names, field_types): (Vec<_>, Vec<_>) = unzip_field_names_and_types(components);\n    let (phantom_fields, phantom_types) =\n        components.generate_parameters_for_unused_generics(generics);\n\n    let log_impl = log_id.map(|log_id| {\n        let log_id_u64: u64 = log_id.parse::<u64>().expect(\"log id should be a valid u64 string\");\n\n        quote! {\n            impl #generics_w_bounds ::fuels::core::codec::Log for #struct_ident #generics_wo_bounds {\n                const LOG_ID: &'static str = #log_id;\n                const LOG_ID_U64: u64 = #log_id_u64;\n            }\n        }\n    });\n\n    quote! {\n        #[derive(\n            Clone,\n            Debug,\n            Eq,\n            PartialEq,\n            #derive_default\n            ::fuels::macros::Parameterize,\n            ::fuels::macros::Tokenizable,\n            ::fuels::macros::TryFrom,\n        )]\n        #maybe_disable_std\n        pub struct #struct_ident #generics_w_bounds {\n            #( pub #field_names: #field_types, )*\n            #(#[Ignore] pub #phantom_fields: #phantom_types, )*\n        }\n\n        impl #generics_w_bounds #struct_ident #generics_wo_bounds {\n            pub fn new(#(#field_names: #field_types,)*) -> Self {\n                Self {\n                    #(#field_names,)*\n                    #(#phantom_fields: ::core::default::Default::default(),)*\n                }\n            }\n        }\n\n        #log_impl\n    }\n}\n"
  },
  {
    "path": "packages/fuels-code-gen/src/program_bindings/custom_types/utils.rs",
    "content": "use fuel_abi_types::{\n    abi::full_program::FullTypeDeclaration,\n    utils::{self, extract_generic_name},\n};\nuse proc_macro2::Ident;\n\n/// Returns a vector of TokenStreams, one for each of the generic parameters\n/// used by the given type.\npub(crate) fn extract_generic_parameters(type_decl: &FullTypeDeclaration) -> Vec<Ident> {\n    type_decl\n        .type_parameters\n        .iter()\n        .map(|decl| {\n            let name = extract_generic_name(&decl.type_field).unwrap_or_else(|| {\n                panic!(\"Type parameters should only contain ids of generic types!\")\n            });\n            utils::ident(&name)\n        })\n        .collect()\n}\n\n#[cfg(test)]\nmod tests {\n    use fuel_abi_types::{\n        abi::unified_program::UnifiedTypeDeclaration, utils::extract_custom_type_name,\n    };\n    use pretty_assertions::assert_eq;\n\n    use super::*;\n    use crate::error::Result;\n\n    #[test]\n    fn extracts_generic_types() -> Result<()> {\n        // given\n        let declaration = UnifiedTypeDeclaration {\n            type_id: 0,\n            type_field: \"\".to_string(),\n            components: None,\n            type_parameters: Some(vec![1, 2]),\n            alias_of: None,\n        };\n        let generic_1 = UnifiedTypeDeclaration {\n            type_id: 1,\n            type_field: \"generic T\".to_string(),\n            components: None,\n            type_parameters: None,\n            alias_of: None,\n        };\n\n        let generic_2 = UnifiedTypeDeclaration {\n            type_id: 2,\n            type_field: \"generic K\".to_string(),\n            components: None,\n            type_parameters: None,\n            alias_of: None,\n        };\n\n        let types = [generic_1, generic_2]\n            .map(|decl| (decl.type_id, decl))\n            .into_iter()\n            .collect();\n\n        // when\n        let generics = extract_generic_parameters(&FullTypeDeclaration::from_counterpart(\n            &declaration,\n            &types,\n        ));\n\n        // then\n        let stringified_generics = generics\n            .into_iter()\n            .map(|generic| generic.to_string())\n            .collect::<Vec<_>>();\n\n        assert_eq!(stringified_generics, vec![\"T\", \"K\"]);\n\n        Ok(())\n    }\n\n    #[test]\n    fn can_extract_struct_name() {\n        let declaration = UnifiedTypeDeclaration {\n            type_id: 0,\n            type_field: \"struct SomeName\".to_string(),\n            components: None,\n            type_parameters: None,\n            alias_of: None,\n        };\n\n        let struct_name = extract_custom_type_name(&declaration.type_field).unwrap();\n\n        assert_eq!(struct_name, \"SomeName\");\n    }\n\n    #[test]\n    fn can_extract_enum_name() {\n        let declaration = UnifiedTypeDeclaration {\n            type_id: 0,\n            type_field: \"enum SomeEnumName\".to_string(),\n            components: None,\n            type_parameters: None,\n            alias_of: None,\n        };\n\n        let struct_name = extract_custom_type_name(&declaration.type_field).unwrap();\n\n        assert_eq!(struct_name, \"SomeEnumName\");\n    }\n}\n"
  },
  {
    "path": "packages/fuels-code-gen/src/program_bindings/custom_types.rs",
    "content": "use std::collections::{HashMap, HashSet};\n\nuse fuel_abi_types::abi::full_program::{FullLoggedType, FullTypeDeclaration};\nuse itertools::Itertools;\nuse quote::quote;\n\nuse crate::{\n    error::Result,\n    program_bindings::{\n        custom_types::{enums::expand_custom_enum, structs::expand_custom_struct},\n        generated_code::GeneratedCode,\n        utils::sdk_provided_custom_types_lookup,\n    },\n    utils::TypePath,\n};\n\nmod enums;\nmod structs;\npub(crate) mod utils;\n\n/// Generates Rust code for each type inside `types` if:\n/// * the type is not present inside `shared_types`, and\n/// * if it should be generated (see: [`should_skip_codegen`], and\n/// * if it is a struct or an enum.\n///\n///\n/// # Arguments\n///\n/// * `types`: Types you wish to generate Rust code for.\n/// * `shared_types`: Types that are shared between multiple\n///   contracts/scripts/predicates and thus generated elsewhere.\npub(crate) fn generate_types<'a>(\n    types: impl IntoIterator<Item = &'a FullTypeDeclaration>,\n    shared_types: &HashSet<FullTypeDeclaration>,\n    logged_types: impl IntoIterator<Item = &'a FullLoggedType>,\n    no_std: bool,\n) -> Result<GeneratedCode> {\n    let log_ids: HashMap<_, _> = logged_types\n        .into_iter()\n        .map(|l| (l.application.type_decl.type_field.clone(), l.log_id.clone()))\n        .collect();\n\n    types\n        .into_iter()\n        .filter(|ttype| !should_skip_codegen(ttype))\n        .map(|ttype: &FullTypeDeclaration| {\n            let log_id = log_ids.get(&ttype.type_field);\n            if shared_types.contains(ttype) {\n                reexport_the_shared_type(ttype, no_std)\n            } else if ttype.is_struct_type() {\n                expand_custom_struct(ttype, no_std, log_id)\n            } else {\n                expand_custom_enum(ttype, no_std, log_id)\n            }\n        })\n        .fold_ok(GeneratedCode::default(), |acc, generated_code| {\n            acc.merge(generated_code)\n        })\n}\n\n/// Instead of generating bindings for `ttype` this fn will just generate a `pub use` pointing to\n/// the already generated equivalent shared type.\nfn reexport_the_shared_type(ttype: &FullTypeDeclaration, no_std: bool) -> Result<GeneratedCode> {\n    // e.g. some_library::another_mod::SomeStruct\n    let type_path = ttype\n        .custom_type_path()\n        .expect(\"This must be a custom type due to the previous filter step\");\n\n    let type_mod = type_path.parent();\n\n    let from_top_lvl_to_shared_types =\n        TypePath::new(\"super::shared_types\").expect(\"This is known to be a valid TypePath\");\n\n    let top_lvl_mod = TypePath::default();\n    let from_current_mod_to_top_level = top_lvl_mod.relative_path_from(&type_mod);\n\n    let path = from_current_mod_to_top_level\n        .append(from_top_lvl_to_shared_types)\n        .append(type_path);\n\n    // e.g. pub use super::super::super::shared_types::some_library::another_mod::SomeStruct;\n    let the_reexport = quote! {pub use #path;};\n\n    Ok(GeneratedCode::new(the_reexport, Default::default(), no_std).wrap_in_mod(type_mod))\n}\n\n// Checks whether the given type should not have code generated for it. This\n// is mainly because the corresponding type in Rust already exists --\n// e.g. the contract's Vec type is mapped to std::vec::Vec from the Rust\n// stdlib, ContractId is a custom type implemented by fuels-rs, etc.\n// Others like 'std::vec::RawVec' are skipped because they are\n// implementation details of the contract's Vec type and are not directly\n// used in the SDK.\npub fn should_skip_codegen(type_decl: &FullTypeDeclaration) -> bool {\n    if !type_decl.is_custom_type() {\n        return true;\n    }\n\n    let type_path = type_decl.custom_type_path().unwrap();\n\n    is_type_sdk_provided(&type_path) || is_type_unused(&type_path)\n}\n\nfn is_type_sdk_provided(type_path: &TypePath) -> bool {\n    sdk_provided_custom_types_lookup().contains_key(type_path)\n}\n\nfn is_type_unused(type_path: &TypePath) -> bool {\n    let msg = \"Known to be correct\";\n    [\n        TypePath::new(\"std::vec::RawVec\").expect(msg),\n        TypePath::new(\"std::bytes::RawBytes\").expect(msg),\n    ]\n    .contains(type_path)\n}\n\n// Doing string -> TokenStream -> string isn't pretty but gives us the opportunity to\n// have a better understanding of the generated code so we consider it ok.\n// To generate the expected examples, output of the functions were taken\n// with code @9ca376, and formatted in-IDE using rustfmt. It should be noted that\n// rustfmt added an extra `,` after the last struct/enum field, which is not added\n// by the `expand_custom_*` functions, and so was removed from the expected string.\n// TODO(iqdecay): append extra `,` to last enum/struct field so it is aligned with rustfmt\n#[cfg(test)]\nmod tests {\n    use std::collections::HashMap;\n\n    use fuel_abi_types::abi::unified_program::{UnifiedTypeApplication, UnifiedTypeDeclaration};\n    use pretty_assertions::assert_eq;\n    use quote::quote;\n\n    use super::*;\n\n    #[test]\n    fn test_expand_custom_enum() -> Result<()> {\n        let p = UnifiedTypeDeclaration {\n            type_id: 0,\n            type_field: String::from(\"enum MatchaTea\"),\n            components: Some(vec![\n                UnifiedTypeApplication {\n                    name: String::from(\"LongIsland\"),\n                    type_id: 1,\n                    ..Default::default()\n                },\n                UnifiedTypeApplication {\n                    name: String::from(\"MoscowMule\"),\n                    type_id: 2,\n                    ..Default::default()\n                },\n            ]),\n            ..Default::default()\n        };\n        let types = [\n            (0, p.clone()),\n            (\n                1,\n                UnifiedTypeDeclaration {\n                    type_id: 1,\n                    type_field: String::from(\"u64\"),\n                    ..Default::default()\n                },\n            ),\n            (\n                2,\n                UnifiedTypeDeclaration {\n                    type_id: 2,\n                    type_field: String::from(\"bool\"),\n                    ..Default::default()\n                },\n            ),\n        ]\n        .into_iter()\n        .collect::<HashMap<_, _>>();\n\n        let actual = expand_custom_enum(\n            &FullTypeDeclaration::from_counterpart(&p, &types),\n            false,\n            None,\n        )?;\n\n        let expected = quote! {\n            #[allow(clippy::enum_variant_names)]\n            #[derive(\n                Clone,\n                Debug,\n                Eq,\n                PartialEq,\n                ::fuels::macros::Parameterize,\n                ::fuels::macros::Tokenizable,\n                ::fuels::macros::TryFrom,\n            )]\n            pub enum MatchaTea {\n                LongIsland(::core::primitive::u64),\n                MoscowMule(::core::primitive::bool),\n            }\n        };\n\n        assert_eq!(actual.code().to_string(), expected.to_string());\n        Ok(())\n    }\n\n    #[test]\n    fn test_enum_with_no_variants_cannot_be_constructed() -> Result<()> {\n        let p = UnifiedTypeDeclaration {\n            type_id: 0,\n            type_field: \"enum SomeEmptyEnum\".to_string(),\n            components: Some(vec![]),\n            ..Default::default()\n        };\n        let types = [(0, p.clone())].into_iter().collect::<HashMap<_, _>>();\n\n        expand_custom_enum(\n            &FullTypeDeclaration::from_counterpart(&p, &types),\n            false,\n            None,\n        )\n        .expect_err(\"Was able to construct an enum without variants\");\n\n        Ok(())\n    }\n\n    #[test]\n    fn test_expand_struct_inside_enum() -> Result<()> {\n        let inner_struct = UnifiedTypeApplication {\n            name: String::from(\"Infrastructure\"),\n            type_id: 1,\n            ..Default::default()\n        };\n        let enum_components = vec![\n            inner_struct,\n            UnifiedTypeApplication {\n                name: \"Service\".to_string(),\n                type_id: 2,\n                ..Default::default()\n            },\n        ];\n        let p = UnifiedTypeDeclaration {\n            type_id: 0,\n            type_field: String::from(\"enum Amsterdam\"),\n            components: Some(enum_components),\n            ..Default::default()\n        };\n\n        let types = [\n            (0, p.clone()),\n            (\n                1,\n                UnifiedTypeDeclaration {\n                    type_id: 1,\n                    type_field: String::from(\"struct Building\"),\n                    components: Some(vec![]),\n                    ..Default::default()\n                },\n            ),\n            (\n                2,\n                UnifiedTypeDeclaration {\n                    type_id: 2,\n                    type_field: String::from(\"u32\"),\n                    ..Default::default()\n                },\n            ),\n        ]\n        .into_iter()\n        .collect::<HashMap<_, _>>();\n\n        let actual = expand_custom_enum(\n            &FullTypeDeclaration::from_counterpart(&p, &types),\n            false,\n            None,\n        )?;\n\n        let expected = quote! {\n            #[allow(clippy::enum_variant_names)]\n            #[derive(\n                Clone,\n                Debug,\n                Eq,\n                PartialEq,\n                ::fuels::macros::Parameterize,\n                ::fuels::macros::Tokenizable,\n                ::fuels::macros::TryFrom,\n            )]\n            pub enum Amsterdam {\n                Infrastructure(self::Building),\n                Service(::core::primitive::u32),\n            }\n        };\n\n        assert_eq!(actual.code().to_string(), expected.to_string());\n        Ok(())\n    }\n\n    #[test]\n    fn test_expand_array_inside_enum() -> Result<()> {\n        let enum_components = vec![UnifiedTypeApplication {\n            name: \"SomeArr\".to_string(),\n            type_id: 1,\n            ..Default::default()\n        }];\n        let p = UnifiedTypeDeclaration {\n            type_id: 0,\n            type_field: String::from(\"enum SomeEnum\"),\n            components: Some(enum_components),\n            ..Default::default()\n        };\n        let types = [\n            (0, p.clone()),\n            (\n                1,\n                UnifiedTypeDeclaration {\n                    type_id: 1,\n                    type_field: \"[u64; 7]\".to_string(),\n                    components: Some(vec![UnifiedTypeApplication {\n                        type_id: 2,\n                        ..Default::default()\n                    }]),\n                    ..Default::default()\n                },\n            ),\n            (\n                2,\n                UnifiedTypeDeclaration {\n                    type_id: 2,\n                    type_field: \"u64\".to_string(),\n                    ..Default::default()\n                },\n            ),\n        ]\n        .into_iter()\n        .collect::<HashMap<_, _>>();\n\n        let actual = expand_custom_enum(\n            &FullTypeDeclaration::from_counterpart(&p, &types),\n            false,\n            None,\n        )?;\n\n        let expected = quote! {\n            #[allow(clippy::enum_variant_names)]\n            #[derive(\n                Clone,\n                Debug,\n                Eq,\n                PartialEq,\n                ::fuels::macros::Parameterize,\n                ::fuels::macros::Tokenizable,\n                ::fuels::macros::TryFrom,\n            )]\n            pub enum SomeEnum {\n                SomeArr([::core::primitive::u64; 7usize]),\n            }\n        };\n\n        assert_eq!(actual.code().to_string(), expected.to_string());\n        Ok(())\n    }\n\n    #[test]\n    fn test_expand_custom_enum_with_enum() -> Result<()> {\n        let p = UnifiedTypeDeclaration {\n            type_id: 3,\n            type_field: String::from(\"enum EnumLevel3\"),\n            components: Some(vec![UnifiedTypeApplication {\n                name: String::from(\"El2\"),\n                type_id: 2,\n                ..Default::default()\n            }]),\n            ..Default::default()\n        };\n        let types = [\n            (3, p.clone()),\n            (\n                2,\n                UnifiedTypeDeclaration {\n                    type_id: 2,\n                    type_field: String::from(\"enum EnumLevel2\"),\n                    components: Some(vec![UnifiedTypeApplication {\n                        name: String::from(\"El1\"),\n                        type_id: 1,\n                        ..Default::default()\n                    }]),\n                    ..Default::default()\n                },\n            ),\n            (\n                1,\n                UnifiedTypeDeclaration {\n                    type_id: 1,\n                    type_field: String::from(\"enum EnumLevel1\"),\n                    components: Some(vec![UnifiedTypeApplication {\n                        name: String::from(\"Num\"),\n                        type_id: 0,\n                        ..Default::default()\n                    }]),\n                    ..Default::default()\n                },\n            ),\n            (\n                0,\n                UnifiedTypeDeclaration {\n                    type_id: 0,\n                    type_field: String::from(\"u32\"),\n                    ..Default::default()\n                },\n            ),\n        ]\n        .into_iter()\n        .collect::<HashMap<_, _>>();\n\n        let log_id = \"42\".to_string();\n        let actual = expand_custom_enum(\n            &FullTypeDeclaration::from_counterpart(&p, &types),\n            false,\n            Some(&log_id),\n        )?;\n\n        let expected = quote! {\n            #[allow(clippy::enum_variant_names)]\n            #[derive(\n                Clone,\n                Debug,\n                Eq,\n                PartialEq,\n                ::fuels::macros::Parameterize,\n                ::fuels::macros::Tokenizable,\n                ::fuels::macros::TryFrom,\n            )]\n            pub enum EnumLevel3 {\n                El2(self::EnumLevel2),\n            }\n\n            impl ::fuels::core::codec::Log for EnumLevel3 {\n                const LOG_ID: &'static str = \"42\";\n                const LOG_ID_U64: u64 = 42u64;\n            }\n        };\n\n        assert_eq!(actual.code().to_string(), expected.to_string());\n        Ok(())\n    }\n\n    #[test]\n    fn test_expand_custom_struct() -> Result<()> {\n        let p = UnifiedTypeDeclaration {\n            type_field: String::from(\"struct Cocktail\"),\n            components: Some(vec![\n                UnifiedTypeApplication {\n                    name: String::from(\"long_island\"),\n                    type_id: 1,\n                    ..Default::default()\n                },\n                UnifiedTypeApplication {\n                    name: String::from(\"cosmopolitan\"),\n                    type_id: 2,\n                    ..Default::default()\n                },\n                UnifiedTypeApplication {\n                    name: String::from(\"mojito\"),\n                    type_id: 3,\n                    ..Default::default()\n                },\n            ]),\n            ..Default::default()\n        };\n        let types = [\n            (0, p.clone()),\n            (\n                1,\n                UnifiedTypeDeclaration {\n                    type_id: 1,\n                    type_field: String::from(\"bool\"),\n                    ..Default::default()\n                },\n            ),\n            (\n                2,\n                UnifiedTypeDeclaration {\n                    type_id: 2,\n                    type_field: String::from(\"u64\"),\n                    ..Default::default()\n                },\n            ),\n            (\n                3,\n                UnifiedTypeDeclaration {\n                    type_id: 3,\n                    type_field: String::from(\"u32\"),\n                    ..Default::default()\n                },\n            ),\n        ]\n        .into_iter()\n        .collect::<HashMap<_, _>>();\n\n        let actual = expand_custom_struct(\n            &FullTypeDeclaration::from_counterpart(&p, &types),\n            false,\n            None,\n        )?;\n\n        let expected = quote! {\n            #[derive(\n                Clone,\n                Debug,\n                Eq,\n                PartialEq,\n                ::fuels::macros::Parameterize,\n                ::fuels::macros::Tokenizable,\n                ::fuels::macros::TryFrom,\n            )]\n            pub struct Cocktail {\n                pub long_island: ::core::primitive::bool,\n                pub cosmopolitan: ::core::primitive::u64,\n                pub mojito: ::core::primitive::u32,\n            }\n            impl Cocktail {\n                pub fn new(\n                    long_island: ::core::primitive::bool,\n                    cosmopolitan: ::core::primitive::u64,\n                    mojito: ::core::primitive::u32,\n                ) -> Self {\n                    Self {\n                        long_island,\n                        cosmopolitan,\n                        mojito,\n                    }\n                }\n            }\n        };\n\n        assert_eq!(actual.code().to_string(), expected.to_string());\n\n        Ok(())\n    }\n\n    #[test]\n    fn test_struct_with_no_fields_can_be_constructed() -> Result<()> {\n        let p = UnifiedTypeDeclaration {\n            type_id: 0,\n            type_field: \"struct SomeEmptyStruct\".to_string(),\n            components: Some(vec![]),\n            ..Default::default()\n        };\n        let types = [(0, p.clone())].into_iter().collect::<HashMap<_, _>>();\n\n        let actual = expand_custom_struct(\n            &FullTypeDeclaration::from_counterpart(&p, &types),\n            false,\n            None,\n        )?;\n\n        let expected = quote! {\n            #[derive(\n                Clone,\n                Debug,\n                Eq,\n                PartialEq,\n                ::core::default::Default,\n                ::fuels::macros::Parameterize,\n                ::fuels::macros::Tokenizable,\n                ::fuels::macros::TryFrom,\n            )]\n            pub struct SomeEmptyStruct {}\n            impl SomeEmptyStruct {\n                pub fn new() -> Self {\n                    Self {}\n                }\n            }\n        };\n\n        assert_eq!(actual.code().to_string(), expected.to_string());\n\n        Ok(())\n    }\n\n    #[test]\n    fn test_expand_custom_struct_with_struct() -> Result<()> {\n        let p = UnifiedTypeDeclaration {\n            type_id: 0,\n            type_field: String::from(\"struct Cocktail\"),\n            components: Some(vec![\n                UnifiedTypeApplication {\n                    name: String::from(\"long_island\"),\n                    type_id: 1,\n                    ..Default::default()\n                },\n                UnifiedTypeApplication {\n                    name: String::from(\"mojito\"),\n                    type_id: 2,\n                    ..Default::default()\n                },\n            ]),\n            ..Default::default()\n        };\n        let types = [\n            (0, p.clone()),\n            (\n                1,\n                UnifiedTypeDeclaration {\n                    type_id: 1,\n                    type_field: String::from(\"struct Shaker\"),\n                    components: Some(vec![]),\n                    ..Default::default()\n                },\n            ),\n            (\n                2,\n                UnifiedTypeDeclaration {\n                    type_id: 2,\n                    type_field: String::from(\"u32\"),\n                    ..Default::default()\n                },\n            ),\n        ]\n        .into_iter()\n        .collect::<HashMap<_, _>>();\n\n        let log_id = \"13\".to_string();\n        let actual = expand_custom_struct(\n            &FullTypeDeclaration::from_counterpart(&p, &types),\n            false,\n            Some(&log_id),\n        )?;\n\n        let expected = quote! {\n            #[derive(\n                Clone,\n                Debug,\n                Eq,\n                PartialEq,\n                ::fuels::macros::Parameterize,\n                ::fuels::macros::Tokenizable,\n                ::fuels::macros::TryFrom,\n            )]\n            pub struct Cocktail {\n                pub long_island: self::Shaker,\n                pub mojito: ::core::primitive::u32,\n            }\n            impl Cocktail {\n                pub fn new(long_island: self::Shaker, mojito: ::core::primitive::u32,) -> Self {\n                    Self {\n                        long_island,\n                        mojito,\n                    }\n                }\n            }\n\n            impl ::fuels::core::codec::Log for Cocktail {\n                const LOG_ID: &'static str = \"13\";\n                const LOG_ID_U64: u64 = 13u64;\n            }\n        };\n\n        assert_eq!(actual.code().to_string(), expected.to_string());\n        Ok(())\n    }\n\n    #[test]\n    fn shared_types_are_just_reexported() {\n        // given\n        let type_decl = FullTypeDeclaration {\n            type_field: \"struct some_shared_lib::SharedStruct\".to_string(),\n            components: vec![],\n            type_parameters: vec![],\n            alias_of: None,\n        };\n        let shared_types = HashSet::from([type_decl.clone()]);\n\n        // when\n        let generated_code = generate_types(&[type_decl], &shared_types, [], false).unwrap();\n\n        // then\n        let expected_code = quote! {\n            #[allow(clippy::too_many_arguments)]\n            #[allow(clippy::disallowed_names)]\n            #[no_implicit_prelude]\n            pub mod some_shared_lib {\n                use ::core::{\n                    clone::Clone,\n                    convert::{Into, TryFrom, From},\n                    iter::IntoIterator,\n                    iter::Iterator,\n                    marker::Sized,\n                    panic,\n                };\n\n                use ::std::{string::ToString, format, vec, default::Default};\n                pub use super::super::shared_types::some_shared_lib::SharedStruct;\n            }\n        };\n\n        assert_eq!(generated_code.code().to_string(), expected_code.to_string());\n    }\n}\n"
  },
  {
    "path": "packages/fuels-code-gen/src/program_bindings/generated_code.rs",
    "content": "use std::collections::{HashMap, HashSet};\n\nuse itertools::Itertools;\nuse proc_macro2::{Ident, TokenStream};\nuse quote::quote;\n\nuse crate::utils::TypePath;\n\n#[derive(Default, Debug)]\npub(crate) struct GeneratedCode {\n    top_level_code: TokenStream,\n    usable_types: HashSet<TypePath>,\n    code_in_mods: HashMap<Ident, GeneratedCode>,\n    no_std: bool,\n}\n\nimpl GeneratedCode {\n    pub fn new(code: TokenStream, usable_types: HashSet<TypePath>, no_std: bool) -> Self {\n        Self {\n            top_level_code: code,\n            code_in_mods: HashMap::default(),\n            usable_types,\n            no_std,\n        }\n    }\n\n    fn prelude(&self) -> TokenStream {\n        let lib = if self.no_std {\n            quote! {::alloc}\n        } else {\n            quote! {::std}\n        };\n\n        quote! {\n                use ::core::{\n                    clone::Clone,\n                    convert::{Into, TryFrom, From},\n                    iter::IntoIterator,\n                    iter::Iterator,\n                    marker::Sized,\n                    panic,\n                };\n\n                use #lib::{string::ToString, format, vec, default::Default};\n\n        }\n    }\n\n    pub fn code(&self) -> TokenStream {\n        let top_level_code = &self.top_level_code;\n\n        let prelude = self.prelude();\n        let code_in_mods = self\n            .code_in_mods\n            .iter()\n            .sorted_by_key(|(mod_name, _)| {\n                // Sorted to make test expectations maintainable\n                *mod_name\n            })\n            .map(|(mod_name, generated_code)| {\n                let code = generated_code.code();\n                quote! {\n                    #[allow(clippy::too_many_arguments)]\n                    #[allow(clippy::disallowed_names)]\n                    #[no_implicit_prelude]\n                    pub mod #mod_name {\n                        #prelude\n                        #code\n                    }\n                }\n            });\n\n        quote! {\n            #top_level_code\n            #(#code_in_mods)*\n        }\n    }\n\n    pub fn is_empty(&self) -> bool {\n        self.code().is_empty()\n    }\n\n    pub fn merge(mut self, another: GeneratedCode) -> Self {\n        self.top_level_code.extend(another.top_level_code);\n        self.usable_types.extend(another.usable_types);\n\n        for (mod_name, code) in another.code_in_mods {\n            let entry = self.code_in_mods.entry(mod_name).or_default();\n            *entry = std::mem::take(entry).merge(code);\n        }\n\n        self\n    }\n\n    pub fn wrap_in_mod(mut self, mod_name: impl Into<TypePath>) -> Self {\n        let mut parts = mod_name.into().take_parts();\n        parts.reverse();\n\n        for mod_name in parts {\n            self = self.wrap_in_single_mod(mod_name)\n        }\n\n        self\n    }\n\n    fn wrap_in_single_mod(self, mod_name: Ident) -> Self {\n        Self {\n            code_in_mods: HashMap::from([(mod_name, self)]),\n            ..Default::default()\n        }\n    }\n\n    pub fn use_statements_for_uniquely_named_types(&self) -> TokenStream {\n        let type_paths = self\n            .types_with_unique_names()\n            .into_iter()\n            .filter(|type_path| type_path.has_multiple_parts());\n\n        quote! {\n            #(pub use #type_paths;)*\n        }\n    }\n\n    fn types_with_unique_names(&self) -> Vec<TypePath> {\n        self.code_in_mods\n            .iter()\n            .flat_map(|(mod_name, code)| {\n                code.types_with_unique_names()\n                    .into_iter()\n                    .map(|type_path| type_path.prepend(mod_name.into()))\n                    .collect::<Vec<_>>()\n            })\n            .chain(self.usable_types.iter().cloned())\n            .sorted_by(|lhs, rhs| lhs.ident().cmp(&rhs.ident()))\n            .group_by(|e| e.ident().cloned())\n            .into_iter()\n            .filter_map(|(_, group)| {\n                let mut types = group.collect::<Vec<_>>();\n                (types.len() == 1).then_some(types.pop().unwrap())\n            })\n            .collect()\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use crate::utils::ident;\n\n    #[test]\n    fn can_merge_top_level_code() {\n        // given\n        let struct_1 = given_some_struct_code(\"Struct1\");\n        let struct_2 = given_some_struct_code(\"Struct2\");\n\n        // when\n        let joined = struct_1.merge(struct_2);\n\n        // then\n        let expected_code = quote! {\n            struct Struct1;\n            struct Struct2;\n        };\n\n        assert_eq!(joined.code().to_string(), expected_code.to_string());\n    }\n\n    #[test]\n    fn wrapping_in_mod_updates_code() {\n        // given\n        let some_type = given_some_struct_code(\"SomeType\");\n\n        // when\n        let wrapped_in_mod = some_type.wrap_in_mod(given_type_path(\"a_mod\"));\n\n        // then\n        let expected_code = quote! {\n            #[allow(clippy::too_many_arguments)]\n            #[allow(clippy::disallowed_names)]\n            #[no_implicit_prelude]\n            pub mod a_mod {\n                use ::core::{\n                    clone::Clone,\n                    convert::{Into, TryFrom, From},\n                    iter::IntoIterator,\n                    iter::Iterator,\n                    marker::Sized,\n                    panic,\n                };\n\n                use ::std::{string::ToString, format, vec, default::Default};\n\n                struct SomeType;\n            }\n        };\n\n        assert_eq!(wrapped_in_mod.code().to_string(), expected_code.to_string());\n    }\n\n    #[test]\n    fn wrapping_in_mod_updates_use_statements() {\n        // given\n        let some_type = given_some_struct_code(\"SomeType\");\n        let wrapped_in_mod = some_type.wrap_in_mod(given_type_path(\"a_mod\"));\n\n        // when\n        let use_statements = wrapped_in_mod.use_statements_for_uniquely_named_types();\n\n        // then\n        let expected_use_statements = quote! {pub use a_mod::SomeType;};\n        assert_eq!(\n            use_statements.to_string(),\n            expected_use_statements.to_string()\n        );\n    }\n\n    #[test]\n    fn merging_code_will_merge_mods_as_well() {\n        // given\n        let common_struct_1 = given_some_struct_code(\"SomeStruct1\")\n            .wrap_in_mod(given_type_path(\"common_mod::deeper_mod\"));\n\n        let common_struct_2 =\n            given_some_struct_code(\"SomeStruct2\").wrap_in_mod(given_type_path(\"common_mod\"));\n\n        let top_level_struct = given_some_struct_code(\"TopLevelStruct\");\n\n        let different_mod_struct =\n            given_some_struct_code(\"SomeStruct3\").wrap_in_mod(given_type_path(\"different_mod\"));\n\n        // when\n        let merged_code = common_struct_1\n            .merge(common_struct_2)\n            .merge(top_level_struct)\n            .merge(different_mod_struct);\n\n        // then\n        let prelude = quote! {\n                use ::core::{\n                    clone::Clone,\n                    convert::{Into, TryFrom, From},\n                    iter::IntoIterator,\n                    iter::Iterator,\n                    marker::Sized,\n                    panic,\n                };\n                use ::std::{string::ToString, format, vec, default::Default};\n        };\n\n        let expected_code = quote! {\n            struct TopLevelStruct;\n            #[allow(clippy::too_many_arguments)]\n            #[allow(clippy::disallowed_names)]\n            #[no_implicit_prelude]\n            pub mod common_mod {\n                #prelude\n\n                struct SomeStruct2;\n                #[allow(clippy::too_many_arguments)]\n                #[allow(clippy::disallowed_names)]\n                #[no_implicit_prelude]\n                pub mod deeper_mod {\n                    #prelude\n                    struct SomeStruct1;\n                }\n            }\n            #[allow(clippy::too_many_arguments)]\n            #[allow(clippy::disallowed_names)]\n            #[no_implicit_prelude]\n            pub mod different_mod {\n                #prelude\n                struct SomeStruct3;\n            }\n        };\n\n        let code = merged_code.code();\n        assert_eq!(code.to_string(), expected_code.to_string());\n\n        let use_statements = merged_code.use_statements_for_uniquely_named_types();\n        let expected_use_statements = quote! {\n            pub use common_mod::deeper_mod::SomeStruct1;\n            pub use common_mod::SomeStruct2;\n            pub use different_mod::SomeStruct3;\n        };\n        assert_eq!(\n            use_statements.to_string(),\n            expected_use_statements.to_string()\n        );\n    }\n\n    #[test]\n    fn use_statement_not_generated_for_top_level_type() {\n        let usable_types = [\"TopLevelImport\", \"something::Deeper\"]\n            .map(given_type_path)\n            .into_iter()\n            .collect();\n        let code = GeneratedCode::new(Default::default(), usable_types, false);\n\n        let use_statements = code.use_statements_for_uniquely_named_types();\n\n        let expected_use_statements = quote! {\n            pub use something::Deeper;\n        };\n        assert_eq!(\n            use_statements.to_string(),\n            expected_use_statements.to_string()\n        );\n    }\n\n    #[test]\n    fn use_statements_only_for_uniquely_named_types() {\n        // given\n        let not_unique_struct =\n            given_some_struct_code(\"NotUnique\").wrap_in_mod(TypePath::new(\"another_mod\").unwrap());\n\n        let generated_code = GeneratedCode::new(\n            Default::default(),\n            HashSet::from([\n                given_type_path(\"some_mod::Unique\"),\n                given_type_path(\"even_though::the_duplicate_is::in_another_mod::NotUnique\"),\n            ]),\n            false,\n        )\n        .merge(not_unique_struct);\n\n        // when\n        let use_statements = generated_code.use_statements_for_uniquely_named_types();\n\n        // then\n        let expected_use_statements = quote! {\n            pub use some_mod::Unique;\n        };\n\n        assert_eq!(\n            use_statements.to_string(),\n            expected_use_statements.to_string()\n        );\n    }\n\n    fn given_some_struct_code(struct_name: &str) -> GeneratedCode {\n        let struct_ident = ident(struct_name);\n\n        GeneratedCode::new(\n            quote! {struct #struct_ident;},\n            HashSet::from([given_type_path(struct_name)]),\n            false,\n        )\n    }\n\n    fn given_type_path(path: &str) -> TypePath {\n        TypePath::new(path).expect(\"hand crafted, should be valid\")\n    }\n}\n"
  },
  {
    "path": "packages/fuels-code-gen/src/program_bindings/resolved_type.rs",
    "content": "use std::fmt::{Display, Formatter};\n\nuse fuel_abi_types::{\n    abi::full_program::FullTypeApplication,\n    utils::{self, extract_array_len, extract_generic_name, extract_str_len, has_tuple_format},\n};\nuse proc_macro2::{Ident, TokenStream};\nuse quote::{ToTokens, quote};\n\nuse crate::{\n    error::{Result, error},\n    program_bindings::utils::sdk_provided_custom_types_lookup,\n    utils::TypePath,\n};\n\n#[derive(Debug, Clone, PartialEq)]\npub enum GenericType {\n    Named(Ident),\n    Constant(usize),\n}\n\nimpl ToTokens for GenericType {\n    fn to_tokens(&self, tokens: &mut TokenStream) {\n        let stream = match self {\n            GenericType::Named(ident) => ident.to_token_stream(),\n            GenericType::Constant(constant) => constant.to_token_stream(),\n        };\n\n        tokens.extend(stream);\n    }\n}\n\n/// Represents a Rust type alongside its generic parameters. For when you want to reference an ABI\n/// type in Rust code since [`ResolvedType`] can be converted into a [`TokenStream`] via\n/// `resolved_type.to_token_stream()`.\n#[derive(Debug, Clone)]\npub enum ResolvedType {\n    Unit,\n    Primitive(TypePath),\n    StructOrEnum {\n        path: TypePath,\n        generics: Vec<ResolvedType>,\n    },\n    Array(Box<ResolvedType>, usize),\n    Tuple(Vec<ResolvedType>),\n    Generic(GenericType),\n}\n\nimpl ResolvedType {\n    pub fn generics(&self) -> Vec<GenericType> {\n        match self {\n            ResolvedType::StructOrEnum {\n                generics: elements, ..\n            }\n            | ResolvedType::Tuple(elements) => {\n                elements.iter().flat_map(|el| el.generics()).collect()\n            }\n            ResolvedType::Array(el, _) => el.generics(),\n            ResolvedType::Generic(inner) => vec![inner.clone()],\n            _ => vec![],\n        }\n    }\n}\n\nimpl ToTokens for ResolvedType {\n    fn to_tokens(&self, tokens: &mut TokenStream) {\n        let tokenized = match self {\n            ResolvedType::Unit => quote! {()},\n            ResolvedType::Primitive(path) => path.into_token_stream(),\n            ResolvedType::StructOrEnum { path, generics } => {\n                if generics.is_empty() {\n                    path.to_token_stream()\n                } else {\n                    quote! { #path<#(#generics),*>}\n                }\n            }\n            ResolvedType::Array(el, count) => quote! { [#el; #count]},\n            ResolvedType::Tuple(elements) => {\n                // it is important to leave a trailing comma because a tuple with\n                // one element is written as (element,) not (element) which is\n                // resolved to just element\n                quote! { (#(#elements,)*) }\n            }\n            ResolvedType::Generic(generic_type) => generic_type.into_token_stream(),\n        };\n\n        tokens.extend(tokenized)\n    }\n}\n\nimpl Display for ResolvedType {\n    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {\n        write!(f, \"{}\", self.to_token_stream())\n    }\n}\n\n/// Used to resolve [`FullTypeApplication`]s into [`ResolvedType`]s\npub(crate) struct TypeResolver {\n    /// The mod in which the produced [`ResolvedType`]s are going to end up in.\n    current_mod: TypePath,\n}\n\nimpl Default for TypeResolver {\n    fn default() -> Self {\n        TypeResolver::new(Default::default())\n    }\n}\n\nimpl TypeResolver {\n    pub(crate) fn new(current_mod: TypePath) -> Self {\n        Self { current_mod }\n    }\n\n    pub(crate) fn resolve(&self, type_application: &FullTypeApplication) -> Result<ResolvedType> {\n        let resolvers = [\n            Self::try_as_primitive_type,\n            Self::try_as_bits256,\n            Self::try_as_generic,\n            Self::try_as_array,\n            Self::try_as_sized_ascii_string,\n            Self::try_as_ascii_string,\n            Self::try_as_tuple,\n            Self::try_as_raw_slice,\n            Self::try_as_custom_type,\n        ];\n\n        for resolver in resolvers {\n            if let Some(resolved) = resolver(self, type_application)? {\n                return Ok(resolved);\n            }\n        }\n\n        let type_field = &type_application.type_decl.type_field;\n        Err(error!(\"could not resolve '{type_field}' to any known type\"))\n    }\n\n    fn resolve_multiple(\n        &self,\n        type_applications: &[FullTypeApplication],\n    ) -> Result<Vec<ResolvedType>> {\n        type_applications\n            .iter()\n            .map(|type_application| self.resolve(type_application))\n            .collect()\n    }\n\n    fn try_as_generic(\n        &self,\n        type_application: &FullTypeApplication,\n    ) -> Result<Option<ResolvedType>> {\n        let Some(name) = extract_generic_name(&type_application.type_decl.type_field) else {\n            return Ok(None);\n        };\n\n        let ident = utils::safe_ident(&name);\n        Ok(Some(ResolvedType::Generic(GenericType::Named(ident))))\n    }\n\n    fn try_as_array(&self, type_application: &FullTypeApplication) -> Result<Option<ResolvedType>> {\n        let type_decl = &type_application.type_decl;\n        let Some(len) = extract_array_len(&type_decl.type_field) else {\n            return Ok(None);\n        };\n\n        let components = self.resolve_multiple(&type_decl.components)?;\n        let type_inside = match components.as_slice() {\n            [single_type] => single_type,\n            other => {\n                return Err(error!(\n                    \"array must have only one component. Actual components: {other:?}\"\n                ));\n            }\n        };\n\n        Ok(Some(ResolvedType::Array(\n            Box::new(type_inside.clone()),\n            len,\n        )))\n    }\n\n    fn try_as_sized_ascii_string(\n        &self,\n        type_application: &FullTypeApplication,\n    ) -> Result<Option<ResolvedType>> {\n        let Some(len) = extract_str_len(&type_application.type_decl.type_field) else {\n            return Ok(None);\n        };\n\n        let path =\n            TypePath::new(\"::fuels::types::SizedAsciiString\").expect(\"this is a valid TypePath\");\n        Ok(Some(ResolvedType::StructOrEnum {\n            path,\n            generics: vec![ResolvedType::Generic(GenericType::Constant(len))],\n        }))\n    }\n\n    fn try_as_ascii_string(\n        &self,\n        type_application: &FullTypeApplication,\n    ) -> Result<Option<ResolvedType>> {\n        let maybe_resolved = (type_application.type_decl.type_field == \"str\").then(|| {\n            let path =\n                TypePath::new(\"::fuels::types::AsciiString\").expect(\"this is a valid TypePath\");\n            ResolvedType::StructOrEnum {\n                path,\n                generics: vec![],\n            }\n        });\n\n        Ok(maybe_resolved)\n    }\n\n    fn try_as_tuple(&self, type_application: &FullTypeApplication) -> Result<Option<ResolvedType>> {\n        let type_decl = &type_application.type_decl;\n        if !has_tuple_format(&type_decl.type_field) {\n            return Ok(None);\n        }\n        let inner_types = self.resolve_multiple(&type_decl.components)?;\n\n        Ok(Some(ResolvedType::Tuple(inner_types)))\n    }\n\n    fn try_as_primitive_type(\n        &self,\n        type_decl: &FullTypeApplication,\n    ) -> Result<Option<ResolvedType>> {\n        let type_field = &type_decl.type_decl.type_field;\n\n        let maybe_resolved = match type_field.as_str() {\n            \"()\" => Some(ResolvedType::Unit),\n            \"bool\" | \"u8\" | \"u16\" | \"u32\" | \"u64\" => {\n                let path = format!(\"::core::primitive::{type_field}\");\n                let type_path = TypePath::new(path).expect(\"to be a valid path\");\n\n                Some(ResolvedType::Primitive(type_path))\n            }\n            \"struct std::u128::U128\" | \"struct U128\" => {\n                let u128_path = TypePath::new(\"::core::primitive::u128\").expect(\"is correct\");\n                Some(ResolvedType::Primitive(u128_path))\n            }\n            \"u256\" => {\n                let u256_path = TypePath::new(\"::fuels::types::U256\").expect(\"is correct\");\n                Some(ResolvedType::Primitive(u256_path))\n            }\n            _ => None,\n        };\n\n        Ok(maybe_resolved)\n    }\n\n    fn try_as_bits256(\n        &self,\n        type_application: &FullTypeApplication,\n    ) -> Result<Option<ResolvedType>> {\n        if type_application.type_decl.type_field != \"b256\" {\n            return Ok(None);\n        }\n\n        let path = TypePath::new(\"::fuels::types::Bits256\").expect(\"to be valid\");\n        Ok(Some(ResolvedType::StructOrEnum {\n            path,\n            generics: vec![],\n        }))\n    }\n\n    fn try_as_raw_slice(\n        &self,\n        type_application: &FullTypeApplication,\n    ) -> Result<Option<ResolvedType>> {\n        if type_application.type_decl.type_field != \"raw untyped slice\" {\n            return Ok(None);\n        }\n\n        let path = TypePath::new(\"::fuels::types::RawSlice\").expect(\"this is a valid TypePath\");\n        Ok(Some(ResolvedType::StructOrEnum {\n            path,\n            generics: vec![],\n        }))\n    }\n\n    fn try_as_custom_type(\n        &self,\n        type_application: &FullTypeApplication,\n    ) -> Result<Option<ResolvedType>> {\n        let type_decl = &type_application.type_decl;\n\n        if !type_decl.is_custom_type() {\n            return Ok(None);\n        }\n\n        let original_path = type_decl.custom_type_path()?;\n\n        let used_path = sdk_provided_custom_types_lookup()\n            .get(&original_path)\n            .cloned()\n            .unwrap_or_else(|| original_path.relative_path_from(&self.current_mod));\n\n        let generics = self.resolve_multiple(&type_application.type_arguments)?;\n\n        Ok(Some(ResolvedType::StructOrEnum {\n            path: used_path,\n            generics,\n        }))\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use std::{collections::HashMap, str::FromStr};\n\n    use fuel_abi_types::{\n        abi::{\n            full_program::FullTypeDeclaration,\n            unified_program::{UnifiedTypeApplication, UnifiedTypeDeclaration},\n        },\n        utils::ident,\n    };\n\n    use super::*;\n\n    #[test]\n    fn correctly_extracts_used_generics() {\n        let resolved_type = ResolvedType::StructOrEnum {\n            path: Default::default(),\n            generics: vec![\n                ResolvedType::Tuple(vec![ResolvedType::Array(\n                    Box::new(ResolvedType::StructOrEnum {\n                        path: Default::default(),\n                        generics: vec![\n                            ResolvedType::Generic(GenericType::Named(ident(\"A\"))),\n                            ResolvedType::Generic(GenericType::Constant(10)),\n                        ],\n                    }),\n                    2,\n                )]),\n                ResolvedType::Generic(GenericType::Named(ident(\"B\"))),\n            ],\n        };\n\n        let generics = resolved_type.generics();\n\n        assert_eq!(\n            generics,\n            vec![\n                GenericType::Named(ident(\"A\")),\n                GenericType::Constant(10),\n                GenericType::Named(ident(\"B\"))\n            ]\n        )\n    }\n\n    fn test_resolve_first_type(\n        expected: &str,\n        type_declarations: &[UnifiedTypeDeclaration],\n    ) -> Result<()> {\n        let types = type_declarations\n            .iter()\n            .map(|td| (td.type_id, td.clone()))\n            .collect::<HashMap<_, _>>();\n        let type_application = UnifiedTypeApplication {\n            type_id: type_declarations[0].type_id,\n            ..Default::default()\n        };\n\n        let application = FullTypeApplication::from_counterpart(&type_application, &types);\n        let resolved_type = TypeResolver::default()\n            .resolve(&application)\n            .map_err(|e| e.combine(error!(\"failed to resolve {:?}\", type_application)))?;\n        let actual = resolved_type.to_token_stream().to_string();\n\n        let expected = TokenStream::from_str(expected).unwrap().to_string();\n        assert_eq!(actual, expected);\n\n        Ok(())\n    }\n\n    fn test_resolve_primitive_type(type_field: &str, expected: &str) -> Result<()> {\n        test_resolve_first_type(\n            expected,\n            &[UnifiedTypeDeclaration {\n                type_id: 0,\n                type_field: type_field.to_string(),\n                ..Default::default()\n            }],\n        )\n    }\n\n    #[test]\n    fn test_resolve_u8() -> Result<()> {\n        test_resolve_primitive_type(\"u8\", \"::core::primitive::u8\")\n    }\n\n    #[test]\n    fn test_resolve_u16() -> Result<()> {\n        test_resolve_primitive_type(\"u16\", \"::core::primitive::u16\")\n    }\n\n    #[test]\n    fn test_resolve_u32() -> Result<()> {\n        test_resolve_primitive_type(\"u32\", \"::core::primitive::u32\")\n    }\n\n    #[test]\n    fn test_resolve_u64() -> Result<()> {\n        test_resolve_primitive_type(\"u64\", \"::core::primitive::u64\")\n    }\n\n    #[test]\n    fn test_resolve_bool() -> Result<()> {\n        test_resolve_primitive_type(\"bool\", \"::core::primitive::bool\")\n    }\n\n    #[test]\n    fn test_resolve_b256() -> Result<()> {\n        test_resolve_primitive_type(\"b256\", \"::fuels::types::Bits256\")\n    }\n\n    #[test]\n    fn test_resolve_unit() -> Result<()> {\n        test_resolve_primitive_type(\"()\", \"()\")\n    }\n\n    #[test]\n    fn test_resolve_array() -> Result<()> {\n        test_resolve_first_type(\n            \"[::core::primitive::u8 ; 3usize]\",\n            &[\n                UnifiedTypeDeclaration {\n                    type_id: 0,\n                    type_field: \"[u8; 3]\".to_string(),\n                    components: Some(vec![UnifiedTypeApplication {\n                        type_id: 1,\n                        ..Default::default()\n                    }]),\n                    ..Default::default()\n                },\n                UnifiedTypeDeclaration {\n                    type_id: 1,\n                    type_field: \"u8\".to_string(),\n                    ..Default::default()\n                },\n            ],\n        )\n    }\n\n    #[test]\n    fn test_resolve_vector() -> Result<()> {\n        test_resolve_first_type(\n            \":: std :: vec :: Vec\",\n            &[\n                UnifiedTypeDeclaration {\n                    type_id: 0,\n                    type_field: \"struct std::vec::Vec\".to_string(),\n                    components: Some(vec![\n                        UnifiedTypeApplication {\n                            name: \"buf\".to_string(),\n                            type_id: 2,\n                            type_arguments: Some(vec![UnifiedTypeApplication {\n                                type_id: 1,\n                                ..Default::default()\n                            }]),\n                            error_message: None,\n                        },\n                        UnifiedTypeApplication {\n                            name: \"len\".to_string(),\n                            type_id: 3,\n                            ..Default::default()\n                        },\n                    ]),\n                    type_parameters: Some(vec![1]),\n                    alias_of: None,\n                },\n                UnifiedTypeDeclaration {\n                    type_id: 1,\n                    type_field: \"generic T\".to_string(),\n                    ..Default::default()\n                },\n                UnifiedTypeDeclaration {\n                    type_id: 2,\n                    type_field: \"raw untyped ptr\".to_string(),\n                    ..Default::default()\n                },\n                UnifiedTypeDeclaration {\n                    type_id: 3,\n                    type_field: \"struct std::vec::RawVec\".to_string(),\n                    components: Some(vec![\n                        UnifiedTypeApplication {\n                            name: \"ptr\".to_string(),\n                            type_id: 2,\n                            ..Default::default()\n                        },\n                        UnifiedTypeApplication {\n                            name: \"cap\".to_string(),\n                            type_id: 4,\n                            ..Default::default()\n                        },\n                    ]),\n                    type_parameters: Some(vec![1]),\n                    alias_of: None,\n                },\n                UnifiedTypeDeclaration {\n                    type_id: 4,\n                    type_field: \"u64\".to_string(),\n                    ..Default::default()\n                },\n                UnifiedTypeDeclaration {\n                    type_id: 5,\n                    type_field: \"u8\".to_string(),\n                    ..Default::default()\n                },\n            ],\n        )\n    }\n\n    #[test]\n    fn test_resolve_bytes() -> Result<()> {\n        test_resolve_first_type(\n            \":: fuels :: types :: Bytes\",\n            &[\n                UnifiedTypeDeclaration {\n                    type_id: 0,\n                    type_field: \"struct String\".to_string(),\n                    components: Some(vec![UnifiedTypeApplication {\n                        name: \"bytes\".to_string(),\n                        type_id: 1,\n                        ..Default::default()\n                    }]),\n                    ..Default::default()\n                },\n                UnifiedTypeDeclaration {\n                    type_id: 0,\n                    type_field: \"struct std::bytes::Bytes\".to_string(),\n                    components: Some(vec![\n                        UnifiedTypeApplication {\n                            name: \"buf\".to_string(),\n                            type_id: 1,\n                            ..Default::default()\n                        },\n                        UnifiedTypeApplication {\n                            name: \"len\".to_string(),\n                            type_id: 3,\n                            ..Default::default()\n                        },\n                    ]),\n                    ..Default::default()\n                },\n                UnifiedTypeDeclaration {\n                    type_id: 1,\n                    type_field: \"struct std::bytes::RawBytes\".to_string(),\n                    components: Some(vec![\n                        UnifiedTypeApplication {\n                            name: \"ptr\".to_string(),\n                            type_id: 2,\n                            ..Default::default()\n                        },\n                        UnifiedTypeApplication {\n                            name: \"cap\".to_string(),\n                            type_id: 3,\n                            ..Default::default()\n                        },\n                    ]),\n                    ..Default::default()\n                },\n                UnifiedTypeDeclaration {\n                    type_id: 2,\n                    type_field: \"raw untyped ptr\".to_string(),\n                    ..Default::default()\n                },\n                UnifiedTypeDeclaration {\n                    type_id: 3,\n                    type_field: \"u64\".to_string(),\n                    ..Default::default()\n                },\n            ],\n        )\n    }\n\n    #[test]\n    fn test_resolve_std_string() -> Result<()> {\n        test_resolve_first_type(\n            \":: std :: string :: String\",\n            &[\n                UnifiedTypeDeclaration {\n                    type_id: 0,\n                    type_field: \"struct std::string::String\".to_string(),\n                    components: Some(vec![UnifiedTypeApplication {\n                        name: \"bytes\".to_string(),\n                        type_id: 1,\n                        ..Default::default()\n                    }]),\n                    ..Default::default()\n                },\n                UnifiedTypeDeclaration {\n                    type_id: 1,\n                    type_field: \"struct std::bytes::Bytes\".to_string(),\n                    components: Some(vec![\n                        UnifiedTypeApplication {\n                            name: \"buf\".to_string(),\n                            type_id: 2,\n                            ..Default::default()\n                        },\n                        UnifiedTypeApplication {\n                            name: \"len\".to_string(),\n                            type_id: 4,\n                            ..Default::default()\n                        },\n                    ]),\n                    ..Default::default()\n                },\n                UnifiedTypeDeclaration {\n                    type_id: 2,\n                    type_field: \"struct std::bytes::RawBytes\".to_string(),\n                    components: Some(vec![\n                        UnifiedTypeApplication {\n                            name: \"ptr\".to_string(),\n                            type_id: 3,\n                            ..Default::default()\n                        },\n                        UnifiedTypeApplication {\n                            name: \"cap\".to_string(),\n                            type_id: 4,\n                            ..Default::default()\n                        },\n                    ]),\n                    ..Default::default()\n                },\n                UnifiedTypeDeclaration {\n                    type_id: 3,\n                    type_field: \"raw untyped ptr\".to_string(),\n                    ..Default::default()\n                },\n                UnifiedTypeDeclaration {\n                    type_id: 4,\n                    type_field: \"u64\".to_string(),\n                    ..Default::default()\n                },\n            ],\n        )\n    }\n\n    #[test]\n    fn test_resolve_static_str() -> Result<()> {\n        test_resolve_primitive_type(\"str[3]\", \":: fuels :: types :: SizedAsciiString < 3usize >\")\n    }\n\n    #[test]\n    fn test_resolve_struct() -> Result<()> {\n        test_resolve_first_type(\n            \"self :: SomeStruct\",\n            &[\n                UnifiedTypeDeclaration {\n                    type_id: 0,\n                    type_field: \"struct SomeStruct\".to_string(),\n                    components: Some(vec![\n                        UnifiedTypeApplication {\n                            name: \"foo\".to_string(),\n                            type_id: 1,\n                            ..Default::default()\n                        },\n                        UnifiedTypeApplication {\n                            name: \"bar\".to_string(),\n                            type_id: 2,\n                            ..Default::default()\n                        },\n                    ]),\n                    type_parameters: Some(vec![1]),\n                    alias_of: None,\n                },\n                UnifiedTypeDeclaration {\n                    type_id: 1,\n                    type_field: \"generic T\".to_string(),\n                    ..Default::default()\n                },\n                UnifiedTypeDeclaration {\n                    type_id: 2,\n                    type_field: \"u8\".to_string(),\n                    ..Default::default()\n                },\n            ],\n        )\n    }\n\n    #[test]\n    fn test_resolve_enum() -> Result<()> {\n        test_resolve_first_type(\n            \"self :: SomeEnum\",\n            &[\n                UnifiedTypeDeclaration {\n                    type_id: 0,\n                    type_field: \"enum SomeEnum\".to_string(),\n                    components: Some(vec![\n                        UnifiedTypeApplication {\n                            name: \"foo\".to_string(),\n                            type_id: 1,\n                            ..Default::default()\n                        },\n                        UnifiedTypeApplication {\n                            name: \"bar\".to_string(),\n                            type_id: 2,\n                            ..Default::default()\n                        },\n                    ]),\n                    type_parameters: Some(vec![1]),\n                    alias_of: None,\n                },\n                UnifiedTypeDeclaration {\n                    type_id: 1,\n                    type_field: \"generic T\".to_string(),\n                    ..Default::default()\n                },\n                UnifiedTypeDeclaration {\n                    type_id: 2,\n                    type_field: \"u8\".to_string(),\n                    ..Default::default()\n                },\n            ],\n        )\n    }\n\n    #[test]\n    fn test_resolve_tuple() -> Result<()> {\n        test_resolve_first_type(\n            \"(::core::primitive::u8, ::core::primitive::u16, ::core::primitive::bool, T,)\",\n            &[\n                UnifiedTypeDeclaration {\n                    type_id: 0,\n                    type_field: \"(u8, u16, bool, T)\".to_string(),\n                    components: Some(vec![\n                        UnifiedTypeApplication {\n                            type_id: 1,\n                            ..Default::default()\n                        },\n                        UnifiedTypeApplication {\n                            type_id: 2,\n                            ..Default::default()\n                        },\n                        UnifiedTypeApplication {\n                            type_id: 3,\n                            ..Default::default()\n                        },\n                        UnifiedTypeApplication {\n                            type_id: 4,\n                            ..Default::default()\n                        },\n                    ]),\n                    type_parameters: Some(vec![4]),\n                    alias_of: None,\n                },\n                UnifiedTypeDeclaration {\n                    type_id: 1,\n                    type_field: \"u8\".to_string(),\n                    ..Default::default()\n                },\n                UnifiedTypeDeclaration {\n                    type_id: 2,\n                    type_field: \"u16\".to_string(),\n                    ..Default::default()\n                },\n                UnifiedTypeDeclaration {\n                    type_id: 3,\n                    type_field: \"bool\".to_string(),\n                    ..Default::default()\n                },\n                UnifiedTypeDeclaration {\n                    type_id: 4,\n                    type_field: \"generic T\".to_string(),\n                    ..Default::default()\n                },\n            ],\n        )\n    }\n\n    #[test]\n    fn custom_types_uses_correct_path_for_sdk_provided_types() {\n        let resolver = TypeResolver::default();\n        for (type_path, expected_path) in sdk_provided_custom_types_lookup() {\n            // given\n            let type_application = given_fn_arg_of_custom_type(&type_path);\n\n            // when\n            let resolved_type = resolver.resolve(&type_application).unwrap();\n\n            // then\n            let expected_type_name = expected_path.into_token_stream();\n            assert_eq!(\n                resolved_type.to_token_stream().to_string(),\n                expected_type_name.to_string()\n            );\n        }\n    }\n\n    fn given_fn_arg_of_custom_type(type_path: &TypePath) -> FullTypeApplication {\n        FullTypeApplication {\n            name: \"some_arg\".to_string(),\n            type_decl: FullTypeDeclaration {\n                type_field: format!(\"struct {type_path}\"),\n                components: vec![],\n                type_parameters: vec![],\n                alias_of: None,\n            },\n            type_arguments: vec![],\n            error_message: None,\n        }\n    }\n}\n"
  },
  {
    "path": "packages/fuels-code-gen/src/program_bindings/utils.rs",
    "content": "use std::collections::{HashMap, HashSet};\n\nuse fuel_abi_types::abi::full_program::FullTypeApplication;\nuse inflector::Inflector;\nuse itertools::Itertools;\nuse proc_macro2::{Ident, TokenStream};\nuse quote::quote;\n\nuse crate::{\n    error::Result,\n    program_bindings::resolved_type::{GenericType, ResolvedType, TypeResolver},\n    utils::{self, TypePath, safe_ident},\n};\n\n#[derive(Debug)]\npub(crate) struct Component {\n    pub(crate) ident: Ident,\n    pub(crate) resolved_type: ResolvedType,\n    pub(crate) error_message: Option<String>,\n}\n\n#[derive(Debug)]\npub(crate) struct Components {\n    components: Vec<Component>,\n}\n\nimpl Components {\n    pub fn new(\n        type_applications: &[FullTypeApplication],\n        snake_case: bool,\n        parent_module: TypePath,\n    ) -> Result<Self> {\n        let type_resolver = TypeResolver::new(parent_module);\n        let components = type_applications\n            .iter()\n            .map(|type_application| {\n                let name = if snake_case {\n                    type_application.name.to_snake_case()\n                } else {\n                    type_application.name.to_owned()\n                };\n\n                let ident = safe_ident(&name);\n                let resolved_type = type_resolver.resolve(type_application)?;\n                let error_message = type_application.error_message.clone();\n\n                Result::Ok(Component {\n                    ident,\n                    resolved_type,\n                    error_message,\n                })\n            })\n            .collect::<Result<Vec<_>>>()?;\n\n        Ok(Self { components })\n    }\n\n    pub fn has_error_messages(&self) -> bool {\n        self.components\n            .iter()\n            .all(|component| component.error_message.is_some())\n    }\n\n    pub fn iter(&self) -> impl Iterator<Item = &Component> {\n        self.components.iter()\n    }\n\n    pub fn is_empty(&self) -> bool {\n        self.components.is_empty()\n    }\n\n    pub fn as_enum_variants(&self) -> impl Iterator<Item = TokenStream> + '_ {\n        self.components.iter().map(\n            |Component {\n                 ident,\n                 resolved_type,\n                 ..\n             }| {\n                if let ResolvedType::Unit = resolved_type {\n                    quote! {#ident}\n                } else {\n                    quote! {#ident(#resolved_type)}\n                }\n            },\n        )\n    }\n\n    pub fn generate_parameters_for_unused_generics(\n        &self,\n        declared_generics: &[Ident],\n    ) -> (Vec<Ident>, Vec<TokenStream>) {\n        self.unused_named_generics(declared_generics)\n            .enumerate()\n            .map(|(index, generic)| {\n                let ident = utils::ident(&format!(\"_unused_generic_{index}\"));\n                let ty = quote! {::core::marker::PhantomData<#generic>};\n                (ident, ty)\n            })\n            .unzip()\n    }\n\n    pub fn generate_variant_for_unused_generics(\n        &self,\n        declared_generics: &[Ident],\n    ) -> Option<TokenStream> {\n        let phantom_types = self\n            .unused_named_generics(declared_generics)\n            .map(|generic| {\n                quote! {::core::marker::PhantomData<#generic>}\n            })\n            .collect_vec();\n\n        (!phantom_types.is_empty()).then(|| {\n            quote! {\n                #[Ignore]\n                IgnoreMe(#(#phantom_types),*)\n            }\n        })\n    }\n\n    fn named_generics(&self) -> HashSet<Ident> {\n        self.components\n            .iter()\n            .flat_map(|Component { resolved_type, .. }| resolved_type.generics())\n            .filter_map(|generic_type| {\n                if let GenericType::Named(name) = generic_type {\n                    Some(name)\n                } else {\n                    None\n                }\n            })\n            .collect()\n    }\n\n    fn unused_named_generics<'a>(\n        &'a self,\n        declared_generics: &'a [Ident],\n    ) -> impl Iterator<Item = &'a Ident> {\n        let used_generics = self.named_generics();\n        declared_generics\n            .iter()\n            .filter(move |generic| !used_generics.contains(generic))\n    }\n}\n\npub(crate) fn tokenize_generics(generics: &[Ident]) -> (TokenStream, TokenStream) {\n    if generics.is_empty() {\n        return (Default::default(), Default::default());\n    }\n\n    (\n        quote! {<#(#generics,)*>},\n        quote! {<#(#generics: ::fuels::core::traits::Tokenizable + ::fuels::core::traits::Parameterize, )*>},\n    )\n}\n\npub(crate) fn sdk_provided_custom_types_lookup() -> HashMap<TypePath, TypePath> {\n    [\n        (\"std::address::Address\", \"::fuels::types::Address\"),\n        (\"std::asset_id::AssetId\", \"::fuels::types::AssetId\"),\n        (\"std::b512::B512\", \"::fuels::types::B512\"),\n        (\"std::bytes::Bytes\", \"::fuels::types::Bytes\"),\n        (\"std::contract_id::ContractId\", \"::fuels::types::ContractId\"),\n        (\"std::identity::Identity\", \"::fuels::types::Identity\"),\n        (\"std::option::Option\", \"::core::option::Option\"),\n        (\"std::result::Result\", \"::core::result::Result\"),\n        (\"std::string::String\", \"::std::string::String\"),\n        (\"std::vec::Vec\", \"::std::vec::Vec\"),\n        (\n            \"std::vm::evm::evm_address::EvmAddress\",\n            \"::fuels::types::EvmAddress\",\n        ),\n    ]\n    .into_iter()\n    .map(|(original_type_path, provided_type_path)| {\n        let msg = \"known at compile time to be correctly formed\";\n        (\n            TypePath::new(original_type_path).expect(msg),\n            TypePath::new(provided_type_path).expect(msg),\n        )\n    })\n    .collect()\n}\n\n#[cfg(test)]\nmod tests {\n    use fuel_abi_types::abi::full_program::FullTypeDeclaration;\n\n    use super::*;\n\n    #[test]\n    fn respects_snake_case_flag() -> Result<()> {\n        // given\n        let type_application = type_application_named(\"WasNotSnakeCased\");\n\n        // when\n        let sut = Components::new(&[type_application], true, TypePath::default())?;\n\n        // then\n        assert_eq!(sut.iter().next().unwrap().ident, \"was_not_snake_cased\");\n\n        Ok(())\n    }\n\n    #[test]\n    fn avoids_collisions_with_reserved_keywords() -> Result<()> {\n        {\n            let type_application = type_application_named(\"if\");\n\n            let sut = Components::new(&[type_application], false, TypePath::default())?;\n\n            assert_eq!(sut.iter().next().unwrap().ident, \"if_\");\n        }\n\n        {\n            let type_application = type_application_named(\"let\");\n\n            let sut = Components::new(&[type_application], false, TypePath::default())?;\n\n            assert_eq!(sut.iter().next().unwrap().ident, \"let_\");\n        }\n\n        Ok(())\n    }\n\n    fn type_application_named(name: &str) -> FullTypeApplication {\n        FullTypeApplication {\n            name: name.to_string(),\n            type_decl: FullTypeDeclaration {\n                type_field: \"u64\".to_string(),\n                components: vec![],\n                type_parameters: vec![],\n                alias_of: None,\n            },\n            type_arguments: vec![],\n            error_message: None,\n        }\n    }\n}\n"
  },
  {
    "path": "packages/fuels-code-gen/src/program_bindings.rs",
    "content": "mod abigen;\nmod custom_types;\nmod generated_code;\nmod resolved_type;\nmod utils;\n\npub use abigen::{Abi, Abigen, AbigenTarget, ProgramType};\n"
  },
  {
    "path": "packages/fuels-code-gen/src/utils.rs",
    "content": "pub use fuel_abi_types::utils::{TypePath, ident, safe_ident};\n\npub fn encode_fn_selector(name: &str) -> Vec<u8> {\n    let bytes = name.as_bytes().to_vec();\n    let len = bytes.len() as u64;\n\n    [len.to_be_bytes().to_vec(), bytes].concat()\n}\n"
  },
  {
    "path": "packages/fuels-core/Cargo.toml",
    "content": "[package]\nname = \"fuels-core\"\nversion = { workspace = true }\nauthors = { workspace = true }\nedition = { workspace = true }\nhomepage = { workspace = true }\nlicense = { workspace = true }\nrepository = { workspace = true }\nrust-version = { workspace = true }\ndescription = \"Fuel Rust SDK core.\"\n\n[dependencies]\nasync-trait = { workspace = true, default-features = false }\nchrono = { workspace = true }\nfuel-abi-types = { workspace = true }\nfuel-asm = { workspace = true }\nfuels-code-gen = { workspace = true }\nfuel-core-chain-config = { workspace = true }\nfuel-core-client = { workspace = true, optional = true }\nfuel-core-types = { workspace = true }\nfuel-crypto = { workspace = true }\nfuel-tx = { workspace = true }\nfuel-types = { workspace = true, features = [\"default\"] }\nfuel-vm = { workspace = true }\nfuels-macros = { workspace = true }\nhex = { workspace = true, features = [\"std\"] }\nitertools = { workspace = true }\npostcard = { version = \"1\", default-features = true, features = [\"alloc\"] }\nserde = { workspace = true, features = [\"derive\"] }\nserde_json = { workspace = true, default-features = true }\nsha2 = { workspace = true }\nthiserror = { workspace = true, default-features = false }\nuint = { workspace = true, default-features = false }\nauto_impl = { workspace = true }\n\n[dev-dependencies]\nfuel-tx = { workspace = true, features = [\"test-helpers\", \"random\"] }\ntokio = { workspace = true, features = [\"test-util\", \"macros\"] }\n\n[features]\ndefault = [\"std\"]\nstd = [\"dep:fuel-core-client\", \"fuel-core-types/std\"]\nfault-proving = [\"fuel-core-chain-config/fault-proving\", \"fuel-core-types/fault-proving\", \"fuel-core-client?/fault-proving\"]\n"
  },
  {
    "path": "packages/fuels-core/src/codec/abi_decoder/bounded_decoder.rs",
    "content": "use crate::{\n    codec::{\n        DecoderConfig,\n        utils::{CodecDirection, CounterWithLimit},\n    },\n    types::{\n        StaticStringToken, Token, U256,\n        errors::{Result, error},\n        param_types::{EnumVariants, NamedParamType, ParamType},\n    },\n};\nuse std::iter::repeat_n;\nuse std::{io::Read, str};\n\n/// Is used to decode bytes into `Token`s from which types implementing `Tokenizable` can be\n/// instantiated. Implements decoding limits to control resource usage.\npub(crate) struct BoundedDecoder {\n    depth_tracker: CounterWithLimit,\n    token_tracker: CounterWithLimit,\n}\n\nimpl BoundedDecoder {\n    pub(crate) fn new(config: DecoderConfig) -> Self {\n        let depth_tracker =\n            CounterWithLimit::new(config.max_depth, \"depth\", CodecDirection::Decoding);\n        let token_tracker =\n            CounterWithLimit::new(config.max_tokens, \"token\", CodecDirection::Decoding);\n        Self {\n            depth_tracker,\n            token_tracker,\n        }\n    }\n\n    pub(crate) fn decode<R: Read>(\n        &mut self,\n        param_type: &ParamType,\n        bytes: &mut R,\n    ) -> Result<Token> {\n        self.decode_param(param_type, bytes)\n    }\n\n    pub(crate) fn decode_multiple<R: Read>(\n        &mut self,\n        param_types: &[ParamType],\n        bytes: &mut R,\n    ) -> Result<Vec<Token>> {\n        self.decode_params(param_types, bytes)\n    }\n\n    fn run_w_depth_tracking(\n        &mut self,\n        decoder: impl FnOnce(&mut Self) -> Result<Token>,\n    ) -> Result<Token> {\n        self.depth_tracker.increase()?;\n        let res = decoder(self);\n        self.depth_tracker.decrease();\n\n        res\n    }\n\n    fn decode_param<R: Read>(&mut self, param_type: &ParamType, bytes: &mut R) -> Result<Token> {\n        self.token_tracker.increase()?;\n        match param_type {\n            ParamType::Unit => Ok(Token::Unit),\n            ParamType::Bool => decode(bytes, |[value]| Token::Bool(value != 0)),\n            ParamType::U8 => decode(bytes, |[value]| Token::U8(value)),\n            ParamType::U16 => decode(bytes, |value| Token::U16(u16::from_be_bytes(value))),\n            ParamType::U32 => decode(bytes, |value| Token::U32(u32::from_be_bytes(value))),\n            ParamType::U64 => decode(bytes, |value| Token::U64(u64::from_be_bytes(value))),\n            ParamType::U128 => decode(bytes, |value| Token::U128(u128::from_be_bytes(value))),\n            ParamType::U256 => decode(bytes, |value| Token::U256(U256::from(value))),\n            ParamType::B256 => decode(bytes, Token::B256),\n            ParamType::Bytes => Ok(Token::Bytes(decode_slice(bytes)?)),\n            ParamType::String => Self::decode_std_string(bytes),\n            ParamType::RawSlice => Ok(Token::RawSlice(decode_slice(bytes)?)),\n            ParamType::StringArray(length) => Self::decode_string_array(bytes, *length),\n            ParamType::StringSlice => Self::decode_string_slice(bytes),\n            ParamType::Tuple(param_types) => {\n                self.run_w_depth_tracking(|ctx| ctx.decode_tuple(param_types, bytes))\n            }\n            ParamType::Array(param_type, length) => {\n                self.run_w_depth_tracking(|ctx| ctx.decode_array(param_type, bytes, *length))\n            }\n            ParamType::Vector(param_type) => {\n                self.run_w_depth_tracking(|ctx| ctx.decode_vector(param_type, bytes))\n            }\n\n            ParamType::Struct { fields, .. } => {\n                self.run_w_depth_tracking(|ctx| ctx.decode_struct(fields, bytes))\n            }\n            ParamType::Enum { enum_variants, .. } => {\n                self.run_w_depth_tracking(|ctx| ctx.decode_enum(enum_variants, bytes))\n            }\n        }\n    }\n\n    fn decode_std_string<R: Read>(bytes: &mut R) -> Result<Token> {\n        let data = decode_slice(bytes)?;\n        let string = str::from_utf8(&data)?.to_string();\n        Ok(Token::String(string))\n    }\n\n    fn decode_string_array<R: Read>(bytes: &mut R, length: usize) -> Result<Token> {\n        let data = decode_sized(bytes, length)?;\n        let decoded = str::from_utf8(&data)?.to_string();\n        Ok(Token::StringArray(StaticStringToken::new(\n            decoded,\n            Some(length),\n        )))\n    }\n\n    fn decode_string_slice<R: Read>(bytes: &mut R) -> Result<Token> {\n        let data = decode_slice(bytes)?;\n        let decoded = str::from_utf8(&data)?.to_string();\n        Ok(Token::StringSlice(StaticStringToken::new(decoded, None)))\n    }\n\n    fn decode_tuple<R: Read>(&mut self, param_types: &[ParamType], bytes: &mut R) -> Result<Token> {\n        Ok(Token::Tuple(self.decode_params(param_types, bytes)?))\n    }\n\n    fn decode_array<R: Read>(\n        &mut self,\n        param_type: &ParamType,\n        bytes: &mut R,\n        length: usize,\n    ) -> Result<Token> {\n        Ok(Token::Array(\n            self.decode_params(repeat_n(param_type, length), bytes)?,\n        ))\n    }\n\n    fn decode_vector<R: Read>(&mut self, param_type: &ParamType, bytes: &mut R) -> Result<Token> {\n        let length = decode_len(bytes)?;\n        Ok(Token::Vector(\n            self.decode_params(repeat_n(param_type, length), bytes)?,\n        ))\n    }\n\n    fn decode_struct<R: Read>(\n        &mut self,\n        fields: &[NamedParamType],\n        bytes: &mut R,\n    ) -> Result<Token> {\n        Ok(Token::Struct(\n            self.decode_params(fields.iter().map(|(_, pt)| pt), bytes)?,\n        ))\n    }\n\n    fn decode_enum<R: Read>(\n        &mut self,\n        enum_variants: &EnumVariants,\n        bytes: &mut R,\n    ) -> Result<Token> {\n        let discriminant = decode(bytes, u64::from_be_bytes)?;\n        let (_, selected_variant) = enum_variants.select_variant(discriminant)?;\n\n        let decoded = self.decode_param(selected_variant, bytes)?;\n\n        Ok(Token::Enum(Box::new((\n            discriminant,\n            decoded,\n            enum_variants.clone(),\n        ))))\n    }\n\n    fn decode_params<'a, R: Read>(\n        &mut self,\n        param_types: impl IntoIterator<Item = &'a ParamType>,\n        bytes: &mut R,\n    ) -> Result<Vec<Token>> {\n        let mut tokens = vec![];\n        for param_type in param_types {\n            tokens.push(self.decode_param(param_type, bytes)?);\n        }\n        Ok(tokens)\n    }\n}\n\n/// Decodes a fixed-size array of bytes using a converter function.\nfn decode<const SIZE: usize, R: Read, Out>(\n    bytes: &mut R,\n    f: impl FnOnce([u8; SIZE]) -> Out,\n) -> Result<Out> {\n    let mut buffer = [0u8; SIZE];\n    bytes.read_exact(&mut buffer)?;\n    Ok(f(buffer))\n}\n\n/// Reads a byte array with known size.\nfn decode_sized<R: Read>(bytes: &mut R, len: usize) -> Result<Vec<u8>> {\n    let mut data = vec![0; len];\n    bytes.read_exact(&mut data)?;\n    Ok(data)\n}\n\n/// Decodes a length prefix.\nfn decode_len<R: Read>(bytes: &mut R) -> Result<usize> {\n    let len_u64 = decode(bytes, u64::from_be_bytes)?;\n    let len: usize = len_u64\n        .try_into()\n        .map_err(|_| error!(Other, \"could not convert `u64` to `usize`\"))?;\n    Ok(len)\n}\n\n/// Decodes a size-prefixed slice.\nfn decode_slice<R: Read>(bytes: &mut R) -> Result<Vec<u8>> {\n    let len = decode_len(bytes)?;\n    let mut data = vec![0; len];\n    bytes.read_exact(&mut data)?;\n    Ok(data)\n}\n"
  },
  {
    "path": "packages/fuels-core/src/codec/abi_decoder/decode_as_debug_str.rs",
    "content": "use std::iter::zip;\n\nuse crate::types::{\n    Token,\n    errors::{Result, error},\n    param_types::ParamType,\n};\n\nfn inner_types_debug(tokens: &[Token], inner_type: &ParamType, join_str: &str) -> Result<String> {\n    let inner_types_log = tokens\n        .iter()\n        .map(|token| decode_as_debug_str(inner_type, token))\n        .collect::<Result<Vec<_>>>()?\n        .join(join_str);\n\n    Ok(inner_types_log)\n}\n\npub(crate) fn decode_as_debug_str(param_type: &ParamType, token: &Token) -> Result<String> {\n    let result = match (param_type, token) {\n        (ParamType::Unit, Token::Unit) => \"()\".to_string(),\n        (ParamType::Bool, Token::Bool(val)) => val.to_string(),\n        (ParamType::U8, Token::U8(val)) => val.to_string(),\n        (ParamType::U16, Token::U16(val)) => val.to_string(),\n        (ParamType::U32, Token::U32(val)) => val.to_string(),\n        (ParamType::U64, Token::U64(val)) => val.to_string(),\n        (ParamType::U128, Token::U128(val)) => val.to_string(),\n        (ParamType::U256, Token::U256(val)) => val.to_string(),\n        (ParamType::B256, Token::B256(val)) => {\n            format!(\"Bits256({val:?})\")\n        }\n        (ParamType::Bytes, Token::Bytes(val)) => {\n            format!(\"Bytes({val:?})\")\n        }\n        (ParamType::String, Token::String(val)) => val.clone(),\n        (ParamType::RawSlice, Token::RawSlice(val)) => {\n            format!(\"RawSlice({val:?})\")\n        }\n        (ParamType::StringArray(..), Token::StringArray(str_token)) => {\n            format!(\"SizedAsciiString {{ data: \\\"{}\\\" }}\", str_token.data)\n        }\n        (ParamType::StringSlice, Token::StringSlice(str_token)) => {\n            format!(\"AsciiString {{ data: \\\"{}\\\" }}\", str_token.data)\n        }\n        (ParamType::Tuple(types), Token::Tuple(tokens)) => {\n            let elements = zip(types, tokens)\n                .map(|(ptype, token)| decode_as_debug_str(ptype, token))\n                .collect::<Result<Vec<_>>>()?\n                .join(\", \");\n\n            format!(\"({elements})\")\n        }\n        (ParamType::Array(inner_type, _), Token::Array(tokens)) => {\n            let elements = inner_types_debug(tokens, inner_type, \", \")?;\n            format!(\"[{elements}]\")\n        }\n        (ParamType::Vector(inner_type), Token::Vector(tokens)) => {\n            let elements = inner_types_debug(tokens, inner_type, \", \")?;\n            format!(\"[{elements}]\")\n        }\n        (ParamType::Struct { name, fields, .. }, Token::Struct(field_tokens)) => {\n            let fields = zip(fields, field_tokens)\n                .map(|((field_name, param_type), token)| -> Result<_> {\n                    Ok(format!(\n                        \"{field_name}: {}\",\n                        decode_as_debug_str(param_type, token)?\n                    ))\n                })\n                .collect::<Result<Vec<_>>>()?\n                .join(\", \");\n            format!(\"{name} {{ {fields} }}\")\n        }\n        (ParamType::Enum { .. }, Token::Enum(selector)) => {\n            let (discriminant, token, variants) = selector.as_ref();\n\n            let (variant_name, variant_param_type) = variants.select_variant(*discriminant)?;\n            let variant_str = decode_as_debug_str(variant_param_type, token)?;\n            let variant_str = if variant_str == \"()\" {\n                \"\".into()\n            } else {\n                format!(\"({variant_str})\")\n            };\n\n            format!(\"{variant_name}{variant_str}\")\n        }\n        _ => {\n            return Err(error!(\n                Codec,\n                \"could not decode debug from param type: `{param_type:?}` and token: `{token:?}`\"\n            ));\n        }\n    };\n    Ok(result)\n}\n\n#[cfg(test)]\nmod tests {\n    use crate::{\n        codec::ABIDecoder,\n        traits::Parameterize,\n        types::{\n            AsciiString, Bits256, Bytes, EvmAddress, RawSlice, SizedAsciiString, U256,\n            errors::Result,\n        },\n    };\n\n    #[test]\n    fn param_type_decode_debug() -> Result<()> {\n        let decoder = ABIDecoder::default();\n        {\n            assert_eq!(\n                format!(\"{:?}\", true),\n                decoder.decode_as_debug_str(&bool::param_type(), [1].as_slice())?\n            );\n\n            assert_eq!(\n                format!(\"{:?}\", 128u8),\n                decoder.decode_as_debug_str(&u8::param_type(), [128].as_slice())?\n            );\n\n            assert_eq!(\n                format!(\"{:?}\", 256u16),\n                decoder.decode_as_debug_str(&u16::param_type(), [1, 0].as_slice())?\n            );\n\n            assert_eq!(\n                format!(\"{:?}\", 512u32),\n                decoder.decode_as_debug_str(&u32::param_type(), [0, 0, 2, 0].as_slice())?\n            );\n\n            assert_eq!(\n                format!(\"{:?}\", 1024u64),\n                decoder\n                    .decode_as_debug_str(&u64::param_type(), [0, 0, 0, 0, 0, 0, 4, 0].as_slice())?\n            );\n\n            assert_eq!(\n                format!(\"{:?}\", 1024u128),\n                decoder.decode_as_debug_str(\n                    &u128::param_type(),\n                    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0].as_slice()\n                )?\n            );\n\n            assert_eq!(\n                format!(\"{:?}\", U256::from(2048)),\n                decoder.decode_as_debug_str(\n                    &U256::param_type(),\n                    [\n                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n                        0, 0, 0, 0, 0, 8, 0\n                    ]\n                    .as_slice()\n                )?\n            );\n        }\n        {\n            let bytes = [\n                239, 134, 175, 169, 105, 108, 240, 220, 99, 133, 226, 196, 7, 166, 225, 89, 161,\n                16, 60, 239, 183, 226, 174, 6, 54, 251, 51, 211, 203, 42, 158, 74,\n            ];\n            let bits256 = Bits256(bytes);\n\n            assert_eq!(\n                format!(\"{bits256:?}\"),\n                decoder.decode_as_debug_str(\n                    &Bits256::param_type(),\n                    [\n                        239, 134, 175, 169, 105, 108, 240, 220, 99, 133, 226, 196, 7, 166, 225, 89,\n                        161, 16, 60, 239, 183, 226, 174, 6, 54, 251, 51, 211, 203, 42, 158, 74\n                    ]\n                    .as_slice()\n                )?\n            );\n\n            assert_eq!(\n                format!(\"{:?}\", Bytes(bytes.to_vec())),\n                decoder.decode_as_debug_str(\n                    &Bytes::param_type(),\n                    [\n                        0, 0, 0, 0, 0, 0, 0, 32, 239, 134, 175, 169, 105, 108, 240, 220, 99, 133,\n                        226, 196, 7, 166, 225, 89, 161, 16, 60, 239, 183, 226, 174, 6, 54, 251, 51,\n                        211, 203, 42, 158, 74\n                    ]\n                    .as_slice()\n                )?\n            );\n\n            assert_eq!(\n                format!(\"{:?}\", RawSlice(bytes.to_vec())),\n                decoder.decode_as_debug_str(\n                    &RawSlice::param_type(),\n                    [\n                        0, 0, 0, 0, 0, 0, 0, 32, 239, 134, 175, 169, 105, 108, 240, 220, 99, 133,\n                        226, 196, 7, 166, 225, 89, 161, 16, 60, 239, 183, 226, 174, 6, 54, 251, 51,\n                        211, 203, 42, 158, 74\n                    ]\n                    .as_slice()\n                )?\n            );\n\n            assert_eq!(\n                format!(\"{:?}\", EvmAddress::from(bits256)),\n                decoder.decode_as_debug_str(\n                    &EvmAddress::param_type(),\n                    [\n                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 166, 225, 89, 161, 16, 60, 239, 183,\n                        226, 174, 6, 54, 251, 51, 211, 203, 42, 158, 74\n                    ]\n                    .as_slice()\n                )?\n            );\n        }\n        {\n            assert_eq!(\n                format!(\"{:?}\", AsciiString::new(\"Fuel\".to_string())?),\n                decoder.decode_as_debug_str(\n                    &AsciiString::param_type(),\n                    [0, 0, 0, 0, 0, 0, 0, 4, 70, 117, 101, 108].as_slice()\n                )?\n            );\n\n            assert_eq!(\n                format!(\"{:?}\", SizedAsciiString::<4>::new(\"Fuel\".to_string())?),\n                decoder.decode_as_debug_str(\n                    &SizedAsciiString::<4>::param_type(),\n                    [70, 117, 101, 108, 0, 0, 0, 0].as_slice()\n                )?\n            );\n\n            assert_eq!(\n                format!(\"{}\", \"Fuel\"),\n                decoder.decode_as_debug_str(\n                    &String::param_type(),\n                    [0, 0, 0, 0, 0, 0, 0, 4, 70, 117, 101, 108].as_slice()\n                )?\n            );\n        }\n        {\n            assert_eq!(\n                format!(\"{:?}\", (1, 2)),\n                decoder.decode_as_debug_str(&<(u8, u8)>::param_type(), [1, 2].as_slice())?\n            );\n\n            assert_eq!(\n                format!(\"{:?}\", [3, 4]),\n                decoder.decode_as_debug_str(\n                    &<[u64; 2]>::param_type(),\n                    [0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4].as_slice()\n                )?\n            );\n        }\n        {\n            assert_eq!(\n                format!(\"{:?}\", Some(42)),\n                decoder.decode_as_debug_str(\n                    &<Option<u64>>::param_type(),\n                    [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 42].as_slice()\n                )?\n            );\n\n            assert_eq!(\n                format!(\"{:?}\", Err::<u64, u64>(42u64)),\n                decoder.decode_as_debug_str(\n                    &<std::result::Result<u64, u64>>::param_type(),\n                    [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 42].as_slice()\n                )?\n            );\n        }\n\n        Ok(())\n    }\n}\n"
  },
  {
    "path": "packages/fuels-core/src/codec/abi_decoder.rs",
    "content": "mod bounded_decoder;\nmod decode_as_debug_str;\n\nuse std::io::Read;\n\nuse crate::{\n    codec::abi_decoder::{\n        bounded_decoder::BoundedDecoder, decode_as_debug_str::decode_as_debug_str,\n    },\n    types::{Token, errors::Result, param_types::ParamType},\n};\n\n#[derive(Debug, Clone, Copy)]\npub struct DecoderConfig {\n    /// Entering a struct, array, tuple, enum or vector increases the depth. Decoding will fail if\n    /// the current depth becomes greater than `max_depth` configured here.\n    pub max_depth: usize,\n    /// Every decoded Token will increase the token count. Decoding will fail if the current\n    /// token count becomes greater than `max_tokens` configured here.\n    pub max_tokens: usize,\n}\n\n// ANCHOR: default_decoder_config\nimpl Default for DecoderConfig {\n    fn default() -> Self {\n        Self {\n            max_depth: 45,\n            max_tokens: 10_000,\n        }\n    }\n}\n// ANCHOR_END: default_decoder_config\n\n#[derive(Default)]\npub struct ABIDecoder {\n    pub config: DecoderConfig,\n}\n\nimpl ABIDecoder {\n    pub fn new(config: DecoderConfig) -> Self {\n        Self { config }\n    }\n\n    /// Decodes `bytes` following the schema described in `param_type` into its respective `Token`.\n    ///\n    /// # Arguments\n    ///\n    /// * `param_type`: The `ParamType` of the type we expect is encoded inside `bytes`.\n    /// * `bytes`:       The bytes to be used in the decoding process.\n    /// # Examples\n    ///\n    /// ```\n    /// use fuels_core::codec::ABIDecoder;\n    /// use fuels_core::traits::Tokenizable;\n    /// use fuels_core::types::param_types::ParamType;\n    ///\n    /// let decoder = ABIDecoder::default();\n    ///\n    /// let token = decoder.decode(&ParamType::U64,  [0, 0, 0, 0, 0, 0, 0, 7].as_slice()).unwrap();\n    ///\n    /// assert_eq!(u64::from_token(token).unwrap(), 7u64);\n    /// ```\n    pub fn decode(&self, param_type: &ParamType, mut bytes: impl Read) -> Result<Token> {\n        BoundedDecoder::new(self.config).decode(param_type, &mut bytes)\n    }\n\n    /// Same as `decode` but decodes multiple `ParamType`s in one go.\n    /// # Examples\n    /// ```\n    /// use fuels_core::codec::ABIDecoder;\n    /// use fuels_core::types::param_types::ParamType;\n    /// use fuels_core::types::Token;\n    ///\n    /// let decoder = ABIDecoder::default();\n    /// let data = [7, 8];\n    ///\n    /// let tokens = decoder.decode_multiple(&[ParamType::U8, ParamType::U8], data.as_slice()).unwrap();\n    ///\n    /// assert_eq!(tokens, vec![Token::U8(7), Token::U8(8)]);\n    /// ```\n    pub fn decode_multiple(\n        &self,\n        param_types: &[ParamType],\n        mut bytes: impl Read,\n    ) -> Result<Vec<Token>> {\n        BoundedDecoder::new(self.config).decode_multiple(param_types, &mut bytes)\n    }\n\n    /// Decodes `bytes` following the schema described in `param_type` into its respective debug\n    /// string.\n    ///\n    /// # Arguments\n    ///\n    /// * `param_type`: The `ParamType` of the type we expect is encoded inside `bytes`.\n    /// * `bytes`:       The bytes to be used in the decoding process.\n    /// # Examples\n    ///\n    /// ```\n    /// use fuels_core::codec::ABIDecoder;\n    /// use fuels_core::types::param_types::ParamType;\n    ///\n    /// let decoder = ABIDecoder::default();\n    ///\n    /// let debug_string = decoder.decode_as_debug_str(&ParamType::U64,  [0, 0, 0, 0, 0, 0, 0, 7].as_slice()).unwrap();\n    /// let expected_value = 7u64;\n    ///\n    /// assert_eq!(debug_string, format!(\"{expected_value}\"));\n    /// ```\n    pub fn decode_as_debug_str(\n        &self,\n        param_type: &ParamType,\n        mut bytes: impl Read,\n    ) -> Result<String> {\n        let token = BoundedDecoder::new(self.config).decode(param_type, &mut bytes)?;\n        decode_as_debug_str(param_type, &token)\n    }\n\n    pub fn decode_multiple_as_debug_str(\n        &self,\n        param_types: &[ParamType],\n        mut bytes: impl Read,\n    ) -> Result<Vec<String>> {\n        let token = BoundedDecoder::new(self.config).decode_multiple(param_types, &mut bytes)?;\n        token\n            .into_iter()\n            .zip(param_types)\n            .map(|(token, param_type)| decode_as_debug_str(param_type, &token))\n            .collect()\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use std::vec;\n\n    use ParamType::*;\n\n    use super::*;\n    use crate::{\n        constants::WORD_SIZE,\n        to_named,\n        traits::Parameterize,\n        types::{StaticStringToken, U256, errors::Error, param_types::EnumVariants},\n    };\n\n    #[test]\n    fn decode_multiple_uint() -> Result<()> {\n        let types = vec![\n            ParamType::U8,\n            ParamType::U16,\n            ParamType::U32,\n            ParamType::U64,\n            ParamType::U128,\n            ParamType::U256,\n        ];\n\n        let data = [\n            255, // u8\n            255, 255, // u16\n            255, 255, 255, 255, // u32\n            255, 255, 255, 255, 255, 255, 255, 255, // u64\n            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,\n            255, // u128\n            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,\n            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // u256\n        ];\n\n        let decoded = ABIDecoder::default().decode_multiple(&types, data.as_slice())?;\n\n        let expected = vec![\n            Token::U8(u8::MAX),\n            Token::U16(u16::MAX),\n            Token::U32(u32::MAX),\n            Token::U64(u64::MAX),\n            Token::U128(u128::MAX),\n            Token::U256(U256::MAX),\n        ];\n        assert_eq!(decoded, expected);\n\n        Ok(())\n    }\n\n    #[test]\n    fn decode_bool() -> Result<()> {\n        let types = vec![ParamType::Bool, ParamType::Bool];\n        let data = [1, 0];\n\n        let decoded = ABIDecoder::default().decode_multiple(&types, data.as_slice())?;\n\n        let expected = vec![Token::Bool(true), Token::Bool(false)];\n\n        assert_eq!(decoded, expected);\n\n        Ok(())\n    }\n\n    #[test]\n    fn decode_b256() -> Result<()> {\n        let data = [\n            213, 87, 156, 70, 223, 204, 127, 24, 32, 112, 19, 230, 91, 68, 228, 203, 78, 44, 34,\n            152, 244, 172, 69, 123, 168, 248, 39, 67, 243, 30, 147, 11,\n        ];\n\n        let decoded = ABIDecoder::default().decode(&ParamType::B256, data.as_slice())?;\n\n        assert_eq!(decoded, Token::B256(data));\n\n        Ok(())\n    }\n\n    #[test]\n    fn decode_string_array() -> Result<()> {\n        let types = vec![ParamType::StringArray(23), ParamType::StringArray(5)];\n        let data = [\n            84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 117, 108, 108, 32, 115, 101, 110,\n            116, 101, 110, 99, 101, //This is a full sentence\n            72, 101, 108, 108, 111, // Hello\n        ];\n\n        let decoded = ABIDecoder::default().decode_multiple(&types, data.as_slice())?;\n\n        let expected = vec![\n            Token::StringArray(StaticStringToken::new(\n                \"This is a full sentence\".into(),\n                Some(23),\n            )),\n            Token::StringArray(StaticStringToken::new(\"Hello\".into(), Some(5))),\n        ];\n\n        assert_eq!(decoded, expected);\n\n        Ok(())\n    }\n\n    #[test]\n    fn decode_string_slice() -> Result<()> {\n        let data = [\n            0, 0, 0, 0, 0, 0, 0, 23, // [length]\n            84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 117, 108, 108, 32, 115, 101, 110,\n            116, 101, 110, 99, 101, //This is a full sentence\n        ];\n\n        let decoded = ABIDecoder::default().decode(&ParamType::StringSlice, data.as_slice())?;\n\n        let expected = Token::StringSlice(StaticStringToken::new(\n            \"This is a full sentence\".into(),\n            None,\n        ));\n\n        assert_eq!(decoded, expected);\n\n        Ok(())\n    }\n\n    #[test]\n    fn decode_string() -> Result<()> {\n        let data = [\n            0, 0, 0, 0, 0, 0, 0, 23, // [length]\n            84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 117, 108, 108, 32, 115, 101, 110,\n            116, 101, 110, 99, 101, //This is a full sentence\n        ];\n\n        let decoded = ABIDecoder::default().decode(&ParamType::String, data.as_slice())?;\n\n        let expected = Token::String(\"This is a full sentence\".to_string());\n\n        assert_eq!(decoded, expected);\n\n        Ok(())\n    }\n\n    #[test]\n    fn decode_tuple() -> Result<()> {\n        let param_type = ParamType::Tuple(vec![ParamType::U32, ParamType::Bool]);\n        let data = [\n            0, 0, 0, 255, //u32\n            1,   //bool\n        ];\n\n        let result = ABIDecoder::default().decode(&param_type, data.as_slice())?;\n\n        let expected = Token::Tuple(vec![Token::U32(255), Token::Bool(true)]);\n\n        assert_eq!(result, expected);\n\n        Ok(())\n    }\n\n    #[test]\n    fn decode_array() -> Result<()> {\n        let types = vec![ParamType::Array(Box::new(ParamType::U8), 2)];\n        let data = [255, 42];\n\n        let decoded = ABIDecoder::default().decode_multiple(&types, data.as_slice())?;\n\n        let expected = vec![Token::Array(vec![Token::U8(255), Token::U8(42)])];\n        assert_eq!(decoded, expected);\n\n        Ok(())\n    }\n\n    #[test]\n    fn decode_struct() -> Result<()> {\n        // struct MyStruct {\n        //     foo: u8,\n        //     bar: bool,\n        // }\n\n        let data = [1, 1];\n\n        let param_type = ParamType::Struct {\n            name: \"\".to_string(),\n            fields: to_named(&[ParamType::U8, ParamType::Bool]),\n            generics: vec![],\n        };\n\n        let decoded = ABIDecoder::default().decode(&param_type, data.as_slice())?;\n\n        let expected = Token::Struct(vec![Token::U8(1), Token::Bool(true)]);\n\n        assert_eq!(decoded, expected);\n\n        Ok(())\n    }\n\n    #[test]\n    fn decode_bytes() -> Result<()> {\n        let data = [0, 0, 0, 0, 0, 0, 0, 7, 255, 0, 1, 2, 3, 4, 5];\n\n        let decoded = ABIDecoder::default().decode(&ParamType::Bytes, data.as_slice())?;\n\n        let expected = Token::Bytes([255, 0, 1, 2, 3, 4, 5].to_vec());\n\n        assert_eq!(decoded, expected);\n\n        Ok(())\n    }\n\n    #[test]\n    fn decode_raw_slice() -> Result<()> {\n        let data = [0, 0, 0, 0, 0, 0, 0, 7, 255, 0, 1, 2, 3, 4, 5];\n\n        let decoded = ABIDecoder::default().decode(&ParamType::RawSlice, data.as_slice())?;\n\n        let expected = Token::RawSlice([255, 0, 1, 2, 3, 4, 5].to_vec());\n\n        assert_eq!(decoded, expected);\n\n        Ok(())\n    }\n\n    #[test]\n    fn decode_enum() -> Result<()> {\n        // enum MyEnum {\n        //     x: u32,\n        //     y: bool,\n        // }\n\n        let types = to_named(&[ParamType::U32, ParamType::Bool]);\n        let inner_enum_types = EnumVariants::new(types)?;\n        let types = vec![ParamType::Enum {\n            name: \"\".to_string(),\n            enum_variants: inner_enum_types.clone(),\n            generics: vec![],\n        }];\n\n        let data = [\n            0, 0, 0, 0, 0, 0, 0, 0, // discriminant\n            0, 0, 0, 42, // u32\n        ];\n\n        let decoded = ABIDecoder::default().decode_multiple(&types, data.as_slice())?;\n\n        let expected = vec![Token::Enum(Box::new((0, Token::U32(42), inner_enum_types)))];\n        assert_eq!(decoded, expected);\n\n        Ok(())\n    }\n\n    #[test]\n    fn decode_nested_struct() -> Result<()> {\n        // struct Foo {\n        //     x: u16,\n        //     y: Bar,\n        // }\n        //\n        // struct Bar {\n        //     a: bool,\n        //     b: u8[2],\n        // }\n\n        let fields = to_named(&[\n            ParamType::U16,\n            ParamType::Struct {\n                name: \"\".to_string(),\n                fields: to_named(&[\n                    ParamType::Bool,\n                    ParamType::Array(Box::new(ParamType::U8), 2),\n                ]),\n                generics: vec![],\n            },\n        ]);\n        let nested_struct = ParamType::Struct {\n            name: \"\".to_string(),\n            fields,\n            generics: vec![],\n        };\n\n        let data = [0, 10, 1, 1, 2];\n\n        let decoded = ABIDecoder::default().decode(&nested_struct, data.as_slice())?;\n\n        let my_nested_struct = vec![\n            Token::U16(10),\n            Token::Struct(vec![\n                Token::Bool(true),\n                Token::Array(vec![Token::U8(1), Token::U8(2)]),\n            ]),\n        ];\n\n        assert_eq!(decoded, Token::Struct(my_nested_struct));\n\n        Ok(())\n    }\n\n    #[test]\n    fn decode_comprehensive() -> Result<()> {\n        // struct Foo {\n        //     x: u16,\n        //     y: Bar,\n        // }\n        //\n        // struct Bar {\n        //     a: bool,\n        //     b: u8[2],\n        // }\n\n        // fn: long_function(Foo,u8[2],b256,str[3],str)\n\n        // Parameters\n        let fields = to_named(&[\n            ParamType::U16,\n            ParamType::Struct {\n                name: \"\".to_string(),\n                fields: to_named(&[\n                    ParamType::Bool,\n                    ParamType::Array(Box::new(ParamType::U8), 2),\n                ]),\n                generics: vec![],\n            },\n        ]);\n        let nested_struct = ParamType::Struct {\n            name: \"\".to_string(),\n            fields,\n            generics: vec![],\n        };\n\n        let u8_arr = ParamType::Array(Box::new(ParamType::U8), 2);\n        let b256 = ParamType::B256;\n\n        let types = [nested_struct, u8_arr, b256];\n\n        let bytes = [\n            0, 10, // u16\n            1,  // bool\n            1, 2, // array[u8;2]\n            1, 2, // array[u8;2]\n            213, 87, 156, 70, 223, 204, 127, 24, 32, 112, 19, 230, 91, 68, 228, 203, 78, 44, 34,\n            152, 244, 172, 69, 123, 168, 248, 39, 67, 243, 30, 147, 11, // b256\n        ];\n\n        let decoded = ABIDecoder::default().decode_multiple(&types, bytes.as_slice())?;\n\n        // Expected tokens\n        let foo = Token::Struct(vec![\n            Token::U16(10),\n            Token::Struct(vec![\n                Token::Bool(true),\n                Token::Array(vec![Token::U8(1), Token::U8(2)]),\n            ]),\n        ]);\n\n        let u8_arr = Token::Array(vec![Token::U8(1), Token::U8(2)]);\n\n        let b256 = Token::B256([\n            213, 87, 156, 70, 223, 204, 127, 24, 32, 112, 19, 230, 91, 68, 228, 203, 78, 44, 34,\n            152, 244, 172, 69, 123, 168, 248, 39, 67, 243, 30, 147, 11,\n        ]);\n\n        let expected: Vec<Token> = vec![foo, u8_arr, b256];\n\n        assert_eq!(decoded, expected);\n\n        Ok(())\n    }\n\n    #[test]\n    fn enums_with_all_unit_variants_are_decoded_from_one_word() -> Result<()> {\n        let data = [0, 0, 0, 0, 0, 0, 0, 1];\n        let types = to_named(&[ParamType::Unit, ParamType::Unit]);\n        let enum_variants = EnumVariants::new(types)?;\n        let enum_w_only_units = ParamType::Enum {\n            name: \"\".to_string(),\n            enum_variants: enum_variants.clone(),\n            generics: vec![],\n        };\n\n        let result = ABIDecoder::default().decode(&enum_w_only_units, data.as_slice())?;\n\n        let expected_enum = Token::Enum(Box::new((1, Token::Unit, enum_variants)));\n        assert_eq!(result, expected_enum);\n\n        Ok(())\n    }\n\n    #[test]\n    fn out_of_bounds_discriminant_is_detected() -> Result<()> {\n        let data = [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2];\n        let types = to_named(&[ParamType::U64]);\n        let enum_variants = EnumVariants::new(types)?;\n        let enum_type = ParamType::Enum {\n            name: \"\".to_string(),\n            enum_variants,\n            generics: vec![],\n        };\n\n        let result = ABIDecoder::default().decode(&enum_type, data.as_slice());\n\n        let error = result.expect_err(\"should have resulted in an error\");\n\n        let expected_msg = \"discriminant `1` doesn't point to any variant: \";\n        assert!(matches!(error, Error::Other(str) if str.starts_with(expected_msg)));\n\n        Ok(())\n    }\n\n    #[test]\n    pub fn division_by_zero() {\n        let param_type = Vec::<[u16; 0]>::param_type();\n        let result = ABIDecoder::default().decode(&param_type, [].as_slice());\n        assert!(matches!(result, Err(Error::IO(_))));\n    }\n\n    #[test]\n    pub fn multiply_overflow_enum() {\n        let result = ABIDecoder::default().decode(\n            &Enum {\n                name: \"\".to_string(),\n                enum_variants: EnumVariants::new(to_named(&[\n                    Array(Box::new(Array(Box::new(RawSlice), 8)), usize::MAX),\n                    B256,\n                    B256,\n                    B256,\n                    B256,\n                    B256,\n                    B256,\n                    B256,\n                    B256,\n                    B256,\n                    B256,\n                ]))\n                .unwrap(),\n                generics: vec![U16],\n            },\n            [].as_slice(),\n        );\n\n        assert!(matches!(result, Err(Error::IO(_))));\n    }\n\n    #[test]\n    pub fn multiply_overflow_arith() {\n        let mut param_type: ParamType = U16;\n        for _ in 0..50 {\n            param_type = Array(Box::new(param_type), 8);\n        }\n        let result = ABIDecoder::default().decode(\n            &Enum {\n                name: \"\".to_string(),\n                enum_variants: EnumVariants::new(to_named(&[param_type])).unwrap(),\n                generics: vec![U16],\n            },\n            [].as_slice(),\n        );\n        assert!(matches!(result, Err(Error::IO(_))));\n    }\n\n    #[test]\n    pub fn capacity_overflow() {\n        let result = ABIDecoder::default().decode(\n            &Array(Box::new(Array(Box::new(Tuple(vec![])), usize::MAX)), 1),\n            [].as_slice(),\n        );\n        assert!(matches!(result, Err(Error::Codec(_))));\n    }\n\n    #[test]\n    pub fn stack_overflow() {\n        let mut param_type: ParamType = U16;\n        for _ in 0..13500 {\n            param_type = Vector(Box::new(param_type));\n        }\n        let result = ABIDecoder::default().decode(&param_type, [].as_slice());\n        assert!(matches!(result, Err(Error::IO(_))));\n    }\n\n    #[test]\n    pub fn capacity_malloc() {\n        let param_type = Array(Box::new(U8), usize::MAX);\n        let result = ABIDecoder::default().decode(&param_type, [].as_slice());\n        assert!(matches!(result, Err(Error::IO(_))));\n    }\n\n    #[test]\n    fn max_depth_surpassed() {\n        const MAX_DEPTH: usize = 2;\n        let config = DecoderConfig {\n            max_depth: MAX_DEPTH,\n            ..Default::default()\n        };\n        let msg = format!(\"depth limit `{MAX_DEPTH}` reached while decoding. Try increasing it\");\n        // for each nested enum so that it may read the discriminant\n        let data = [0; MAX_DEPTH * WORD_SIZE];\n\n        [nested_struct, nested_enum, nested_tuple, nested_array]\n            .iter()\n            .map(|fun| fun(MAX_DEPTH + 1))\n            .for_each(|param_type| {\n                assert_decoding_failed_w_data(config, &param_type, &msg, data.as_slice());\n            })\n    }\n\n    #[test]\n    fn depth_is_not_reached() {\n        const MAX_DEPTH: usize = 3;\n        const ACTUAL_DEPTH: usize = MAX_DEPTH - 1;\n\n        // enough data to decode 2*ACTUAL_DEPTH enums (discriminant + u8 = 2*WORD_SIZE)\n        let data = [0; 2 * ACTUAL_DEPTH * (WORD_SIZE * 2)];\n        let config = DecoderConfig {\n            max_depth: MAX_DEPTH,\n            ..Default::default()\n        };\n\n        [nested_struct, nested_enum, nested_tuple, nested_array]\n            .into_iter()\n            .map(|fun| fun(ACTUAL_DEPTH))\n            .map(|param_type| {\n                // Wrapping everything in a structure so that we may check whether the depth is\n                // decremented after finishing every struct field.\n                ParamType::Struct {\n                    name: \"\".to_string(),\n                    fields: to_named(&[param_type.clone(), param_type]),\n                    generics: vec![],\n                }\n            })\n            .for_each(|param_type| {\n                ABIDecoder::new(config)\n                    .decode(&param_type, data.as_slice())\n                    .unwrap();\n            })\n    }\n\n    #[test]\n    fn too_many_tokens() {\n        let config = DecoderConfig {\n            max_tokens: 3,\n            ..Default::default()\n        };\n        {\n            let data = [0; 3 * WORD_SIZE];\n            let inner_param_types = vec![ParamType::U64; 3];\n            for param_type in [\n                ParamType::Struct {\n                    name: \"\".to_string(),\n                    fields: to_named(&inner_param_types),\n                    generics: vec![],\n                },\n                ParamType::Tuple(inner_param_types.clone()),\n                ParamType::Array(Box::new(ParamType::U64), 3),\n            ] {\n                assert_decoding_failed_w_data(\n                    config,\n                    &param_type,\n                    \"token limit `3` reached while decoding. Try increasing it\",\n                    &data,\n                );\n            }\n        }\n        {\n            let data = [0, 0, 0, 0, 0, 0, 0, 3, 1, 2, 3];\n\n            assert_decoding_failed_w_data(\n                config,\n                &ParamType::Vector(Box::new(ParamType::U8)),\n                \"token limit `3` reached while decoding. Try increasing it\",\n                &data,\n            );\n        }\n    }\n\n    #[test]\n    fn token_count_is_being_reset_between_decodings() {\n        // given\n        let config = DecoderConfig {\n            max_tokens: 3,\n            ..Default::default()\n        };\n\n        let param_type = ParamType::Array(Box::new(ParamType::StringArray(0)), 2);\n\n        let decoder = ABIDecoder::new(config);\n        decoder.decode(&param_type, [].as_slice()).unwrap();\n\n        // when\n        let result = decoder.decode(&param_type, [].as_slice());\n\n        // then\n        result.expect(\"element count to be reset\");\n    }\n\n    fn assert_decoding_failed_w_data(\n        config: DecoderConfig,\n        param_type: &ParamType,\n        msg: &str,\n        data: &[u8],\n    ) {\n        let decoder = ABIDecoder::new(config);\n\n        let err = decoder.decode(param_type, data);\n\n        let Err(Error::Codec(actual_msg)) = err else {\n            panic!(\"expected a `Codec` error. Got: `{err:?}`\");\n        };\n\n        assert_eq!(actual_msg, msg);\n    }\n\n    fn nested_struct(depth: usize) -> ParamType {\n        let fields = if depth == 1 {\n            vec![]\n        } else {\n            to_named(&[nested_struct(depth - 1)])\n        };\n\n        ParamType::Struct {\n            name: \"\".to_string(),\n            fields,\n            generics: vec![],\n        }\n    }\n\n    fn nested_enum(depth: usize) -> ParamType {\n        let fields = if depth == 1 {\n            to_named(&[ParamType::U8])\n        } else {\n            to_named(&[nested_enum(depth - 1)])\n        };\n\n        ParamType::Enum {\n            name: \"\".to_string(),\n            enum_variants: EnumVariants::new(fields).unwrap(),\n            generics: vec![],\n        }\n    }\n\n    fn nested_array(depth: usize) -> ParamType {\n        let field = if depth == 1 {\n            ParamType::U8\n        } else {\n            nested_array(depth - 1)\n        };\n\n        ParamType::Array(Box::new(field), 1)\n    }\n\n    fn nested_tuple(depth: usize) -> ParamType {\n        let fields = if depth == 1 {\n            vec![ParamType::U8]\n        } else {\n            vec![nested_tuple(depth - 1)]\n        };\n\n        ParamType::Tuple(fields)\n    }\n}\n"
  },
  {
    "path": "packages/fuels-core/src/codec/abi_encoder/bounded_encoder.rs",
    "content": "use crate::{\n    codec::{\n        EncoderConfig,\n        utils::{CodecDirection, CounterWithLimit},\n    },\n    types::{EnumSelector, StaticStringToken, Token, U256, errors::Result},\n};\n\npub(crate) struct BoundedEncoder {\n    depth_tracker: CounterWithLimit,\n    token_tracker: CounterWithLimit,\n}\n\nimpl BoundedEncoder {\n    pub(crate) fn new(config: EncoderConfig) -> Self {\n        let depth_tracker =\n            CounterWithLimit::new(config.max_depth, \"depth\", CodecDirection::Encoding);\n        let token_tracker =\n            CounterWithLimit::new(config.max_tokens, \"token\", CodecDirection::Encoding);\n        Self {\n            depth_tracker,\n            token_tracker,\n        }\n    }\n\n    pub fn encode(&mut self, tokens: &[Token]) -> Result<Vec<u8>> {\n        let mut data = vec![];\n\n        for token in tokens.iter() {\n            let new_data = self.encode_token(token)?;\n            data.extend(new_data);\n        }\n\n        Ok(data)\n    }\n\n    fn run_w_depth_tracking(\n        &mut self,\n        encoder: impl FnOnce(&mut Self) -> Result<Vec<u8>>,\n    ) -> Result<Vec<u8>> {\n        self.depth_tracker.increase()?;\n        let res = encoder(self);\n        self.depth_tracker.decrease();\n\n        res\n    }\n\n    fn encode_token(&mut self, arg: &Token) -> Result<Vec<u8>> {\n        self.token_tracker.increase()?;\n        let encoded_token = match arg {\n            Token::Unit => vec![],\n            Token::Bool(arg_bool) => vec![u8::from(*arg_bool)],\n            Token::U8(arg_u8) => vec![*arg_u8],\n            Token::U16(arg_u16) => arg_u16.to_be_bytes().to_vec(),\n            Token::U32(arg_u32) => arg_u32.to_be_bytes().to_vec(),\n            Token::U64(arg_u64) => arg_u64.to_be_bytes().to_vec(),\n            Token::U128(arg_u128) => arg_u128.to_be_bytes().to_vec(),\n            Token::U256(arg_u256) => Self::encode_u256(*arg_u256),\n            Token::B256(arg_bits256) => arg_bits256.to_vec(),\n            Token::Bytes(data) => Self::encode_bytes(data.to_vec())?,\n            Token::String(string) => Self::encode_bytes(string.clone().into_bytes())?,\n            Token::RawSlice(data) => Self::encode_bytes(data.clone())?,\n            Token::StringArray(arg_string) => Self::encode_string_array(arg_string)?,\n            Token::StringSlice(arg_string) => Self::encode_string_slice(arg_string)?,\n            Token::Tuple(arg_tuple) => self.run_w_depth_tracking(|ctx| ctx.encode(arg_tuple))?,\n            Token::Array(arg_array) => self.run_w_depth_tracking(|ctx| ctx.encode(arg_array))?,\n            Token::Vector(data) => self.run_w_depth_tracking(|ctx| ctx.encode_vector(data))?,\n            Token::Struct(arg_struct) => self.run_w_depth_tracking(|ctx| ctx.encode(arg_struct))?,\n            Token::Enum(arg_enum) => self.run_w_depth_tracking(|ctx| ctx.encode_enum(arg_enum))?,\n        };\n\n        Ok(encoded_token)\n    }\n\n    fn encode_u256(arg_u256: U256) -> Vec<u8> {\n        let mut bytes = [0u8; 32];\n        arg_u256.to_big_endian(&mut bytes);\n\n        bytes.to_vec()\n    }\n\n    fn encode_bytes(data: Vec<u8>) -> Result<Vec<u8>> {\n        let len = data.len();\n\n        Ok([Self::encode_length(len as u64), data].concat())\n    }\n\n    fn encode_string_array(arg_string: &StaticStringToken) -> Result<Vec<u8>> {\n        Ok(arg_string.get_encodable_str()?.as_bytes().to_vec())\n    }\n\n    fn encode_string_slice(arg_string: &StaticStringToken) -> Result<Vec<u8>> {\n        Self::encode_bytes(arg_string.get_encodable_str()?.as_bytes().to_vec())\n    }\n\n    fn encode_vector(&mut self, data: &[Token]) -> Result<Vec<u8>> {\n        let encoded_data = self.encode(data)?;\n\n        Ok([Self::encode_length(data.len() as u64), encoded_data].concat())\n    }\n\n    fn encode_enum(&mut self, selector: &EnumSelector) -> Result<Vec<u8>> {\n        let (discriminant, token_within_enum, _) = selector;\n        let encoded_discriminant = Self::encode_discriminant(*discriminant);\n        let encoded_token = self.encode_token(token_within_enum)?;\n\n        Ok([encoded_discriminant, encoded_token].concat())\n    }\n\n    fn encode_length(len: u64) -> Vec<u8> {\n        len.to_be_bytes().to_vec()\n    }\n\n    fn encode_discriminant(discriminant: u64) -> Vec<u8> {\n        discriminant.to_be_bytes().to_vec()\n    }\n}\n"
  },
  {
    "path": "packages/fuels-core/src/codec/abi_encoder.rs",
    "content": "mod bounded_encoder;\n\nuse std::default::Default;\n\nuse crate::{\n    codec::abi_encoder::bounded_encoder::BoundedEncoder,\n    types::{Token, errors::Result},\n};\n\n#[derive(Debug, Clone, Copy)]\npub struct EncoderConfig {\n    /// Entering a struct, array, tuple, enum or vector increases the depth. Encoding will fail if\n    /// the current depth becomes greater than `max_depth` configured here.\n    pub max_depth: usize,\n    /// Every encoded argument will increase the token count. Encoding will fail if the current\n    /// token count becomes greater than `max_tokens` configured here.\n    pub max_tokens: usize,\n}\n\n// ANCHOR: default_encoder_config\nimpl Default for EncoderConfig {\n    fn default() -> Self {\n        Self {\n            max_depth: 45,\n            max_tokens: 10_000,\n        }\n    }\n}\n// ANCHOR_END: default_encoder_config\n\n#[derive(Default, Clone, Debug)]\npub struct ABIEncoder {\n    pub config: EncoderConfig,\n}\n\nimpl ABIEncoder {\n    pub fn new(config: EncoderConfig) -> Self {\n        Self { config }\n    }\n\n    /// Encodes `Token`s following the ABI specs defined\n    /// [here](https://github.com/FuelLabs/fuel-specs/blob/master/specs/protocol/abi.md)\n    pub fn encode(&self, tokens: &[Token]) -> Result<Vec<u8>> {\n        BoundedEncoder::new(self.config).encode(tokens)\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use std::slice;\n\n    use super::*;\n    use crate::{\n        to_named,\n        types::{\n            StaticStringToken, U256,\n            errors::Error,\n            param_types::{EnumVariants, ParamType},\n        },\n    };\n\n    #[test]\n    fn encode_multiple_uint() -> Result<()> {\n        let tokens = [\n            Token::U8(u8::MAX),\n            Token::U16(u16::MAX),\n            Token::U32(u32::MAX),\n            Token::U64(u64::MAX),\n            Token::U128(u128::MAX),\n            Token::U256(U256::MAX),\n        ];\n\n        let result = ABIEncoder::default().encode(&tokens)?;\n\n        let expected = [\n            255, // u8\n            255, 255, // u16\n            255, 255, 255, 255, // u32\n            255, 255, 255, 255, 255, 255, 255, 255, // u64\n            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,\n            255, // u128\n            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,\n            255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, // u256\n        ];\n\n        assert_eq!(result, expected);\n\n        Ok(())\n    }\n\n    #[test]\n    fn encode_bool() -> Result<()> {\n        let token = Token::Bool(true);\n\n        let result = ABIEncoder::default().encode(&[token])?;\n\n        let expected = [1];\n\n        assert_eq!(result, expected);\n\n        Ok(())\n    }\n\n    #[test]\n    fn encode_b256() -> Result<()> {\n        let data = [\n            213, 87, 156, 70, 223, 204, 127, 24, 32, 112, 19, 230, 91, 68, 228, 203, 78, 44, 34,\n            152, 244, 172, 69, 123, 168, 248, 39, 67, 243, 30, 147, 11,\n        ];\n        let token = Token::B256(data);\n\n        let result = ABIEncoder::default().encode(&[token])?;\n\n        assert_eq!(result, data);\n\n        Ok(())\n    }\n\n    #[test]\n    fn encode_bytes() -> Result<()> {\n        let token = Token::Bytes([255, 0, 1, 2, 3, 4, 5].to_vec());\n\n        let result = ABIEncoder::default().encode(&[token])?;\n\n        let expected = [\n            0, 0, 0, 0, 0, 0, 0, 7, // len\n            255, 0, 1, 2, 3, 4, 5, // data\n        ];\n\n        assert_eq!(result, expected);\n\n        Ok(())\n    }\n\n    #[test]\n    fn encode_string() -> Result<()> {\n        let token = Token::String(\"This is a full sentence\".to_string());\n\n        let result = ABIEncoder::default().encode(&[token])?;\n\n        let expected = [\n            0, 0, 0, 0, 0, 0, 0, 23, // len\n            84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 117, 108, 108, 32, 115, 101, 110,\n            116, 101, 110, 99, 101, //This is a full sentence\n        ];\n\n        assert_eq!(result, expected);\n\n        Ok(())\n    }\n\n    #[test]\n    fn encode_raw_slice() -> Result<()> {\n        let token = Token::RawSlice([255, 0, 1, 2, 3, 4, 5].to_vec());\n\n        let result = ABIEncoder::default().encode(&[token])?;\n\n        let expected = [\n            0, 0, 0, 0, 0, 0, 0, 7, // len\n            255, 0, 1, 2, 3, 4, 5, // data\n        ];\n\n        assert_eq!(result, expected);\n\n        Ok(())\n    }\n\n    #[test]\n    fn encode_string_array() -> Result<()> {\n        let token = Token::StringArray(StaticStringToken::new(\n            \"This is a full sentence\".into(),\n            Some(23),\n        ));\n\n        let result = ABIEncoder::default().encode(&[token])?;\n\n        let expected = [\n            84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 117, 108, 108, 32, 115, 101, 110,\n            116, 101, 110, 99, 101, //This is a full sentence\n        ];\n\n        assert_eq!(result, expected);\n\n        Ok(())\n    }\n\n    #[test]\n    fn encode_string_slice() -> Result<()> {\n        let token = Token::StringSlice(StaticStringToken::new(\n            \"This is a full sentence\".into(),\n            None,\n        ));\n\n        let result = ABIEncoder::default().encode(&[token])?;\n\n        let expected = [\n            0, 0, 0, 0, 0, 0, 0, 23, // len\n            84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 117, 108, 108, 32, 115, 101, 110,\n            116, 101, 110, 99, 101, //This is a full sentence\n        ];\n\n        assert_eq!(result, expected);\n\n        Ok(())\n    }\n\n    #[test]\n    fn encode_tuple() -> Result<()> {\n        let token = Token::Tuple(vec![Token::U32(255), Token::Bool(true)]);\n\n        let result = ABIEncoder::default().encode(&[token])?;\n\n        let expected = [\n            0, 0, 0, 255, //u32\n            1,   //bool\n        ];\n\n        assert_eq!(result, expected);\n\n        Ok(())\n    }\n\n    #[test]\n    fn encode_array() -> Result<()> {\n        let token = Token::Tuple(vec![Token::U32(255), Token::U32(128)]);\n\n        let result = ABIEncoder::default().encode(&[token])?;\n\n        let expected = [\n            0, 0, 0, 255, //u32\n            0, 0, 0, 128, //u32\n        ];\n\n        assert_eq!(result, expected);\n\n        Ok(())\n    }\n\n    #[test]\n    fn encode_enum_with_deeply_nested_types() -> Result<()> {\n        /*\n        enum DeeperEnum {\n            v1: bool,\n            v2: str[10]\n        }\n         */\n        let types = to_named(&[ParamType::Bool, ParamType::StringArray(10)]);\n        let deeper_enum_variants = EnumVariants::new(types)?;\n        let deeper_enum_token =\n            Token::StringArray(StaticStringToken::new(\"0123456789\".into(), Some(10)));\n\n        /*\n        struct StructA {\n            some_enum: DeeperEnum\n            some_number: u32\n        }\n         */\n\n        let fields = to_named(&[\n            ParamType::Enum {\n                name: \"\".to_string(),\n                enum_variants: deeper_enum_variants.clone(),\n                generics: vec![],\n            },\n            ParamType::Bool,\n        ]);\n        let struct_a_type = ParamType::Struct {\n            name: \"\".to_string(),\n            fields,\n            generics: vec![],\n        };\n\n        let struct_a_token = Token::Struct(vec![\n            Token::Enum(Box::new((1, deeper_enum_token, deeper_enum_variants))),\n            Token::U32(11332),\n        ]);\n\n        /*\n         enum TopLevelEnum {\n            v1: StructA,\n            v2: bool,\n            v3: u64\n        }\n        */\n\n        let types = to_named(&[struct_a_type, ParamType::Bool, ParamType::U64]);\n        let top_level_enum_variants = EnumVariants::new(types)?;\n        let top_level_enum_token =\n            Token::Enum(Box::new((0, struct_a_token, top_level_enum_variants)));\n\n        let result = ABIEncoder::default().encode(slice::from_ref(&top_level_enum_token))?;\n\n        let expected = [\n            0, 0, 0, 0, 0, 0, 0, 0, // TopLevelEnum::v1 discriminant\n            0, 0, 0, 0, 0, 0, 0, 1, // DeeperEnum::v2 discriminant\n            48, 49, 50, 51, 52, 53, 54, 55, 56, 57, // str[10]\n            0, 0, 44, 68, // StructA.some_number\n        ];\n\n        assert_eq!(result, expected);\n\n        Ok(())\n    }\n\n    #[test]\n    fn encode_nested_structs() -> Result<()> {\n        let token = Token::Struct(vec![\n            Token::U16(10),\n            Token::Struct(vec![\n                Token::Bool(true),\n                Token::Array(vec![Token::U8(1), Token::U8(2)]),\n            ]),\n        ]);\n\n        let result = ABIEncoder::default().encode(&[token])?;\n\n        let expected = [\n            0, 10, // u16\n            1,  // bool\n            1, 2, // [u8, u8]\n        ];\n\n        assert_eq!(result, expected);\n\n        Ok(())\n    }\n\n    #[test]\n    fn encode_comprehensive() -> Result<()> {\n        let foo = Token::Struct(vec![\n            Token::U16(10),\n            Token::Struct(vec![\n                Token::Bool(true),\n                Token::Array(vec![Token::U8(1), Token::U8(2)]),\n            ]),\n        ]);\n        let arr_u8 = Token::Array(vec![Token::U8(1), Token::U8(2)]);\n        let b256 = Token::B256([255; 32]);\n        let str_arr = Token::StringArray(StaticStringToken::new(\n            \"This is a full sentence\".into(),\n            Some(23),\n        ));\n        let tokens = vec![foo, arr_u8, b256, str_arr];\n\n        let result = ABIEncoder::default().encode(&tokens)?;\n\n        let expected = [\n            0, 10, // foo.x == 10u16\n            1,  // foo.y.a == true\n            1,  // foo.y.b.0 == 1u8\n            2,  // foo.y.b.1 == 2u8\n            1,  // u8[2].0 == 1u8\n            2,  // u8[2].0 == 2u8\n            255, 255, 255, 255, 255, 255, 255, 255, // b256\n            255, 255, 255, 255, 255, 255, 255, 255, // b256\n            255, 255, 255, 255, 255, 255, 255, 255, // b256\n            255, 255, 255, 255, 255, 255, 255, 255, // b256\n            84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 117, 108, 108, 32, 115, 101, 110,\n            116, 101, 110, 99, 101, // str[23]\n        ];\n\n        assert_eq!(result, expected);\n\n        Ok(())\n    }\n\n    #[test]\n    fn enums_with_only_unit_variants_are_encoded_in_one_word() -> Result<()> {\n        let expected = [0, 0, 0, 0, 0, 0, 0, 1];\n\n        let types = to_named(&[ParamType::Unit, ParamType::Unit]);\n        let enum_selector = Box::new((1, Token::Unit, EnumVariants::new(types)?));\n\n        let actual = ABIEncoder::default().encode(&[Token::Enum(enum_selector)])?;\n\n        assert_eq!(actual, expected);\n\n        Ok(())\n    }\n\n    #[test]\n    fn vec_in_enum() -> Result<()> {\n        // arrange\n        let types = to_named(&[ParamType::B256, ParamType::Vector(Box::new(ParamType::U64))]);\n        let variants = EnumVariants::new(types)?;\n        let selector = (1, Token::Vector(vec![Token::U64(5)]), variants);\n        let token = Token::Enum(Box::new(selector));\n\n        // act\n        let result = ABIEncoder::default().encode(&[token])?;\n\n        // assert\n        let expected = [\n            0, 0, 0, 0, 0, 0, 0, 1, // enum dicsriminant\n            0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 5, // vec[len, u64]\n        ];\n\n        assert_eq!(result, expected);\n\n        Ok(())\n    }\n\n    #[test]\n    fn enum_in_vec() -> Result<()> {\n        // arrange\n        let types = to_named(&[ParamType::B256, ParamType::U8]);\n        let variants = EnumVariants::new(types)?;\n        let selector = (1, Token::U8(8), variants);\n        let enum_token = Token::Enum(Box::new(selector));\n\n        let vec_token = Token::Vector(vec![enum_token]);\n\n        // act\n        let result = ABIEncoder::default().encode(&[vec_token])?;\n\n        // assert\n        let expected = [\n            0, 0, 0, 0, 0, 0, 0, 1, // vec len\n            0, 0, 0, 0, 0, 0, 0, 1, 8, // enum discriminant and u8 value\n        ];\n\n        assert_eq!(result, expected);\n\n        Ok(())\n    }\n\n    #[test]\n    fn vec_in_struct() -> Result<()> {\n        // arrange\n        let token = Token::Struct(vec![Token::Vector(vec![Token::U64(5)]), Token::U8(9)]);\n\n        // act\n        let result = ABIEncoder::default().encode(&[token])?;\n\n        // assert\n        let expected = [\n            0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 5, // vec[len, u64]\n            9, // u8\n        ];\n\n        assert_eq!(result, expected);\n\n        Ok(())\n    }\n\n    #[test]\n    fn vec_in_vec() -> Result<()> {\n        // arrange\n        let token = Token::Vector(vec![Token::Vector(vec![Token::U8(5), Token::U8(6)])]);\n\n        // act\n        let result = ABIEncoder::default().encode(&[token])?;\n\n        // assert\n        let expected = [\n            0, 0, 0, 0, 0, 0, 0, 1, // vec1 len\n            0, 0, 0, 0, 0, 0, 0, 2, 5, 6, // vec2 [len, u8, u8]\n        ];\n\n        assert_eq!(result, expected);\n\n        Ok(())\n    }\n\n    #[test]\n    fn max_depth_surpassed() {\n        const MAX_DEPTH: usize = 2;\n        let config = EncoderConfig {\n            max_depth: MAX_DEPTH,\n            ..Default::default()\n        };\n        let msg = \"depth limit `2` reached while encoding. Try increasing it\".to_string();\n\n        [nested_struct, nested_enum, nested_tuple, nested_array]\n            .iter()\n            .map(|fun| fun(MAX_DEPTH + 1))\n            .for_each(|token| {\n                assert_encoding_failed(config, token, &msg);\n            });\n    }\n\n    fn assert_encoding_failed(config: EncoderConfig, token: Token, msg: &str) {\n        let encoder = ABIEncoder::new(config);\n\n        let err = encoder.encode(&[token]);\n\n        let Err(Error::Codec(actual_msg)) = err else {\n            panic!(\"expected a Codec error. Got: `{err:?}`\");\n        };\n        assert_eq!(actual_msg, msg);\n    }\n\n    fn nested_struct(depth: usize) -> Token {\n        let fields = if depth == 1 {\n            vec![Token::U8(255), Token::String(\"bloopblip\".to_string())]\n        } else {\n            vec![nested_struct(depth - 1)]\n        };\n\n        Token::Struct(fields)\n    }\n\n    fn nested_enum(depth: usize) -> Token {\n        if depth == 0 {\n            return Token::U8(255);\n        }\n\n        let inner_enum = nested_enum(depth - 1);\n\n        // Create a basic EnumSelector for the current level (the `EnumVariants` is not\n        // actually accurate but it's not used for encoding)\n        let selector = (\n            0u64,\n            inner_enum,\n            EnumVariants::new(to_named(&[ParamType::U64])).unwrap(),\n        );\n\n        Token::Enum(Box::new(selector))\n    }\n\n    fn nested_array(depth: usize) -> Token {\n        if depth == 1 {\n            Token::Array(vec![Token::U8(255)])\n        } else {\n            Token::Array(vec![nested_array(depth - 1)])\n        }\n    }\n\n    fn nested_tuple(depth: usize) -> Token {\n        let fields = if depth == 1 {\n            vec![Token::U8(255), Token::String(\"bloopblip\".to_string())]\n        } else {\n            vec![nested_tuple(depth - 1)]\n        };\n\n        Token::Tuple(fields)\n    }\n}\n"
  },
  {
    "path": "packages/fuels-core/src/codec/abi_formatter.rs",
    "content": "use std::{collections::HashMap, io::Read};\n\nuse fuel_abi_types::abi::unified_program::UnifiedProgramABI;\nuse itertools::Itertools;\n\nuse super::{ABIDecoder, DecoderConfig};\nuse crate::{Result, error, types::param_types::ParamType};\n\npub struct ABIFormatter {\n    functions: HashMap<String, Vec<ParamType>>,\n    configurables: Vec<(String, ParamType)>,\n    decoder: ABIDecoder,\n}\n\nimpl ABIFormatter {\n    pub fn has_fn(&self, fn_name: &str) -> bool {\n        self.functions.contains_key(fn_name)\n    }\n\n    pub fn with_decoder_config(mut self, config: DecoderConfig) -> Self {\n        self.decoder = ABIDecoder::new(config);\n        self\n    }\n\n    pub fn from_abi(abi: UnifiedProgramABI) -> Result<Self> {\n        let functions = abi\n            .functions\n            .iter()\n            .map(|fun| (fun.name.clone(), fun.clone()))\n            .collect::<HashMap<_, _>>();\n\n        let type_lookup = abi\n            .types\n            .iter()\n            .map(|decl| (decl.type_id, decl.clone()))\n            .collect::<HashMap<_, _>>();\n\n        let functions = functions\n            .into_iter()\n            .map(|(name, fun)| {\n                let args = fun\n                    .inputs\n                    .iter()\n                    .map(|type_application| {\n                        ParamType::try_from_type_application(type_application, &type_lookup)\n                    })\n                    .collect::<Result<Vec<_>>>()?;\n                Ok((name.clone(), args))\n            })\n            .collect::<Result<HashMap<_, _>>>()?;\n\n        let configurables = abi\n            .configurables\n            .into_iter()\n            .flatten()\n            .sorted_by_key(|c| c.offset)\n            .map(|c| {\n                let param_type =\n                    ParamType::try_from_type_application(&c.application, &type_lookup)?;\n\n                Ok((c.name, param_type))\n            })\n            .collect::<Result<Vec<_>>>()?;\n\n        Ok(Self {\n            functions,\n            decoder: ABIDecoder::default(),\n            configurables,\n        })\n    }\n\n    pub fn from_json_abi(abi: impl AsRef<str>) -> Result<Self> {\n        let parsed_abi = UnifiedProgramABI::from_json_abi(abi.as_ref())?;\n        Self::from_abi(parsed_abi)\n    }\n\n    pub fn decode_fn_args<R: Read>(&self, fn_name: &str, data: R) -> Result<Vec<String>> {\n        let args = self\n            .functions\n            .get(fn_name)\n            .ok_or_else(|| error!(Codec, \"Function '{}' not found in the ABI\", fn_name))?;\n\n        self.decoder.decode_multiple_as_debug_str(args, data)\n    }\n\n    pub fn decode_configurables<R: Read>(\n        &self,\n        configurable_data: R,\n    ) -> Result<Vec<(String, String)>> {\n        let param_types = self\n            .configurables\n            .iter()\n            .map(|(_, param_type)| param_type)\n            .cloned()\n            .collect::<Vec<_>>();\n\n        let decoded = self\n            .decoder\n            .decode_multiple_as_debug_str(&param_types, configurable_data)?\n            .into_iter()\n            .zip(&self.configurables)\n            .map(|(value, (name, _))| (name.clone(), value))\n            .collect();\n\n        Ok(decoded)\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use crate::types::errors::Error;\n\n    #[test]\n    fn gracefully_handles_missing_fn() {\n        // given\n        let decoder = ABIFormatter::from_abi(UnifiedProgramABI::default()).unwrap();\n\n        // when\n        let err = decoder\n            .decode_fn_args(\"non_existent_fn\", [].as_slice())\n            .unwrap_err();\n\n        // then\n        let Error::Codec(err) = err else {\n            panic!(\"Expected Codec error, got {:?}\", err);\n        };\n\n        assert_eq!(err, \"Function 'non_existent_fn' not found in the ABI\");\n    }\n}\n"
  },
  {
    "path": "packages/fuels-core/src/codec/function_selector.rs",
    "content": "pub use fuels_code_gen::utils::encode_fn_selector;\n\n/// This uses the default `EncoderConfig` configuration.\n#[macro_export]\nmacro_rules! calldata {\n    ( $($arg: expr),* ) => {\n        ::fuels::core::codec::ABIEncoder::default().encode(&[$(::fuels::core::traits::Tokenizable::into_token($arg)),*])\n    }\n}\n\npub use calldata;\n"
  },
  {
    "path": "packages/fuels-core/src/codec/logs.rs",
    "content": "use std::{\n    any::TypeId,\n    collections::{HashMap, HashSet},\n    fmt::{Debug, Formatter},\n    iter::FilterMap,\n};\n\n/// Trait that represents a log with a unique identifier.\npub trait Log {\n    /// Returns the unique identifier of the log as a string.\n    const LOG_ID: &'static str;\n    /// Returns the unique identifier of the log as a `u64`.\n    const LOG_ID_U64: u64;\n}\n\n#[derive(Debug, Clone)]\npub struct ErrorDetails {\n    pub(crate) pkg: String,\n    pub(crate) file: String,\n    pub(crate) line: u64,\n    pub(crate) column: u64,\n    pub(crate) log_id: Option<String>,\n    pub(crate) msg: Option<String>,\n}\n\nimpl ErrorDetails {\n    pub fn new(\n        pkg: String,\n        file: String,\n        line: u64,\n        column: u64,\n        log_id: Option<String>,\n        msg: Option<String>,\n    ) -> Self {\n        Self {\n            pkg,\n            file,\n            line,\n            column,\n            log_id,\n            msg,\n        }\n    }\n}\n\nuse fuel_tx::{ContractId, Receipt};\n\nuse crate::{\n    codec::{ABIDecoder, DecoderConfig},\n    traits::{Parameterize, Tokenizable},\n    types::errors::{Error, Result, error},\n};\n\n#[derive(Clone)]\npub struct LogFormatter {\n    formatter: fn(DecoderConfig, &[u8]) -> Result<String>,\n    type_id: TypeId,\n}\n\nimpl LogFormatter {\n    pub fn new_log<T: Tokenizable + Parameterize + Debug + 'static>() -> Self {\n        Self {\n            formatter: Self::format_log::<T>,\n            type_id: TypeId::of::<T>(),\n        }\n    }\n\n    pub fn new_error<T: Tokenizable + Parameterize + std::error::Error + 'static>() -> Self {\n        Self {\n            formatter: Self::format_error::<T>,\n            type_id: TypeId::of::<T>(),\n        }\n    }\n\n    fn format_log<T: Parameterize + Tokenizable + Debug>(\n        decoder_config: DecoderConfig,\n        bytes: &[u8],\n    ) -> Result<String> {\n        let token = ABIDecoder::new(decoder_config).decode(&T::param_type(), bytes)?;\n\n        Ok(format!(\"{:?}\", T::from_token(token)?))\n    }\n\n    fn format_error<T: Parameterize + Tokenizable + std::error::Error>(\n        decoder_config: DecoderConfig,\n        bytes: &[u8],\n    ) -> Result<String> {\n        let token = ABIDecoder::new(decoder_config).decode(&T::param_type(), bytes)?;\n\n        Ok(T::from_token(token)?.to_string())\n    }\n\n    pub fn can_handle_type<T: Tokenizable + Parameterize + 'static>(&self) -> bool {\n        TypeId::of::<T>() == self.type_id\n    }\n\n    pub fn format(&self, decoder_config: DecoderConfig, bytes: &[u8]) -> Result<String> {\n        (self.formatter)(decoder_config, bytes)\n    }\n}\n\nimpl Debug for LogFormatter {\n    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {\n        f.debug_struct(\"LogFormatter\")\n            .field(\"type_id\", &self.type_id)\n            .finish()\n    }\n}\n\n/// Holds a unique log ID\n#[derive(Debug, Clone, Default, PartialEq, Eq, Hash)]\npub struct LogId(ContractId, String);\n\n/// Struct used to pass the log mappings from the Abigen\n#[derive(Debug, Clone, Default)]\npub struct LogDecoder {\n    /// A mapping of LogId and param-type\n    log_formatters: HashMap<LogId, LogFormatter>,\n    error_codes: HashMap<u64, ErrorDetails>,\n    decoder_config: DecoderConfig,\n}\n\n#[derive(Debug)]\npub struct LogResult {\n    pub results: Vec<Result<String>>,\n}\n\nimpl LogResult {\n    pub fn filter_succeeded(&self) -> Vec<&str> {\n        self.results\n            .iter()\n            .filter_map(|result| result.as_deref().ok())\n            .collect()\n    }\n\n    pub fn filter_failed(&self) -> Vec<&Error> {\n        self.results\n            .iter()\n            .filter_map(|result| result.as_ref().err())\n            .collect()\n    }\n}\n\nimpl LogDecoder {\n    pub fn new(\n        log_formatters: HashMap<LogId, LogFormatter>,\n        error_codes: HashMap<u64, ErrorDetails>,\n    ) -> Self {\n        Self {\n            log_formatters,\n            error_codes,\n            decoder_config: Default::default(),\n        }\n    }\n\n    pub fn get_error_codes(&self, id: &u64) -> Option<&ErrorDetails> {\n        self.error_codes.get(id)\n    }\n\n    pub fn set_decoder_config(&mut self, decoder_config: DecoderConfig) -> &mut Self {\n        self.decoder_config = decoder_config;\n        self\n    }\n\n    /// Get all logs results from the given receipts as `Result<String>`\n    pub fn decode_logs(&self, receipts: &[Receipt]) -> LogResult {\n        let results = receipts\n            .iter()\n            .extract_log_id_and_data()\n            .map(|(log_id, data)| self.format_log(&log_id, &data))\n            .collect();\n\n        LogResult { results }\n    }\n\n    fn format_log(&self, log_id: &LogId, data: &[u8]) -> Result<String> {\n        self.log_formatters\n            .get(log_id)\n            .ok_or_else(|| {\n                error!(\n                    Codec,\n                    \"missing log formatter for log_id: `{:?}`, data: `{:?}`. \\\n                     Consider adding external contracts using `with_contracts()`\",\n                    log_id,\n                    data\n                )\n            })\n            .and_then(|log_formatter| log_formatter.format(self.decoder_config, data))\n    }\n\n    pub(crate) fn decode_last_log(&self, receipts: &[Receipt]) -> Result<String> {\n        receipts\n            .iter()\n            .rev()\n            .extract_log_id_and_data()\n            .next()\n            .ok_or_else(|| error!(Codec, \"no receipts found for decoding last log\"))\n            .and_then(|(log_id, data)| self.format_log(&log_id, &data))\n    }\n\n    pub(crate) fn decode_last_two_logs(&self, receipts: &[Receipt]) -> Result<(String, String)> {\n        let res = receipts\n            .iter()\n            .rev()\n            .extract_log_id_and_data()\n            .map(|(log_id, data)| self.format_log(&log_id, &data))\n            .take(2)\n            .collect::<Result<Vec<_>>>();\n\n        match res.as_deref() {\n            Ok([rhs, lhs]) => Ok((lhs.to_string(), rhs.to_string())),\n            Ok(some_slice) => Err(error!(\n                Codec,\n                \"expected to have two logs. Found {}\",\n                some_slice.len()\n            )),\n            Err(_) => Err(res.expect_err(\"must be an error\")),\n        }\n    }\n\n    /// Get decoded logs with specific type from the given receipts.\n    /// Note that this method returns the actual type and not a `String` representation.\n    pub fn decode_logs_with_type<T: Tokenizable + Parameterize + 'static>(\n        &self,\n        receipts: &[Receipt],\n    ) -> Result<Vec<T>> {\n        let target_ids: HashSet<LogId> = self\n            .log_formatters\n            .iter()\n            .filter(|(_, log_formatter)| log_formatter.can_handle_type::<T>())\n            .map(|(log_id, _)| log_id.clone())\n            .collect();\n\n        receipts\n            .iter()\n            .extract_log_id_and_data()\n            .filter_map(|(log_id, bytes)| {\n                target_ids.contains(&log_id).then(|| {\n                    let token = ABIDecoder::new(self.decoder_config)\n                        .decode(&T::param_type(), bytes.as_slice())?;\n\n                    T::from_token(token)\n                })\n            })\n            .collect()\n    }\n\n    /// Get LogIds and lazy decoders for specific type from a single receipt.\n    pub fn decode_logs_lazy<'a, T: Tokenizable + Parameterize + 'static>(\n        &'a self,\n        receipt: &'a Receipt,\n    ) -> impl Iterator<Item = impl FnOnce() -> Result<T>> + 'a {\n        let target_ids: HashSet<&LogId> = self\n            .log_formatters\n            .iter()\n            .filter(|(_, log_formatter)| log_formatter.can_handle_type::<T>())\n            .map(|(log_id, _)| log_id)\n            .collect();\n\n        std::iter::once(receipt).extract_matching_logs_lazy::<T>(target_ids, self.decoder_config)\n    }\n\n    pub fn merge(&mut self, log_decoder: LogDecoder) {\n        self.log_formatters.extend(log_decoder.log_formatters);\n        self.error_codes.extend(log_decoder.error_codes);\n    }\n}\n\ntrait ExtractLogIdData {\n    type Output: Iterator<Item = (LogId, Vec<u8>)>;\n    fn extract_log_id_and_data(self) -> Self::Output;\n}\n\ntrait ExtractLogIdLazy {\n    fn extract_matching_logs_lazy<T: Tokenizable + Parameterize + 'static>(\n        self,\n        target_ids: HashSet<&LogId>,\n        decoder_config: DecoderConfig,\n    ) -> impl Iterator<Item = impl FnOnce() -> Result<T>>;\n}\n\nimpl<'a, I: Iterator<Item = &'a Receipt>> ExtractLogIdData for I {\n    type Output = FilterMap<Self, fn(&Receipt) -> Option<(LogId, Vec<u8>)>>;\n    fn extract_log_id_and_data(self) -> Self::Output {\n        self.filter_map(|r| match r {\n            Receipt::LogData {\n                rb,\n                data: Some(data),\n                id,\n                ..\n            } => Some((LogId(*id, (*rb).to_string()), data.to_vec())),\n            Receipt::Log { ra, rb, id, .. } => {\n                Some((LogId(*id, (*rb).to_string()), ra.to_be_bytes().to_vec()))\n            }\n            _ => None,\n        })\n    }\n}\n\nimpl<'a, I: Iterator<Item = &'a Receipt>> ExtractLogIdLazy for I {\n    fn extract_matching_logs_lazy<T: Tokenizable + Parameterize + 'static>(\n        self,\n        target_ids: HashSet<&LogId>,\n        decoder_config: DecoderConfig,\n    ) -> impl Iterator<Item = impl FnOnce() -> Result<T>> {\n        self.filter_map(move |r| {\n            let log_id = match r {\n                Receipt::LogData { rb, id, .. } => LogId(*id, (*rb).to_string()),\n                Receipt::Log { rb, id, .. } => LogId(*id, (*rb).to_string()),\n                _ => return None,\n            };\n\n            if !target_ids.contains(&log_id) {\n                return None;\n            }\n\n            enum Data<'a> {\n                LogData(&'a [u8]),\n                LogRa(u64),\n            }\n\n            let data = match r {\n                Receipt::LogData {\n                    data: Some(data), ..\n                } => Some(Data::LogData(data.as_slice())),\n                Receipt::Log { ra, .. } => Some(Data::LogRa(*ra)),\n                _ => None,\n            };\n\n            data.map(move |data| {\n                move || {\n                    let normalized_data = match data {\n                        Data::LogData(data) => data,\n                        Data::LogRa(ra) => &ra.to_be_bytes(),\n                    };\n                    let token = ABIDecoder::new(decoder_config)\n                        .decode(&T::param_type(), normalized_data)?;\n                    T::from_token(token)\n                }\n            })\n        })\n    }\n}\n\npub fn log_formatters_lookup(\n    log_id_log_formatter_pairs: Vec<(String, LogFormatter)>,\n    contract_id: ContractId,\n) -> HashMap<LogId, LogFormatter> {\n    log_id_log_formatter_pairs\n        .into_iter()\n        .map(|(id, log_formatter)| (LogId(contract_id, id), log_formatter))\n        .collect()\n}\n"
  },
  {
    "path": "packages/fuels-core/src/codec/utils.rs",
    "content": "use crate::types::errors::{Result, error};\n\npub(crate) struct CounterWithLimit {\n    count: usize,\n    max: usize,\n    name: String,\n    direction: CodecDirection,\n}\n\n#[derive(Debug)]\npub(crate) enum CodecDirection {\n    Encoding,\n    Decoding,\n}\n\nimpl std::fmt::Display for CodecDirection {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        match self {\n            CodecDirection::Encoding => write!(f, \"encoding\"),\n            CodecDirection::Decoding => write!(f, \"decoding\"),\n        }\n    }\n}\n\nimpl CounterWithLimit {\n    pub(crate) fn new(max: usize, name: impl Into<String>, direction: CodecDirection) -> Self {\n        Self {\n            count: 0,\n            max,\n            direction,\n            name: name.into(),\n        }\n    }\n\n    pub(crate) fn increase(&mut self) -> Result<()> {\n        self.count += 1;\n        if self.count > self.max {\n            return Err(error!(\n                Codec,\n                \"{} limit `{}` reached while {}. Try increasing it\",\n                self.name,\n                self.max,\n                self.direction\n            ));\n        }\n        Ok(())\n    }\n\n    pub(crate) fn decrease(&mut self) {\n        if self.count > 0 {\n            self.count -= 1;\n        }\n    }\n}\n"
  },
  {
    "path": "packages/fuels-core/src/codec.rs",
    "content": "mod abi_decoder;\nmod abi_encoder;\nmod abi_formatter;\nmod function_selector;\nmod logs;\nmod utils;\n\nuse std::io::Read;\n\npub use abi_decoder::*;\npub use abi_encoder::*;\npub use abi_formatter::*;\npub use function_selector::*;\npub use logs::*;\n\nuse crate::{\n    traits::{Parameterize, Tokenizable},\n    types::errors::Result,\n};\n\n/// Decodes `bytes` into type `T` following the schema defined by T's `Parameterize` impl\npub fn try_from_bytes<T>(bytes: impl Read, decoder_config: DecoderConfig) -> Result<T>\nwhere\n    T: Parameterize + Tokenizable,\n{\n    let token = ABIDecoder::new(decoder_config).decode(&T::param_type(), bytes)?;\n\n    T::from_token(token)\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use crate::{\n        constants::WORD_SIZE,\n        types::{Address, AsciiString, AssetId, ContractId},\n    };\n\n    #[test]\n    fn convert_all_from_bool_to_u64() -> Result<()> {\n        let bytes = [255; WORD_SIZE];\n\n        macro_rules! test_decode {\n            ($($for_type: ident),*) => {\n                $(assert_eq!(\n                        try_from_bytes::<$for_type>(bytes.as_slice(), DecoderConfig::default())?,\n                        $for_type::MAX\n                );)*\n            };\n        }\n\n        assert!(try_from_bytes::<bool>(\n            bytes.as_slice(),\n            DecoderConfig::default()\n        )?);\n\n        test_decode!(u8, u16, u32, u64);\n\n        Ok(())\n    }\n\n    #[test]\n    fn convert_bytes_into_tuple() -> Result<()> {\n        let tuple_in_bytes = [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2];\n\n        let the_tuple: (u64, u32) =\n            try_from_bytes(tuple_in_bytes.as_slice(), DecoderConfig::default())?;\n\n        assert_eq!(the_tuple, (1, 2));\n\n        Ok(())\n    }\n\n    #[test]\n    fn convert_native_types() -> Result<()> {\n        let bytes = [255; 32];\n\n        macro_rules! test_decode {\n            ($($for_type: ident),*) => {\n                $(assert_eq!(\n                        try_from_bytes::<$for_type>(bytes.as_slice(), DecoderConfig::default())?,\n                        $for_type::new(bytes.as_slice().try_into()?)\n                );)*\n            };\n        }\n\n        test_decode!(Address, ContractId, AssetId);\n\n        Ok(())\n    }\n\n    #[test]\n    fn string_slice_is_read_in_total() {\n        // This was a bug where the decoder read more bytes than it reported, causing the next\n        // element to be read incorrectly.\n\n        // given\n        #[derive(\n            fuels_macros::Tokenizable, fuels_macros::Parameterize, Clone, PartialEq, Debug,\n        )]\n        #[FuelsCorePath = \"crate\"]\n        #[FuelsTypesPath = \"crate::types\"]\n        struct Test {\n            name: AsciiString,\n            age: u64,\n        }\n\n        let input = Test {\n            name: AsciiString::new(\"Alice\".to_owned()).unwrap(),\n            age: 42,\n        };\n\n        let encoded = ABIEncoder::default()\n            .encode(&[input.clone().into_token()])\n            .unwrap();\n\n        // when\n        let decoded = try_from_bytes::<Test>(encoded.as_slice(), DecoderConfig::default()).unwrap();\n\n        // then\n        assert_eq!(decoded, input);\n    }\n}\n"
  },
  {
    "path": "packages/fuels-core/src/lib.rs",
    "content": "pub mod codec;\npub mod traits;\npub mod types;\nmod utils;\n\npub use utils::*;\n\nuse crate::types::errors::Result;\n\n#[derive(Debug, Clone, Default, PartialEq)]\npub struct Configurable {\n    /// The offset (in bytes) within the binary where the data is located.\n    pub offset: u64,\n    /// The data related to the configurable.\n    pub data: Vec<u8>,\n}\n\n#[derive(Debug, Clone, Default, PartialEq)]\npub struct Configurables {\n    pub offsets_with_data: Vec<Configurable>,\n}\n\nimpl Configurables {\n    pub fn new(offsets_with_data: Vec<Configurable>) -> Self {\n        Self { offsets_with_data }\n    }\n\n    pub fn with_shifted_offsets(self, shift: i64) -> Result<Self> {\n        let new_offsets_with_data = self\n            .offsets_with_data\n            .into_iter()\n            .map(|c| {\n                let new_offset = if shift.is_negative() {\n                    c.offset.checked_sub(shift.unsigned_abs())\n                } else {\n                    c.offset.checked_add(shift.unsigned_abs())\n                };\n\n                let new_offset = new_offset.ok_or_else(|| {\n                    crate::error!(\n                        Other,\n                        \"Overflow occurred while shifting offset: {} + {shift}\",\n                        c.offset\n                    )\n                })?;\n\n                Ok(Configurable {\n                    offset: new_offset,\n                    data: c.data,\n                })\n            })\n            .collect::<Result<Vec<_>>>()?;\n\n        Ok(Self {\n            offsets_with_data: new_offsets_with_data,\n        })\n    }\n\n    pub fn update_constants_in(&self, binary: &mut [u8]) {\n        for c in &self.offsets_with_data {\n            let offset = c.offset as usize;\n            binary[offset..offset + c.data.len()].copy_from_slice(&c.data)\n        }\n    }\n}\n\nimpl From<Configurables> for Vec<Configurable> {\n    fn from(config: Configurables) -> Vec<Configurable> {\n        config.offsets_with_data.clone()\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn test_with_shifted_offsets_positive_shift() {\n        let offsets_with_data = vec![Configurable {\n            offset: 10u64,\n            data: vec![1, 2, 3],\n        }];\n        let configurables = Configurables::new(offsets_with_data.clone());\n        let shifted_configurables = configurables.with_shifted_offsets(5).unwrap();\n        let expected_offsets_with_data = vec![Configurable {\n            offset: 15u64,\n            data: vec![1, 2, 3],\n        }];\n        assert_eq!(\n            shifted_configurables.offsets_with_data,\n            expected_offsets_with_data\n        );\n    }\n\n    #[test]\n    fn test_with_shifted_offsets_negative_shift() {\n        let offsets_with_data = vec![Configurable {\n            offset: 10u64,\n            data: vec![4, 5, 6],\n        }];\n        let configurables = Configurables::new(offsets_with_data.clone());\n        let shifted_configurables = configurables.with_shifted_offsets(-5).unwrap();\n        let expected_offsets_with_data = vec![Configurable {\n            offset: 5u64,\n            data: vec![4, 5, 6],\n        }];\n        assert_eq!(\n            shifted_configurables.offsets_with_data,\n            expected_offsets_with_data\n        );\n    }\n\n    #[test]\n    fn test_with_shifted_offsets_zero_shift() {\n        let offsets_with_data = vec![Configurable {\n            offset: 20u64,\n            data: vec![7, 8, 9],\n        }];\n        let configurables = Configurables::new(offsets_with_data.clone());\n        let shifted_configurables = configurables.with_shifted_offsets(0).unwrap();\n        let expected_offsets_with_data = offsets_with_data;\n        assert_eq!(\n            shifted_configurables.offsets_with_data,\n            expected_offsets_with_data\n        );\n    }\n\n    #[test]\n    fn test_with_shifted_offsets_overflow() {\n        let offsets_with_data = vec![Configurable {\n            offset: u64::MAX - 1,\n            data: vec![1, 2, 3],\n        }];\n        let configurables = Configurables::new(offsets_with_data);\n        let result = configurables.with_shifted_offsets(10);\n        assert!(result.is_err());\n        if let Err(e) = result {\n            assert!(\n                e.to_string()\n                    .contains(\"Overflow occurred while shifting offset\")\n            );\n        }\n    }\n\n    #[test]\n    fn test_with_shifted_offsets_underflow() {\n        let offsets_with_data = vec![Configurable {\n            offset: 5u64,\n            data: vec![4, 5, 6],\n        }];\n        let configurables = Configurables::new(offsets_with_data);\n        let result = configurables.with_shifted_offsets(-10);\n        assert!(result.is_err());\n        if let Err(e) = result {\n            assert!(\n                e.to_string()\n                    .contains(\"Overflow occurred while shifting offset\")\n            );\n        }\n    }\n}\n"
  },
  {
    "path": "packages/fuels-core/src/traits/parameterize.rs",
    "content": "use fuel_types::{Address, AssetId, ContractId};\n\nuse crate::types::{\n    AsciiString, Bits256, Bytes, RawSlice, SizedAsciiString,\n    param_types::{EnumVariants, ParamType},\n};\n\n/// `abigen` requires `Parameterized` to construct nested types. It is also used by `try_from_bytes`\n/// to facilitate the instantiation of custom types from bytes.\npub trait Parameterize {\n    fn param_type() -> ParamType;\n}\n\nimpl Parameterize for Bits256 {\n    fn param_type() -> ParamType {\n        ParamType::B256\n    }\n}\n\nimpl Parameterize for RawSlice {\n    fn param_type() -> ParamType {\n        ParamType::RawSlice\n    }\n}\n\nimpl<const SIZE: usize, T: Parameterize> Parameterize for [T; SIZE] {\n    fn param_type() -> ParamType {\n        ParamType::Array(Box::new(T::param_type()), SIZE)\n    }\n}\n\nimpl<T: Parameterize> Parameterize for Vec<T> {\n    fn param_type() -> ParamType {\n        ParamType::Vector(Box::new(T::param_type()))\n    }\n}\n\nimpl Parameterize for Bytes {\n    fn param_type() -> ParamType {\n        ParamType::Bytes\n    }\n}\n\nimpl Parameterize for String {\n    fn param_type() -> ParamType {\n        ParamType::String\n    }\n}\n\nimpl Parameterize for Address {\n    fn param_type() -> ParamType {\n        ParamType::Struct {\n            name: \"Address\".to_string(),\n            fields: vec![(\"0\".to_string(), ParamType::B256)],\n            generics: vec![],\n        }\n    }\n}\n\nimpl Parameterize for ContractId {\n    fn param_type() -> ParamType {\n        ParamType::Struct {\n            name: \"ContractId\".to_string(),\n            fields: vec![(\"0\".to_string(), ParamType::B256)],\n            generics: vec![],\n        }\n    }\n}\n\nimpl Parameterize for AssetId {\n    fn param_type() -> ParamType {\n        ParamType::Struct {\n            name: \"AssetId\".to_string(),\n            fields: vec![(\"0\".to_string(), ParamType::B256)],\n            generics: vec![],\n        }\n    }\n}\n\nimpl Parameterize for () {\n    fn param_type() -> ParamType {\n        ParamType::Unit\n    }\n}\n\nimpl Parameterize for bool {\n    fn param_type() -> ParamType {\n        ParamType::Bool\n    }\n}\n\nimpl Parameterize for u8 {\n    fn param_type() -> ParamType {\n        ParamType::U8\n    }\n}\n\nimpl Parameterize for u16 {\n    fn param_type() -> ParamType {\n        ParamType::U16\n    }\n}\n\nimpl Parameterize for u32 {\n    fn param_type() -> ParamType {\n        ParamType::U32\n    }\n}\n\nimpl Parameterize for u64 {\n    fn param_type() -> ParamType {\n        ParamType::U64\n    }\n}\n\nimpl Parameterize for u128 {\n    fn param_type() -> ParamType {\n        ParamType::U128\n    }\n}\n\nimpl<T> Parameterize for Option<T>\nwhere\n    T: Parameterize,\n{\n    fn param_type() -> ParamType {\n        let variant_param_types = vec![\n            (\"None\".to_string(), ParamType::Unit),\n            (\"Some\".to_string(), T::param_type()),\n        ];\n        let enum_variants = EnumVariants::new(variant_param_types)\n            .expect(\"should never happen as we provided valid Option param types\");\n        ParamType::Enum {\n            name: \"Option\".to_string(),\n            enum_variants,\n            generics: vec![T::param_type()],\n        }\n    }\n}\n\nimpl<T, E> Parameterize for Result<T, E>\nwhere\n    T: Parameterize,\n    E: Parameterize,\n{\n    fn param_type() -> ParamType {\n        let variant_param_types = vec![\n            (\"Ok\".to_string(), T::param_type()),\n            (\"Err\".to_string(), E::param_type()),\n        ];\n        let enum_variants = EnumVariants::new(variant_param_types)\n            .expect(\"should never happen as we provided valid Result param types\");\n        ParamType::Enum {\n            name: \"Result\".to_string(),\n            enum_variants,\n            generics: vec![T::param_type(), E::param_type()],\n        }\n    }\n}\n\nimpl<const LEN: usize> Parameterize for SizedAsciiString<LEN> {\n    fn param_type() -> ParamType {\n        ParamType::StringArray(LEN)\n    }\n}\n\nimpl Parameterize for AsciiString {\n    fn param_type() -> ParamType {\n        ParamType::StringSlice\n    }\n}\n\n// Here we implement `Parameterize` for a given tuple of a given length.\n// This is done this way because we can't use `impl<T> Parameterize for (T,)`.\n// So we implement `Parameterize` for each tuple length, covering\n// a reasonable range of tuple lengths.\nmacro_rules! impl_parameterize_tuples {\n    ($num: expr, $( $ty: ident : $no: tt, )+) => {\n        impl<$($ty, )+> Parameterize for ($($ty,)+) where\n            $(\n                $ty: Parameterize,\n            )+\n        {\n            fn param_type() -> ParamType {\n                ParamType::Tuple(vec![\n                    $( $ty::param_type(), )+\n                ])\n            }\n\n        }\n    }\n}\n\n// And where we actually implement the `Parameterize` for tuples\n// from size 1 to size 16.\nimpl_parameterize_tuples!(1, A:0, );\nimpl_parameterize_tuples!(2, A:0, B:1, );\nimpl_parameterize_tuples!(3, A:0, B:1, C:2, );\nimpl_parameterize_tuples!(4, A:0, B:1, C:2, D:3, );\nimpl_parameterize_tuples!(5, A:0, B:1, C:2, D:3, E:4, );\nimpl_parameterize_tuples!(6, A:0, B:1, C:2, D:3, E:4, F:5, );\nimpl_parameterize_tuples!(7, A:0, B:1, C:2, D:3, E:4, F:5, G:6, );\nimpl_parameterize_tuples!(8, A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, );\nimpl_parameterize_tuples!(9, A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, );\nimpl_parameterize_tuples!(10, A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, );\nimpl_parameterize_tuples!(11, A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10, );\nimpl_parameterize_tuples!(12, A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10, L:11, );\nimpl_parameterize_tuples!(13, A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10, L:11, M:12, );\nimpl_parameterize_tuples!(14, A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10, L:11, M:12, N:13, );\nimpl_parameterize_tuples!(15, A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10, L:11, M:12, N:13, O:14, );\nimpl_parameterize_tuples!(16, A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10, L:11, M:12, N:13, O:14, P:15, );\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn sized_ascii_string_is_parameterized_correctly() {\n        let param_type = SizedAsciiString::<3>::param_type();\n\n        assert!(matches!(param_type, ParamType::StringArray(3)));\n    }\n\n    #[test]\n    fn test_param_type_b256() {\n        assert_eq!(Bits256::param_type(), ParamType::B256);\n    }\n\n    #[test]\n    fn test_param_type_raw_slice() {\n        assert_eq!(RawSlice::param_type(), ParamType::RawSlice);\n    }\n}\n"
  },
  {
    "path": "packages/fuels-core/src/traits/signer.rs",
    "content": "use async_trait::async_trait;\nuse auto_impl::auto_impl;\nuse fuel_crypto::{Message, Signature};\n\nuse crate::types::{Address, errors::Result};\n\n/// Trait for signing transactions and messages\n///\n/// Implement this trait to support different signing modes, e.g. hardware wallet, hosted etc.\n#[cfg_attr(target_arch = \"wasm32\", async_trait(?Send))]\n#[cfg_attr(not(target_arch = \"wasm32\"), async_trait)]\n#[auto_impl(&, Box, Rc, Arc)]\npub trait Signer {\n    async fn sign(&self, message: Message) -> Result<Signature>;\n    fn address(&self) -> Address;\n}\n"
  },
  {
    "path": "packages/fuels-core/src/traits/tokenizable.rs",
    "content": "use fuel_types::{Address, AssetId, ContractId};\n\nuse crate::{\n    traits::Parameterize,\n    types::{\n        AsciiString, Bits256, Bytes, RawSlice, SizedAsciiString, StaticStringToken, Token,\n        errors::{Result, error},\n        param_types::ParamType,\n    },\n};\n\npub trait Tokenizable {\n    /// Converts a `Token` into expected type.\n    fn from_token(token: Token) -> Result<Self>\n    where\n        Self: Sized;\n    /// Converts a specified type back into token.\n    fn into_token(self) -> Token;\n}\n\nimpl Tokenizable for Token {\n    fn from_token(token: Token) -> Result<Self> {\n        Ok(token)\n    }\n    fn into_token(self) -> Token {\n        self\n    }\n}\n\nimpl Tokenizable for Bits256 {\n    fn from_token(token: Token) -> Result<Self>\n    where\n        Self: Sized,\n    {\n        match token {\n            Token::B256(data) => Ok(Bits256(data)),\n            _ => Err(error!(\n                Other,\n                \"`Bits256` cannot be constructed from token {token}\"\n            )),\n        }\n    }\n\n    fn into_token(self) -> Token {\n        Token::B256(self.0)\n    }\n}\n\nimpl<T: Tokenizable> Tokenizable for Vec<T> {\n    fn from_token(token: Token) -> Result<Self>\n    where\n        Self: Sized,\n    {\n        if let Token::Vector(tokens) = token {\n            tokens.into_iter().map(Tokenizable::from_token).collect()\n        } else {\n            Err(error!(\n                Other,\n                \"`Vec::from_token` must only be given a `Token::Vector`. Got: `{token}`\"\n            ))\n        }\n    }\n\n    fn into_token(self) -> Token {\n        let tokens = self.into_iter().map(Tokenizable::into_token).collect();\n        Token::Vector(tokens)\n    }\n}\n\nimpl Tokenizable for bool {\n    fn from_token(token: Token) -> Result<Self> {\n        match token {\n            Token::Bool(data) => Ok(data),\n            other => Err(error!(Other, \"expected `bool`, got `{:?}`\", other)),\n        }\n    }\n    fn into_token(self) -> Token {\n        Token::Bool(self)\n    }\n}\n\nimpl Tokenizable for () {\n    fn from_token(token: Token) -> Result<Self>\n    where\n        Self: Sized,\n    {\n        match token {\n            Token::Unit => Ok(()),\n            other => Err(error!(Other, \"expected `Unit`, got `{:?}`\", other)),\n        }\n    }\n\n    fn into_token(self) -> Token {\n        Token::Unit\n    }\n}\n\nimpl Tokenizable for u8 {\n    fn from_token(token: Token) -> Result<Self> {\n        match token {\n            Token::U8(data) => Ok(data),\n            other => Err(error!(Other, \"expected `u8`, got `{:?}`\", other)),\n        }\n    }\n    fn into_token(self) -> Token {\n        Token::U8(self)\n    }\n}\n\nimpl Tokenizable for u16 {\n    fn from_token(token: Token) -> Result<Self> {\n        match token {\n            Token::U16(data) => Ok(data),\n            other => Err(error!(Other, \"expected `u16`, got `{:?}`\", other)),\n        }\n    }\n    fn into_token(self) -> Token {\n        Token::U16(self)\n    }\n}\n\nimpl Tokenizable for u32 {\n    fn from_token(token: Token) -> Result<Self> {\n        match token {\n            Token::U32(data) => Ok(data),\n            other => Err(error!(Other, \"expected `u32`, got {:?}\", other)),\n        }\n    }\n    fn into_token(self) -> Token {\n        Token::U32(self)\n    }\n}\n\nimpl Tokenizable for u64 {\n    fn from_token(token: Token) -> Result<Self> {\n        match token {\n            Token::U64(data) => Ok(data),\n            other => Err(error!(Other, \"expected `u64`, got {:?}\", other)),\n        }\n    }\n    fn into_token(self) -> Token {\n        Token::U64(self)\n    }\n}\n\nimpl Tokenizable for u128 {\n    fn from_token(token: Token) -> Result<Self> {\n        match token {\n            Token::U128(data) => Ok(data),\n            other => Err(error!(Other, \"expected `u128`, got {:?}\", other)),\n        }\n    }\n    fn into_token(self) -> Token {\n        Token::U128(self)\n    }\n}\n\nimpl Tokenizable for RawSlice {\n    fn from_token(token: Token) -> Result<Self>\n    where\n        Self: Sized,\n    {\n        match token {\n            Token::RawSlice(contents) => Ok(Self(contents)),\n            _ => Err(error!(\n                Other,\n                \"`RawSlice::from_token` expected a token of the variant `Token::RawSlice`, got: `{token}`\"\n            )),\n        }\n    }\n\n    fn into_token(self) -> Token {\n        Token::RawSlice(Vec::from(self))\n    }\n}\n\nimpl Tokenizable for Bytes {\n    fn from_token(token: Token) -> Result<Self>\n    where\n        Self: Sized,\n    {\n        match token {\n            Token::Bytes(contents) => Ok(Self(contents)),\n            _ => Err(error!(\n                Other,\n                \"`Bytes::from_token` expected a token of the variant `Token::Bytes`, got: `{token}`\"\n            )),\n        }\n    }\n\n    fn into_token(self) -> Token {\n        Token::Bytes(Vec::from(self))\n    }\n}\n\nimpl Tokenizable for String {\n    fn from_token(token: Token) -> Result<Self>\n    where\n        Self: Sized,\n    {\n        match token {\n            Token::String(string) => Ok(string),\n            _ => Err(error!(\n                Other,\n                \"`String::from_token` expected a token of the variant `Token::String`, got: `{token}`\"\n            )),\n        }\n    }\n\n    fn into_token(self) -> Token {\n        Token::String(self)\n    }\n}\n\n// Here we implement `Tokenizable` for a given tuple of a given length.\n// This is done this way because we can't use `impl<T> Tokenizable for (T,)`.\n// So we implement `Tokenizable` for each tuple length, covering\n// a reasonable range of tuple lengths.\nmacro_rules! impl_tokenizable_tuples {\n    ($num: expr, $( $ty: ident : $no: tt, )+) => {\n        impl<$($ty, )+> Tokenizable for ($($ty,)+) where\n            $(\n                $ty: Tokenizable,\n            )+\n        {\n            fn from_token(token: Token) -> Result<Self> {\n                match token {\n                    Token::Tuple(tokens) => {\n                        let mut it = tokens.into_iter();\n                        let mut next_token = move || {\n                            it.next().ok_or_else(|| {\n                                error!(Other, \"ran out of tokens before tuple could be constructed\")\n                            })\n                        };\n                        Ok(($(\n                          $ty::from_token(next_token()?)?,\n                        )+))\n                    },\n                    other => Err(error!(Other,\n                        \"expected `Tuple`, got `{:?}`\",\n                        other\n                    )),\n                }\n            }\n\n            fn into_token(self) -> Token {\n                Token::Tuple(vec![\n                    $( self.$no.into_token(), )+\n                ])\n            }\n        }\n\n    }\n}\n\n// And where we actually implement the `Tokenizable` for tuples\n// from size 1 to size 16.\nimpl_tokenizable_tuples!(1, A:0, );\nimpl_tokenizable_tuples!(2, A:0, B:1, );\nimpl_tokenizable_tuples!(3, A:0, B:1, C:2, );\nimpl_tokenizable_tuples!(4, A:0, B:1, C:2, D:3, );\nimpl_tokenizable_tuples!(5, A:0, B:1, C:2, D:3, E:4, );\nimpl_tokenizable_tuples!(6, A:0, B:1, C:2, D:3, E:4, F:5, );\nimpl_tokenizable_tuples!(7, A:0, B:1, C:2, D:3, E:4, F:5, G:6, );\nimpl_tokenizable_tuples!(8, A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, );\nimpl_tokenizable_tuples!(9, A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, );\nimpl_tokenizable_tuples!(10, A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, );\nimpl_tokenizable_tuples!(11, A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10, );\nimpl_tokenizable_tuples!(12, A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10, L:11, );\nimpl_tokenizable_tuples!(13, A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10, L:11, M:12, );\nimpl_tokenizable_tuples!(14, A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10, L:11, M:12, N:13, );\nimpl_tokenizable_tuples!(15, A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10, L:11, M:12, N:13, O:14, );\nimpl_tokenizable_tuples!(16, A:0, B:1, C:2, D:3, E:4, F:5, G:6, H:7, I:8, J:9, K:10, L:11, M:12, N:13, O:14, P:15, );\n\nimpl Tokenizable for ContractId {\n    fn from_token(token: Token) -> Result<Self>\n    where\n        Self: Sized,\n    {\n        if let Token::Struct(tokens) = token {\n            if let [Token::B256(data)] = tokens.as_slice() {\n                Ok(ContractId::from(*data))\n            } else {\n                Err(error!(\n                    Other,\n                    \"`ContractId` expected one `Token::B256`, got `{tokens:?}`\"\n                ))\n            }\n        } else {\n            Err(error!(\n                Other,\n                \"`ContractId` expected `Token::Struct` got `{token:?}`\"\n            ))\n        }\n    }\n\n    fn into_token(self) -> Token {\n        let underlying_data: &[u8; 32] = &self;\n        Token::Struct(vec![Bits256(*underlying_data).into_token()])\n    }\n}\n\nimpl Tokenizable for Address {\n    fn from_token(token: Token) -> Result<Self>\n    where\n        Self: Sized,\n    {\n        if let Token::Struct(tokens) = token {\n            if let [Token::B256(data)] = tokens.as_slice() {\n                Ok(Address::from(*data))\n            } else {\n                Err(error!(\n                    Other,\n                    \"`Address` expected one `Token::B256`, got `{tokens:?}`\"\n                ))\n            }\n        } else {\n            Err(error!(\n                Other,\n                \"`Address` expected `Token::Struct` got `{token:?}`\"\n            ))\n        }\n    }\n\n    fn into_token(self) -> Token {\n        let underlying_data: &[u8; 32] = &self;\n\n        Token::Struct(vec![Bits256(*underlying_data).into_token()])\n    }\n}\n\nimpl Tokenizable for AssetId {\n    fn from_token(token: Token) -> Result<Self>\n    where\n        Self: Sized,\n    {\n        if let Token::Struct(tokens) = token {\n            if let [Token::B256(data)] = tokens.as_slice() {\n                Ok(AssetId::from(*data))\n            } else {\n                Err(error!(\n                    Other,\n                    \"`AssetId` expected one `Token::B256`, got `{tokens:?}`\"\n                ))\n            }\n        } else {\n            Err(error!(\n                Other,\n                \"`AssetId` expected `Token::Struct` got `{token:?}`\"\n            ))\n        }\n    }\n\n    fn into_token(self) -> Token {\n        let underlying_data: &[u8; 32] = &self;\n        Token::Struct(vec![Bits256(*underlying_data).into_token()])\n    }\n}\n\nimpl<T> Tokenizable for Option<T>\nwhere\n    T: Tokenizable + Parameterize,\n{\n    fn from_token(token: Token) -> Result<Self> {\n        if let Token::Enum(enum_selector) = token {\n            match *enum_selector {\n                (0, _, _) => Ok(None),\n                (1, token, _) => Ok(Option::<T>::Some(T::from_token(token)?)),\n                (_, _, _) => Err(error!(\n                    Other,\n                    \"could not construct `Option` from `enum_selector`. Received: `{:?}`\",\n                    enum_selector\n                )),\n            }\n        } else {\n            Err(error!(\n                Other,\n                \"could not construct `Option` from token. Received: `{token:?}`\"\n            ))\n        }\n    }\n    fn into_token(self) -> Token {\n        let (dis, tok) = match self {\n            None => (0, Token::Unit),\n            Some(value) => (1, value.into_token()),\n        };\n        if let ParamType::Enum { enum_variants, .. } = Self::param_type() {\n            let selector = (dis, tok, enum_variants);\n            Token::Enum(Box::new(selector))\n        } else {\n            panic!(\"should never happen as `Option::param_type()` returns valid Enum variants\");\n        }\n    }\n}\n\nimpl<T, E> Tokenizable for std::result::Result<T, E>\nwhere\n    T: Tokenizable + Parameterize,\n    E: Tokenizable + Parameterize,\n{\n    fn from_token(token: Token) -> Result<Self> {\n        if let Token::Enum(enum_selector) = token {\n            match *enum_selector {\n                (0, token, _) => Ok(std::result::Result::<T, E>::Ok(T::from_token(token)?)),\n                (1, token, _) => Ok(std::result::Result::<T, E>::Err(E::from_token(token)?)),\n                (_, _, _) => Err(error!(\n                    Other,\n                    \"could not construct `Result` from `enum_selector`. Received: `{:?}`\",\n                    enum_selector\n                )),\n            }\n        } else {\n            Err(error!(\n                Other,\n                \"could not construct `Result` from token. Received: `{token:?}`\"\n            ))\n        }\n    }\n    fn into_token(self) -> Token {\n        let (dis, tok) = match self {\n            Ok(value) => (0, value.into_token()),\n            Err(value) => (1, value.into_token()),\n        };\n        if let ParamType::Enum { enum_variants, .. } = Self::param_type() {\n            let selector = (dis, tok, enum_variants);\n            Token::Enum(Box::new(selector))\n        } else {\n            panic!(\"should never happen as Result::param_type() returns valid Enum variants\");\n        }\n    }\n}\n\nimpl<const SIZE: usize, T: Tokenizable> Tokenizable for [T; SIZE] {\n    fn from_token(token: Token) -> Result<Self>\n    where\n        Self: Sized,\n    {\n        let gen_error = |reason| error!(Other, \"constructing an array of size {SIZE}: {reason}\");\n\n        match token {\n            Token::Array(elements) => {\n                let len = elements.len();\n                if len != SIZE {\n                    return Err(gen_error(format!(\n                        \"`Token::Array` has wrong number of elements: {len}\"\n                    )));\n                }\n\n                let detokenized = elements\n                    .into_iter()\n                    .map(Tokenizable::from_token)\n                    .collect::<Result<Vec<T>>>()\n                    .map_err(|err| {\n                        gen_error(format!(\", not all elements could be detokenized: {err}\"))\n                    })?;\n\n                Ok(detokenized.try_into().unwrap_or_else(|_| {\n                    panic!(\"this should never fail since we're checking the length beforehand\")\n                }))\n            }\n            _ => Err(gen_error(format!(\"expected a `Token::Array`, got {token}\"))),\n        }\n    }\n\n    fn into_token(self) -> Token {\n        Token::Array(self.map(Tokenizable::into_token).to_vec())\n    }\n}\n\nimpl<const LEN: usize> Tokenizable for SizedAsciiString<LEN> {\n    fn from_token(token: Token) -> Result<Self>\n    where\n        Self: Sized,\n    {\n        match token {\n            Token::StringArray(contents) => {\n                let expected_len = contents.get_encodable_str()?.len();\n                if expected_len != LEN {\n                    return Err(error!(\n                        Other,\n                        \"`SizedAsciiString<{LEN}>::from_token` got a `Token::StringArray` whose expected length({}) is != {LEN}\",\n                        expected_len\n                    ));\n                }\n                Self::new(contents.try_into()?)\n            }\n            _ => Err(error!(\n                Other,\n                \"`SizedAsciiString<{LEN}>::from_token` expected a token of the variant `Token::StringArray`, got: `{token}`\"\n            )),\n        }\n    }\n\n    fn into_token(self) -> Token {\n        Token::StringArray(StaticStringToken::new(self.into(), Some(LEN)))\n    }\n}\n\nimpl Tokenizable for AsciiString {\n    fn from_token(token: Token) -> Result<Self>\n    where\n        Self: Sized,\n    {\n        match token {\n            Token::StringSlice(contents) => Self::new(contents.try_into()?),\n            _ => Err(error!(\n                Other,\n                \"`AsciiString::from_token` expected a token of the variant `Token::StringSlice`, got: `{token}`\"\n            )),\n        }\n    }\n\n    fn into_token(self) -> Token {\n        Token::StringSlice(StaticStringToken::new(self.into(), None))\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn test_from_token_b256() -> Result<()> {\n        let data = [1u8; 32];\n        let token = Token::B256(data);\n\n        let bits256 = Bits256::from_token(token)?;\n\n        assert_eq!(bits256.0, data);\n\n        Ok(())\n    }\n\n    #[test]\n    fn test_into_token_b256() {\n        let bytes = [1u8; 32];\n        let bits256 = Bits256(bytes);\n\n        let token = bits256.into_token();\n\n        assert_eq!(token, Token::B256(bytes));\n    }\n\n    #[test]\n    fn test_from_token_raw_slice() -> Result<()> {\n        let data = vec![42; 11];\n        let token = Token::RawSlice(data.clone());\n\n        let slice = RawSlice::from_token(token)?;\n\n        assert_eq!(slice, data);\n\n        Ok(())\n    }\n\n    #[test]\n    fn test_into_token_raw_slice() {\n        let data = vec![13; 32];\n        let raw_slice_token = Token::RawSlice(data.clone());\n\n        let token = raw_slice_token.into_token();\n\n        assert_eq!(token, Token::RawSlice(data));\n    }\n\n    #[test]\n    fn sized_ascii_string_is_tokenized_correctly() -> Result<()> {\n        let sut = SizedAsciiString::<3>::new(\"abc\".to_string())?;\n\n        let token = sut.into_token();\n\n        match token {\n            Token::StringArray(string_token) => {\n                let contents = string_token.get_encodable_str()?;\n                assert_eq!(contents, \"abc\");\n            }\n            _ => {\n                panic!(\"not tokenized correctly! Should have gotten a `Token::String`\")\n            }\n        }\n\n        Ok(())\n    }\n\n    #[test]\n    fn sized_ascii_string_is_detokenized_correctly() -> Result<()> {\n        let token = Token::StringArray(StaticStringToken::new(\"abc\".to_string(), Some(3)));\n\n        let sized_ascii_string =\n            SizedAsciiString::<3>::from_token(token).expect(\"should have succeeded\");\n\n        assert_eq!(sized_ascii_string, \"abc\");\n\n        Ok(())\n    }\n\n    #[test]\n    fn test_into_token_std_string() -> Result<()> {\n        let expected = String::from(\"hello\");\n        let token = Token::String(expected.clone());\n        let detokenized = String::from_token(token.into_token())?;\n\n        assert_eq!(detokenized, expected);\n\n        Ok(())\n    }\n}\n"
  },
  {
    "path": "packages/fuels-core/src/traits.rs",
    "content": "mod parameterize;\nmod signer;\nmod tokenizable;\n\npub use parameterize::*;\npub use signer::*;\npub use tokenizable::*;\n"
  },
  {
    "path": "packages/fuels-core/src/types/checksum_address.rs",
    "content": "use sha2::{Digest, Sha256};\n\nuse crate::types::errors::{Error, Result};\n\npub fn checksum_encode(address: &str) -> Result<String> {\n    let trimmed = address.trim_start_matches(\"0x\");\n    pre_validate(trimmed)?;\n\n    let lowercase = trimmed.to_ascii_lowercase();\n\n    let hash = Sha256::digest(lowercase.as_bytes());\n    let mut checksum = String::with_capacity(trimmed.len());\n\n    for (i, addr_char) in lowercase.chars().enumerate() {\n        let hash_byte = hash[i / 2];\n        let hash_nibble = if i % 2 == 0 {\n            // even index: high nibble\n            (hash_byte >> 4) & 0x0F\n        } else {\n            // odd index: low nibble\n            hash_byte & 0x0F\n        };\n\n        // checksum rule\n        if hash_nibble > 7 {\n            checksum.push(addr_char.to_ascii_uppercase());\n        } else {\n            checksum.push(addr_char);\n        }\n    }\n\n    Ok(format!(\"0x{checksum}\"))\n}\n\nfn pre_validate(s: &str) -> Result<()> {\n    if s.len() != 64 {\n        return Err(Error::Codec(\"invalid address length\".to_string()));\n    }\n\n    if !s.chars().all(|c| c.is_ascii_hexdigit()) {\n        return Err(Error::Codec(\n            \"address contains invalid characters\".to_string(),\n        ));\n    }\n\n    Ok(())\n}\n\npub fn is_checksum_valid(address: &str) -> bool {\n    let Ok(checksum) = checksum_encode(address) else {\n        return false;\n    };\n\n    let address_normalized = if address.starts_with(\"0x\") {\n        address.to_string()\n    } else {\n        format!(\"0x{}\", address)\n    };\n\n    checksum == address_normalized\n}\n\n#[cfg(test)]\nmod test {\n    use std::str::FromStr;\n\n    use fuel_core_client::client::schema::Address;\n\n    use super::*;\n\n    const VALID_CHECKSUM: [&str; 4] = [\n        \"0x9cfB2CAd509D417ec40b70ebE1DD72a3624D46fdD1Ea5420dBD755CE7f4Dc897\",\n        \"0x54944e5B8189827e470e5a8bAcFC6C3667397DC4E1EEF7EF3519d16D6D6c6610\",\n        \"c36bE0E14d3EAf5d8D233e0F4a40b3b4e48427D25F84C460d2B03B242A38479e\",\n        \"a1184D77D0D08A064E03b2bd9f50863e88faDdea4693A05cA1ee9B1732ea99B7\",\n    ];\n    const INVALID_CHECKSUM: [&str; 8] = [\n        \"0x587aa0482482efEa0234752d1ad9a9c438D1f34D2859b8bef2d56A432cB68e33\",\n        \"0xe10f526B192593793b7a1559aA91445faba82a1d669e3eb2DCd17f9c121b24b1\",\n        \"6b63804cFbF9856e68e5B6e7aEf238dc8311ec55bec04df774003A2c96E0418e\",\n        \"81f3A10b61828580D06cC4c7b0ed8f59b9Fb618bE856c55d33deCD95489A1e23\",\n        // all lower\n        \"0xf8f8b6283d7fa5b672b530cbb84fcccb4ff8dc40f8176ef4544ddb1f1952ad07\",\n        \"7e2becd64cd598da59b4d1064b711661898656c6b1f4918a787156b8965dc83c\",\n        // all caps\n        \"0x26183FBE7375045250865947695DFC12500DCC43EFB9102B4E8C4D3C20009DCB\",\n        \"577E424EE53A16E6A85291FEABC8443862495F74AC39A706D2DD0B9FC16955EB\",\n    ];\n    const INVALID_LEN: [&str; 6] = [\n        // too short\n        \"0x1234567890abcdef\",\n        // too long\n        \"0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234\",\n        // 65 characters\n        \"1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1\",\n        // 63 characters\n        \"0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcde\",\n        \"\",\n        \"0x\",\n    ];\n    const INVALID_CHARACTERS: &str =\n        \"0xGHIJKL7890abcdef1234567890abcdef1234567890abcdef1234567890abcdef\";\n\n    #[test]\n    fn will_detect_valid_checksums() {\n        for valid in VALID_CHECKSUM.iter() {\n            assert!(is_checksum_valid(valid));\n        }\n    }\n\n    #[test]\n    fn will_detect_invalid_checksums() {\n        for invalid in INVALID_CHECKSUM.iter() {\n            assert!(!is_checksum_valid(invalid));\n        }\n    }\n\n    #[test]\n    fn can_construct_address_from_checksum() {\n        let checksum = checksum_encode(INVALID_CHECKSUM[0]).expect(\"should encode\");\n        Address::from_str(&checksum).expect(\"should be valid address\");\n    }\n\n    #[test]\n    fn will_detect_invalid_lengths() {\n        for invalid in INVALID_LEN.iter() {\n            let result = checksum_encode(invalid).expect_err(\"should not encode\");\n            assert!(result.to_string().contains(\"invalid address length\"));\n        }\n    }\n\n    #[test]\n    fn will_detect_invalid_characters() {\n        let result = checksum_encode(INVALID_CHARACTERS).expect_err(\"should not encode\");\n        assert!(\n            result\n                .to_string()\n                .contains(\"address contains invalid characters\")\n        );\n    }\n}\n"
  },
  {
    "path": "packages/fuels-core/src/types/core/bits.rs",
    "content": "use fuel_tx::SubAssetId;\nuse fuel_types::AssetId;\nuse fuels_macros::{Parameterize, Tokenizable, TryFrom};\n\nuse crate::types::errors::Result;\n\n// A simple wrapper around [u8; 32] representing the `b256` type. Exists\n// mainly so that we may differentiate `Parameterize` and `Tokenizable`\n// implementations from what otherwise is just an array of 32 u8's.\n#[derive(Debug, PartialEq, Eq, Copy, Clone)]\npub struct Bits256(pub [u8; 32]);\n\nimpl Bits256 {\n    /// Returns `Self` with zeroes inside.\n    pub fn zeroed() -> Self {\n        Self([0; 32])\n    }\n\n    /// Create a new `Bits256` from a string representation of a hex.\n    /// Accepts both `0x` prefixed and non-prefixed hex strings.\n    pub fn from_hex_str(hex: &str) -> Result<Self> {\n        let hex = if let Some(stripped_hex) = hex.strip_prefix(\"0x\") {\n            stripped_hex\n        } else {\n            hex\n        };\n\n        let mut bytes = [0u8; 32];\n        hex::decode_to_slice(hex, &mut bytes as &mut [u8])?;\n\n        Ok(Bits256(bytes))\n    }\n}\n\nimpl From<AssetId> for Bits256 {\n    fn from(value: AssetId) -> Self {\n        Self(value.into())\n    }\n}\n\nimpl From<SubAssetId> for Bits256 {\n    fn from(value: SubAssetId) -> Self {\n        Self(value.into())\n    }\n}\n\n// A simple wrapper around [Bits256; 2] representing the `B512` type.\n#[derive(Debug, PartialEq, Eq, Copy, Clone, Parameterize, Tokenizable, TryFrom)]\n#[FuelsCorePath = \"crate\"]\n#[FuelsTypesPath = \"crate::types\"]\n// ANCHOR: b512\npub struct B512 {\n    pub bytes: [Bits256; 2],\n}\n// ANCHOR_END: b512\n\nimpl From<(Bits256, Bits256)> for B512 {\n    fn from(bits_tuple: (Bits256, Bits256)) -> Self {\n        B512 {\n            bytes: [bits_tuple.0, bits_tuple.1],\n        }\n    }\n}\n\n#[derive(Debug, PartialEq, Eq, Copy, Clone, Parameterize, Tokenizable, TryFrom)]\n#[FuelsCorePath = \"crate\"]\n#[FuelsTypesPath = \"crate::types\"]\n// ANCHOR: evm_address\npub struct EvmAddress {\n    // An evm address is only 20 bytes, the first 12 bytes should be set to 0\n    value: Bits256,\n}\n// ANCHOR_END: evm_address\nimpl EvmAddress {\n    fn new(b256: Bits256) -> Self {\n        Self {\n            value: Bits256(Self::clear_12_bytes(b256.0)),\n        }\n    }\n\n    pub fn value(&self) -> Bits256 {\n        self.value\n    }\n\n    // sets the leftmost 12 bytes to zero\n    fn clear_12_bytes(bytes: [u8; 32]) -> [u8; 32] {\n        let mut bytes = bytes;\n        bytes[..12].copy_from_slice(&[0u8; 12]);\n\n        bytes\n    }\n}\n\nimpl From<Bits256> for EvmAddress {\n    fn from(b256: Bits256) -> Self {\n        EvmAddress::new(b256)\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use crate::{\n        traits::{Parameterize, Tokenizable},\n        types::{Token, param_types::ParamType},\n    };\n\n    #[test]\n    fn from_hex_str_b256() -> Result<()> {\n        // ANCHOR: from_hex_str\n        let hex_str = \"0101010101010101010101010101010101010101010101010101010101010101\";\n\n        let bits256 = Bits256::from_hex_str(hex_str)?;\n\n        assert_eq!(bits256.0, [1u8; 32]);\n\n        // With the `0x0` prefix\n        // ANCHOR: hex_str_to_bits256\n        let hex_str = \"0x0101010101010101010101010101010101010101010101010101010101010101\";\n\n        let bits256 = Bits256::from_hex_str(hex_str)?;\n        // ANCHOR_END: hex_str_to_bits256\n\n        assert_eq!(bits256.0, [1u8; 32]);\n        // ANCHOR_END: from_hex_str\n\n        Ok(())\n    }\n\n    #[test]\n    fn test_param_type_evm_addr() {\n        assert_eq!(\n            EvmAddress::param_type(),\n            ParamType::Struct {\n                name: \"EvmAddress\".to_string(),\n                fields: vec![(\"value\".to_string(), ParamType::B256)],\n                generics: vec![]\n            }\n        );\n    }\n\n    #[test]\n    fn evm_address_clears_first_12_bytes() -> Result<()> {\n        let data = [1u8; 32];\n        let address = EvmAddress::new(Bits256(data));\n\n        let expected_data = Bits256([\n            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n            1, 1, 1,\n        ]);\n\n        assert_eq!(address.value(), expected_data);\n\n        Ok(())\n    }\n\n    #[test]\n    fn test_into_token_evm_addr() {\n        let bits = [1u8; 32];\n        let evm_address = EvmAddress::from(Bits256(bits));\n\n        let token = evm_address.into_token();\n\n        let expected_data = [\n            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n            1, 1, 1,\n        ];\n\n        assert_eq!(token, Token::Struct(vec![Token::B256(expected_data)]));\n    }\n}\n"
  },
  {
    "path": "packages/fuels-core/src/types/core/bytes.rs",
    "content": "use crate::types::errors::Result;\n\n#[derive(Debug, PartialEq, Clone, Eq)]\npub struct Bytes(pub Vec<u8>);\n\nimpl Bytes {\n    /// Create a new `Bytes` from a string representation of a hex.\n    /// Accepts both `0x` prefixed and non-prefixed hex strings.\n    pub fn from_hex_str(hex: &str) -> Result<Self> {\n        let hex = if let Some(stripped_hex) = hex.strip_prefix(\"0x\") {\n            stripped_hex\n        } else {\n            hex\n        };\n        let bytes = hex::decode(hex)?;\n\n        Ok(Bytes(bytes))\n    }\n}\n\nimpl From<Bytes> for Vec<u8> {\n    fn from(bytes: Bytes) -> Vec<u8> {\n        bytes.0\n    }\n}\n\nimpl PartialEq<Vec<u8>> for Bytes {\n    fn eq(&self, other: &Vec<u8>) -> bool {\n        self.0 == *other\n    }\n}\n\nimpl PartialEq<Bytes> for Vec<u8> {\n    fn eq(&self, other: &Bytes) -> bool {\n        *self == other.0\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn from_hex_str_b256() -> Result<()> {\n        // ANCHOR: bytes_from_hex_str\n        let hex_str = \"0101010101010101010101010101010101010101010101010101010101010101\";\n\n        let bytes = Bytes::from_hex_str(hex_str)?;\n\n        assert_eq!(bytes.0, vec![1u8; 32]);\n\n        // With the `0x0` prefix\n        // ANCHOR: hex_string_to_bytes32\n        let hex_str = \"0x0101010101010101010101010101010101010101010101010101010101010101\";\n\n        let bytes = Bytes::from_hex_str(hex_str)?;\n        // ANCHOR_END: hex_string_to_bytes32\n\n        assert_eq!(bytes.0, vec![1u8; 32]);\n        // ANCHOR_END: bytes_from_hex_str\n\n        Ok(())\n    }\n}\n"
  },
  {
    "path": "packages/fuels-core/src/types/core/identity.rs",
    "content": "use fuel_types::{Address, ContractId};\nuse fuels_macros::{Parameterize, Tokenizable, TryFrom};\nuse serde::{Deserialize, Serialize};\n\n#[derive(\n    Debug,\n    Copy,\n    Clone,\n    PartialEq,\n    Eq,\n    Hash,\n    Parameterize,\n    Tokenizable,\n    TryFrom,\n    Serialize,\n    Deserialize,\n)]\n#[FuelsCorePath = \"crate\"]\n#[FuelsTypesPath = \"crate::types\"]\npub enum Identity {\n    Address(Address),\n    ContractId(ContractId),\n}\n\nimpl Default for Identity {\n    fn default() -> Self {\n        Self::Address(Address::default())\n    }\n}\n\nimpl AsRef<[u8]> for Identity {\n    fn as_ref(&self) -> &[u8] {\n        match self {\n            Identity::Address(address) => address.as_ref(),\n            Identity::ContractId(contract_id) => contract_id.as_ref(),\n        }\n    }\n}\n\nimpl From<&Address> for Identity {\n    fn from(address: &Address) -> Self {\n        Self::Address(*address)\n    }\n}\nimpl From<Address> for Identity {\n    fn from(address: Address) -> Self {\n        Self::Address(address)\n    }\n}\n\nimpl From<&ContractId> for Identity {\n    fn from(contract_id: &ContractId) -> Self {\n        Self::ContractId(*contract_id)\n    }\n}\nimpl From<ContractId> for Identity {\n    fn from(contract_id: ContractId) -> Self {\n        Self::ContractId(contract_id)\n    }\n}\n"
  },
  {
    "path": "packages/fuels-core/src/types/core/raw_slice.rs",
    "content": "#[derive(Debug, PartialEq, Clone, Eq)]\npub struct RawSlice(pub Vec<u8>);\n\nimpl From<RawSlice> for Vec<u8> {\n    fn from(raw_slice: RawSlice) -> Vec<u8> {\n        raw_slice.0\n    }\n}\n\nimpl PartialEq<Vec<u8>> for RawSlice {\n    fn eq(&self, other: &Vec<u8>) -> bool {\n        self.0 == *other\n    }\n}\n\nimpl PartialEq<RawSlice> for Vec<u8> {\n    fn eq(&self, other: &RawSlice) -> bool {\n        *self == other.0\n    }\n}\n"
  },
  {
    "path": "packages/fuels-core/src/types/core/sized_ascii_string.rs",
    "content": "use std::fmt::{Debug, Display, Formatter};\n\nuse serde::{Deserialize, Serialize};\n\nuse crate::types::errors::{Error, Result, error};\n\n// To be used when interacting with contracts which have string slices in their ABI.\n// The FuelVM strings only support ascii characters.\n#[derive(Debug, PartialEq, Clone, Eq)]\npub struct AsciiString {\n    data: String,\n}\n\nimpl AsciiString {\n    pub fn new(data: String) -> Result<Self> {\n        if !data.is_ascii() {\n            return Err(error!(\n                Other,\n                \"`AsciiString` must be constructed from a string containing only ascii encodable characters. Got: `{data}`\"\n            ));\n        }\n        Ok(Self { data })\n    }\n\n    pub fn to_trimmed_str(&self) -> &str {\n        self.data.trim()\n    }\n    pub fn to_left_trimmed_str(&self) -> &str {\n        self.data.trim_start()\n    }\n    pub fn to_right_trimmed_str(&self) -> &str {\n        self.data.trim_end()\n    }\n}\n\nimpl TryFrom<&str> for AsciiString {\n    type Error = Error;\n\n    fn try_from(value: &str) -> Result<Self> {\n        Self::new(value.to_owned())\n    }\n}\n\nimpl TryFrom<String> for AsciiString {\n    type Error = Error;\n\n    fn try_from(value: String) -> Result<Self> {\n        Self::new(value)\n    }\n}\n\nimpl From<AsciiString> for String {\n    fn from(ascii_str: AsciiString) -> Self {\n        ascii_str.data\n    }\n}\n\nimpl<const LEN: usize> AsRef<str> for SizedAsciiString<LEN> {\n    fn as_ref(&self) -> &str {\n        &self.data\n    }\n}\n\nimpl Display for AsciiString {\n    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {\n        write!(f, \"{}\", self.data)\n    }\n}\n\nimpl PartialEq<&str> for AsciiString {\n    fn eq(&self, other: &&str) -> bool {\n        self.data == *other\n    }\n}\nimpl PartialEq<AsciiString> for &str {\n    fn eq(&self, other: &AsciiString) -> bool {\n        *self == other.data\n    }\n}\n\n// To be used when interacting with contracts which have strings in their ABI.\n// The length of a string is part of its type -- i.e. str[2] is a\n// different type from str[3]. The FuelVM strings only support ascii characters.\n#[derive(Debug, PartialEq, Clone, Eq, Hash, Default)]\npub struct SizedAsciiString<const LEN: usize> {\n    data: String,\n}\n\nimpl<const LEN: usize> SizedAsciiString<LEN> {\n    pub fn new(data: String) -> Result<Self> {\n        if !data.is_ascii() {\n            return Err(error!(\n                Other,\n                \"`SizedAsciiString` must be constructed from a `String` containing only ascii encodable characters. Got: `{data}`\"\n            ));\n        }\n        if data.len() != LEN {\n            return Err(error!(\n                Other,\n                \"`SizedAsciiString<{LEN}>` must be constructed from a `String` of length {LEN}. Got: `{data}`\"\n            ));\n        }\n        Ok(Self { data })\n    }\n\n    pub fn to_trimmed_str(&self) -> &str {\n        self.data.trim()\n    }\n    pub fn to_left_trimmed_str(&self) -> &str {\n        self.data.trim_start()\n    }\n    pub fn to_right_trimmed_str(&self) -> &str {\n        self.data.trim_end()\n    }\n\n    /// Pad `data` string with whitespace characters on the right to fit into the `SizedAsciiString`\n    pub fn new_with_right_whitespace_padding(data: String) -> Result<Self> {\n        if data.len() > LEN {\n            return Err(error!(\n                Other,\n                \"`SizedAsciiString<{LEN}>` cannot be constructed from a string of size {}\",\n                data.len()\n            ));\n        }\n\n        Ok(Self {\n            data: format!(\"{:LEN$}\", data),\n        })\n    }\n}\n\nimpl<const LEN: usize> TryFrom<&str> for SizedAsciiString<LEN> {\n    type Error = Error;\n\n    fn try_from(value: &str) -> Result<Self> {\n        Self::new(value.to_owned())\n    }\n}\n\nimpl<const LEN: usize> TryFrom<String> for SizedAsciiString<LEN> {\n    type Error = Error;\n\n    fn try_from(value: String) -> Result<Self> {\n        Self::new(value)\n    }\n}\n\nimpl<const LEN: usize> From<SizedAsciiString<LEN>> for String {\n    fn from(sized_ascii_str: SizedAsciiString<LEN>) -> Self {\n        sized_ascii_str.data\n    }\n}\n\nimpl<const LEN: usize> Display for SizedAsciiString<LEN> {\n    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {\n        write!(f, \"{}\", self.data)\n    }\n}\n\nimpl<const LEN: usize> PartialEq<&str> for SizedAsciiString<LEN> {\n    fn eq(&self, other: &&str) -> bool {\n        self.data == *other\n    }\n}\n\nimpl<const LEN: usize> PartialEq<SizedAsciiString<LEN>> for &str {\n    fn eq(&self, other: &SizedAsciiString<LEN>) -> bool {\n        *self == other.data\n    }\n}\n\nimpl<const LEN: usize> Serialize for SizedAsciiString<LEN> {\n    fn serialize<S: serde::Serializer>(\n        &self,\n        serializer: S,\n    ) -> core::result::Result<S::Ok, S::Error> {\n        self.data.serialize(serializer)\n    }\n}\n\nimpl<'de, const LEN: usize> Deserialize<'de> for SizedAsciiString<LEN> {\n    fn deserialize<D: serde::Deserializer<'de>>(\n        deserializer: D,\n    ) -> core::result::Result<Self, D::Error> {\n        let data = String::deserialize(deserializer)?;\n        Self::new(data).map_err(serde::de::Error::custom)\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn accepts_ascii_of_correct_length() {\n        // ANCHOR: string_simple_example\n        let ascii_data = \"abc\".to_string();\n\n        SizedAsciiString::<3>::new(ascii_data)\n            .expect(\"should have succeeded since we gave ascii data of correct length!\");\n        // ANCHOR_END: string_simple_example\n    }\n\n    #[test]\n    fn refuses_non_ascii() {\n        let ascii_data = \"ab©\".to_string();\n\n        let err = SizedAsciiString::<3>::new(ascii_data)\n            .expect_err(\"should not have succeeded since we gave non ascii data\");\n\n        let expected_reason = \"`SizedAsciiString` must be constructed from a `String` containing only ascii encodable characters. Got: \";\n        assert!(matches!(err, Error::Other(reason) if reason.starts_with(expected_reason)));\n    }\n\n    #[test]\n    fn refuses_invalid_len() {\n        let ascii_data = \"abcd\".to_string();\n\n        let err = SizedAsciiString::<3>::new(ascii_data)\n            .expect_err(\"should not have succeeded since we gave data of wrong length\");\n\n        let expected_reason =\n            \"`SizedAsciiString<3>` must be constructed from a `String` of length 3. Got: `abcd`\";\n        assert!(matches!(err, Error::Other(reason) if reason.starts_with(expected_reason)));\n    }\n\n    // ANCHOR: conversion\n    #[test]\n    fn can_be_constructed_from_str_ref() {\n        let _: SizedAsciiString<3> = \"abc\".try_into().expect(\"should have succeeded\");\n    }\n\n    #[test]\n    fn can_be_constructed_from_string() {\n        let _: SizedAsciiString<3> = \"abc\".to_string().try_into().expect(\"should have succeeded\");\n    }\n\n    #[test]\n    fn can_be_converted_into_string() {\n        let sized_str = SizedAsciiString::<3>::new(\"abc\".to_string()).unwrap();\n\n        let str: String = sized_str.into();\n\n        assert_eq!(str, \"abc\");\n    }\n    // ANCHOR_END: conversion\n\n    #[test]\n    fn can_be_printed() {\n        let sized_str = SizedAsciiString::<3>::new(\"abc\".to_string()).unwrap();\n\n        assert_eq!(sized_str.to_string(), \"abc\");\n    }\n\n    #[test]\n    fn can_be_compared_w_str_ref() {\n        let sized_str = SizedAsciiString::<3>::new(\"abc\".to_string()).unwrap();\n\n        assert_eq!(sized_str, \"abc\");\n        // and vice-versa\n        assert_eq!(\"abc\", sized_str);\n    }\n\n    #[test]\n    fn trim() -> Result<()> {\n        // Using single whitespaces\n        let untrimmed = SizedAsciiString::<9>::new(\" est abc \".to_string())?;\n        assert_eq!(\"est abc \", untrimmed.to_left_trimmed_str());\n        assert_eq!(\" est abc\", untrimmed.to_right_trimmed_str());\n        assert_eq!(\"est abc\", untrimmed.to_trimmed_str());\n\n        let padded = // adds 6 whitespaces\n            SizedAsciiString::<12>::new_with_right_whitespace_padding(\"victor\".to_string())?;\n        assert_eq!(\"victor      \", padded);\n\n        Ok(())\n    }\n\n    #[test]\n    fn test_can_serialize_sized_ascii() {\n        let sized_str = SizedAsciiString::<3>::new(\"abc\".to_string()).unwrap();\n\n        let serialized = serde_json::to_string(&sized_str).unwrap();\n        assert_eq!(serialized, \"\\\"abc\\\"\");\n    }\n\n    #[test]\n    fn test_can_deserialize_sized_ascii() {\n        let serialized = \"\\\"abc\\\"\";\n\n        let deserialized: SizedAsciiString<3> = serde_json::from_str(serialized).unwrap();\n        assert_eq!(\n            deserialized,\n            SizedAsciiString::<3>::new(\"abc\".to_string()).unwrap()\n        );\n    }\n\n    #[test]\n    fn test_can_convert_sized_ascii_to_bytes() {\n        let sized_str = SizedAsciiString::<3>::new(\"abc\".to_string()).unwrap();\n\n        let bytes: &[u8] = sized_str.as_ref().as_bytes();\n        assert_eq!(bytes, &[97, 98, 99]);\n    }\n}\n"
  },
  {
    "path": "packages/fuels-core/src/types/core/u256.rs",
    "content": "#![allow(clippy::assign_op_pattern)]\n#![allow(clippy::manual_div_ceil)]\n\nuse serde::{Deserialize, Deserializer, Serialize, Serializer, de};\nuse uint::construct_uint;\n\nuse crate::{\n    traits::{Parameterize, Tokenizable},\n    types::{\n        Token,\n        errors::{Result as FuelsResult, error},\n        param_types::ParamType,\n    },\n};\n\nconstruct_uint! {\n    pub struct U256(4);\n}\n\nimpl Parameterize for U256 {\n    fn param_type() -> ParamType {\n        ParamType::U256\n    }\n}\n\nimpl Tokenizable for U256 {\n    fn from_token(token: Token) -> FuelsResult<Self>\n    where\n        Self: Sized,\n    {\n        match token {\n            Token::U256(data) => Ok(data),\n            _ => Err(error!(\n                Other,\n                \"`U256` cannot be constructed from token `{token}`\"\n            )),\n        }\n    }\n\n    fn into_token(self) -> Token {\n        Token::U256(self)\n    }\n}\n\nimpl Serialize for U256 {\n    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>\n    where\n        S: Serializer,\n    {\n        serializer.serialize_str(&self.to_string())\n    }\n}\n\nimpl<'de> Deserialize<'de> for U256 {\n    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>\n    where\n        D: Deserializer<'de>,\n    {\n        U256::from_dec_str(Deserialize::deserialize(deserializer)?).map_err(de::Error::custom)\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use crate::types::U256;\n\n    #[test]\n    fn u256_serialize_deserialize() {\n        let num = U256::from(123);\n        let serialized: String = serde_json::to_string(&num).unwrap();\n        assert_eq!(serialized, \"\\\"123\\\"\");\n\n        let deserialized_num: U256 = serde_json::from_str(&serialized).unwrap();\n        assert_eq!(deserialized_num, num);\n    }\n}\n"
  },
  {
    "path": "packages/fuels-core/src/types/core.rs",
    "content": "pub use bits::*;\npub use bytes::*;\npub use identity::*;\npub use raw_slice::*;\npub use sized_ascii_string::*;\npub use u256::*;\n\nmod bits;\nmod bytes;\nmod identity;\nmod raw_slice;\nmod sized_ascii_string;\nmod u256;\n"
  },
  {
    "path": "packages/fuels-core/src/types/dry_runner.rs",
    "content": "use std::fmt::Debug;\n\nuse async_trait::async_trait;\nuse fuel_tx::{ConsensusParameters, Transaction as FuelTransaction};\n\nuse crate::types::errors::Result;\n\n#[derive(Debug, Clone, Copy)]\npub struct DryRun {\n    pub succeeded: bool,\n    pub script_gas: u64,\n    pub variable_outputs: usize,\n}\n\nimpl DryRun {\n    pub fn gas_with_tolerance(&self, tolerance: f32) -> u64 {\n        let gas_used = self.script_gas as f64;\n        let adjusted_gas = gas_used * (1.0 + f64::from(tolerance));\n        adjusted_gas.ceil() as u64\n    }\n}\n\n#[cfg_attr(target_arch = \"wasm32\", async_trait(?Send))]\n#[cfg_attr(not(target_arch = \"wasm32\"), async_trait)]\npub trait DryRunner: Send + Sync {\n    async fn dry_run(&self, tx: FuelTransaction) -> Result<DryRun>;\n    async fn estimate_gas_price(&self, block_horizon: u32) -> Result<u64>;\n    async fn consensus_parameters(&self) -> Result<ConsensusParameters>;\n    async fn estimate_predicates(\n        &self,\n        tx: &FuelTransaction,\n        latest_chain_executor_version: Option<u32>,\n    ) -> Result<FuelTransaction>;\n}\n\n#[cfg_attr(target_arch = \"wasm32\", async_trait(?Send))]\n#[cfg_attr(not(target_arch = \"wasm32\"), async_trait)]\nimpl<T: DryRunner> DryRunner for &T {\n    async fn dry_run(&self, tx: FuelTransaction) -> Result<DryRun> {\n        (*self).dry_run(tx).await\n    }\n\n    async fn estimate_gas_price(&self, block_horizon: u32) -> Result<u64> {\n        (*self).estimate_gas_price(block_horizon).await\n    }\n\n    async fn consensus_parameters(&self) -> Result<ConsensusParameters> {\n        (*self).consensus_parameters().await\n    }\n\n    async fn estimate_predicates(\n        &self,\n        tx: &FuelTransaction,\n        latest_chain_executor_version: Option<u32>,\n    ) -> Result<FuelTransaction> {\n        (*self)\n            .estimate_predicates(tx, latest_chain_executor_version)\n            .await\n    }\n}\n"
  },
  {
    "path": "packages/fuels-core/src/types/errors.rs",
    "content": "pub mod transaction {\n    #[cfg(feature = \"std\")]\n    use std::sync::Arc;\n\n    #[cfg(not(feature = \"std\"))]\n    use alloc::sync::Arc;\n\n    #[derive(thiserror::Error, Debug, Clone)]\n    pub enum Reason {\n        #[error(\"builder: {0}\")]\n        Builder(String),\n        #[error(\"validation: {0}\")]\n        Validation(String),\n        #[error(\"squeezedOut: {0}\")]\n        SqueezedOut(String),\n        #[error(\"reverted: {reason}, receipts: {receipts:?}\")]\n        Failure {\n            reason: String,\n            revert_id: Option<u64>,\n            receipts: Arc<Vec<fuel_tx::Receipt>>,\n        },\n        #[error(\": {0}\")]\n        Other(String),\n    }\n\n    impl Reason {\n        pub(crate) fn context(self, context: impl std::fmt::Display) -> Self {\n            match self {\n                Reason::Builder(msg) => Reason::Builder(format!(\"{context}: {msg}\")),\n                Reason::Validation(msg) => Reason::Validation(format!(\"{context}: {msg}\")),\n                Reason::SqueezedOut(msg) => Reason::SqueezedOut(format!(\"{context}: {msg}\")),\n                Reason::Failure {\n                    reason,\n                    revert_id,\n                    receipts,\n                } => Reason::Failure {\n                    reason: format!(\"{context}: {reason}\"),\n                    revert_id,\n                    receipts,\n                },\n                Reason::Other(msg) => Reason::Other(format!(\"{context}: {msg}\")),\n            }\n        }\n    }\n}\n\nuse std::fmt::Display;\n\nuse crate::sealed::Sealed;\n\n#[derive(thiserror::Error, Debug, Clone)]\npub enum Error {\n    #[error(\"io: {0}\")]\n    IO(String),\n    #[error(\"codec: {0}\")]\n    Codec(String),\n    #[error(\"transaction {0}\")]\n    Transaction(transaction::Reason),\n    #[error(\"provider: {0}\")]\n    Provider(String),\n    #[error(\"{0}\")]\n    Other(String),\n}\n\nimpl From<std::io::Error> for Error {\n    fn from(value: std::io::Error) -> Self {\n        Self::IO(value.to_string())\n    }\n}\n\nimpl Error {\n    pub(crate) fn context(self, context: impl Display) -> Self {\n        match self {\n            Error::IO(msg) => Error::IO(format!(\"{context}: {msg}\")),\n            Error::Codec(msg) => Error::Codec(format!(\"{context}: {msg}\")),\n            Error::Transaction(reason) => Error::Transaction(reason.context(context)),\n            Error::Provider(msg) => Error::Provider(format!(\"{context}: {msg}\")),\n            Error::Other(msg) => Error::Other(format!(\"{context}: {msg}\")),\n        }\n    }\n}\n\npub type Result<T> = std::result::Result<T, Error>;\n\n/// Provides `context` and `with_context` to `Result`.\n///\n/// # Examples\n/// ```\n/// use fuels_core::types:: errors::{Context, Error, Result};\n///\n/// let res_with_context: Result<()> =\n/// Err(Error::Other(\"some error\".to_owned())).context(\"some context\");\n///\n/// let res_with_context: Result<()> =\n/// Err(Error::Other(\"some error\".to_owned())).with_context(|| \"some context\");\n/// ```\npub trait Context<T>: Sealed {\n    fn context<C>(self, context: C) -> Result<T>\n    where\n        C: Display + Send + Sync + 'static;\n\n    fn with_context<C, F>(self, f: F) -> Result<T>\n    where\n        C: Display + Send + Sync + 'static,\n        F: FnOnce() -> C;\n}\n\nimpl<T> Sealed for Result<T> {}\n\nimpl<T> Context<T> for Result<T> {\n    /// Wrap the error value with additional context\n    fn context<C>(self, context: C) -> Result<T>\n    where\n        C: Display + Send + Sync + 'static,\n    {\n        self.map_err(|e| e.context(context))\n    }\n\n    /// Wrap the error value with additional context that is evaluated lazily\n    fn with_context<C, F>(self, context: F) -> Result<T>\n    where\n        C: Display + Send + Sync + 'static,\n        F: FnOnce() -> C,\n    {\n        self.context(context())\n    }\n}\n\n/// This macro can only be used for `Error` variants that have a `String` field.\n/// Those are: `IO`, `Codec`, `Provider`, `Other`.\n#[macro_export]\nmacro_rules! error {\n   ($err_variant:ident, $fmt_str: literal $(,$arg: expr)*) => {\n    $crate::types::errors::Error::$err_variant(format!($fmt_str,$($arg),*))\n   }\n}\npub use error;\n\n/// This macro can only be used for `Error::Transaction` variants that have a `String` field.\n/// Those are: `Builder`, `Validation`, `SqueezedOut`, `Other`.\n#[macro_export]\nmacro_rules! error_transaction {\n   ($err_variant:ident, $fmt_str: literal $(,$arg: expr)*) => {\n    $crate::types::errors::Error::Transaction(\n        $crate::types::errors::transaction::Reason::$err_variant(format!($fmt_str,$($arg),*)))\n   }\n}\npub use error_transaction;\n\nimpl From<fuel_vm::checked_transaction::CheckError> for Error {\n    fn from(err: fuel_vm::checked_transaction::CheckError) -> Error {\n        error_transaction!(Validation, \"{err:?}\")\n    }\n}\n\nimpl From<fuel_tx::ValidityError> for Error {\n    fn from(err: fuel_tx::ValidityError) -> Error {\n        error_transaction!(Validation, \"{err:?}\")\n    }\n}\n\nmacro_rules! impl_error_from {\n    ($err_variant:ident, $err_type:ty ) => {\n        impl From<$err_type> for $crate::types::errors::Error {\n            fn from(err: $err_type) -> $crate::types::errors::Error {\n                $crate::types::errors::Error::$err_variant(err.to_string())\n            }\n        }\n    };\n}\n\nimpl_error_from!(Other, &'static str);\nimpl_error_from!(Other, fuel_crypto::Error);\nimpl_error_from!(Other, serde_json::Error);\nimpl_error_from!(Other, hex::FromHexError);\nimpl_error_from!(Other, std::array::TryFromSliceError);\nimpl_error_from!(Other, std::str::Utf8Error);\nimpl_error_from!(Other, fuel_abi_types::error::Error);\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn result_context() {\n        {\n            let res_with_context: Result<()> =\n                Err(error!(Provider, \"some error\")).context(\"some context\");\n\n            assert_eq!(\n                res_with_context.unwrap_err().to_string(),\n                \"provider: some context: some error\",\n            );\n        }\n        {\n            let res_with_context: Result<()> =\n                Err(error_transaction!(Builder, \"some error\")).context(\"some context\");\n\n            assert_eq!(\n                res_with_context.unwrap_err().to_string(),\n                \"transaction builder: some context: some error\"\n            );\n        }\n    }\n\n    #[test]\n    fn result_with_context() {\n        {\n            let res_with_context: Result<()> =\n                Err(error!(Other, \"some error\")).with_context(|| \"some context\");\n\n            assert_eq!(\n                res_with_context.unwrap_err().to_string(),\n                \"some context: some error\",\n            );\n        }\n        {\n            let res_with_context: Result<()> =\n                Err(error_transaction!(Validation, \"some error\")).with_context(|| \"some context\");\n\n            assert_eq!(\n                res_with_context.unwrap_err().to_string(),\n                \"transaction validation: some context: some error\"\n            );\n        }\n    }\n}\n"
  },
  {
    "path": "packages/fuels-core/src/types/method_descriptor.rs",
    "content": "/// This type is used to specify the fn_selector and name\n/// of methods on contracts at compile time, exported by the abigen! macro\n#[derive(Debug, Clone, Copy)]\npub struct MethodDescriptor {\n    /// The name of the method.\n    pub name: &'static str,\n    /// The function selector of the method.\n    pub fn_selector: &'static [u8],\n}\n\nimpl MethodDescriptor {\n    /// Returns the function selector of the method.\n    pub const fn fn_selector(&self) -> &'static [u8] {\n        self.fn_selector\n    }\n\n    /// Returns the name of the method.\n    pub const fn name(&self) -> &'static str {\n        self.name\n    }\n}\n"
  },
  {
    "path": "packages/fuels-core/src/types/param_types/from_type_application.rs",
    "content": "use std::{collections::HashMap, iter::zip};\n\nuse fuel_abi_types::{\n    abi::unified_program::{UnifiedTypeApplication, UnifiedTypeDeclaration},\n    utils::{extract_array_len, extract_generic_name, extract_str_len, has_tuple_format},\n};\n\nuse crate::types::{\n    errors::{Error, Result, error},\n    param_types::{EnumVariants, NamedParamType, ParamType},\n};\n\nimpl ParamType {\n    /// For when you need to convert a ABI JSON's UnifiedTypeApplication into a ParamType.\n    ///\n    /// # Arguments\n    ///\n    /// * `type_application`: The UnifiedTypeApplication you wish to convert into a ParamType\n    /// * `type_lookup`: A HashMap of UnifiedTypeDeclarations mentioned in the\n    ///   UnifiedTypeApplication where the type id is the key.\n    pub fn try_from_type_application(\n        type_application: &UnifiedTypeApplication,\n        type_lookup: &HashMap<usize, UnifiedTypeDeclaration>,\n    ) -> Result<Self> {\n        Type::try_from(type_application, type_lookup)?.try_into()\n    }\n}\n\n#[derive(Debug, Clone)]\nstruct Type {\n    name: String,\n    type_field: String,\n    generic_params: Vec<Type>,\n    components: Vec<Type>,\n}\n\nimpl Type {\n    /// Will recursively drill down the given generic parameters until all types are\n    /// resolved.\n    ///\n    /// # Arguments\n    ///\n    /// * `type_application`: the type we wish to resolve\n    /// * `types`: all types used in the function call\n    pub fn try_from(\n        type_application: &UnifiedTypeApplication,\n        type_lookup: &HashMap<usize, UnifiedTypeDeclaration>,\n    ) -> Result<Self> {\n        Self::resolve(type_application, type_lookup, &[])\n    }\n\n    fn resolve(\n        type_application: &UnifiedTypeApplication,\n        type_lookup: &HashMap<usize, UnifiedTypeDeclaration>,\n        parent_generic_params: &[(usize, Type)],\n    ) -> Result<Self> {\n        let type_declaration = type_lookup.get(&type_application.type_id).ok_or_else(|| {\n            error!(\n                Codec,\n                \"type id {} not found in type lookup\", type_application.type_id\n            )\n        })?;\n\n        if extract_generic_name(&type_declaration.type_field).is_some() {\n            let (_, generic_type) = parent_generic_params\n                .iter()\n                .find(|(id, _)| *id == type_application.type_id)\n                .ok_or_else(|| {\n                    error!(\n                        Codec,\n                        \"type id {} not found in parent's generic parameters\",\n                        type_application.type_id\n                    )\n                })?;\n\n            // The generic will inherit the name from the parent `type_application`\n            return Ok(Self {\n                name: type_application.name.clone(),\n                ..generic_type.clone()\n            });\n        }\n\n        // Figure out what does the current type do with the inherited generic\n        // parameters and reestablish the mapping since the current type might have\n        // renamed the inherited generic parameters.\n        let generic_params_lookup = Self::determine_generics_for_type(\n            type_application,\n            type_lookup,\n            type_declaration,\n            parent_generic_params,\n        )?;\n\n        // Resolve the enclosed components (if any) with the newly resolved generic\n        // parameters.\n        let components = type_declaration\n            .components\n            .iter()\n            .flatten()\n            .map(|component| Self::resolve(component, type_lookup, &generic_params_lookup))\n            .collect::<Result<Vec<_>>>()?;\n\n        Ok(Type {\n            name: type_application.name.clone(),\n            type_field: type_declaration.type_field.clone(),\n            components,\n            generic_params: generic_params_lookup\n                .into_iter()\n                .map(|(_, ty)| ty)\n                .collect(),\n        })\n    }\n\n    /// For the given type generates generic_type_id -> Type mapping describing to\n    /// which types generic parameters should be resolved.\n    ///\n    /// # Arguments\n    ///\n    /// * `type_application`: The type on which the generic parameters are defined.\n    /// * `types`: All types used.\n    /// * `parent_generic_params`: The generic parameters as inherited from the\n    ///   enclosing type (a struct/enum/array etc.).\n    fn determine_generics_for_type(\n        type_application: &UnifiedTypeApplication,\n        type_lookup: &HashMap<usize, UnifiedTypeDeclaration>,\n        type_declaration: &UnifiedTypeDeclaration,\n        parent_generic_params: &[(usize, Type)],\n    ) -> Result<Vec<(usize, Self)>> {\n        match &type_declaration.type_parameters {\n            // The presence of type_parameters indicates that the current type\n            // (a struct or an enum) defines some generic parameters (i.e. SomeStruct<T, K>).\n            Some(params) if !params.is_empty() => {\n                // Determine what Types the generics will resolve to.\n                let generic_params_from_current_type = type_application\n                    .type_arguments\n                    .iter()\n                    .flatten()\n                    .map(|ty| Self::resolve(ty, type_lookup, parent_generic_params))\n                    .collect::<Result<Vec<_>>>()?;\n\n                let generics_to_use = if !generic_params_from_current_type.is_empty() {\n                    generic_params_from_current_type\n                } else {\n                    // Types such as arrays and enums inherit and forward their\n                    // generic parameters, without declaring their own.\n                    parent_generic_params\n                        .iter()\n                        .map(|(_, ty)| ty)\n                        .cloned()\n                        .collect()\n                };\n\n                // All inherited but unused generic types are dropped. The rest are\n                // re-mapped to new type_ids since child types are free to rename\n                // the generic parameters as they see fit -- i.e.\n                // struct ParentStruct<T>{\n                //     b: ChildStruct<T>\n                // }\n                // struct ChildStruct<K> {\n                //     c: K\n                // }\n\n                Ok(zip(params.clone(), generics_to_use).collect())\n            }\n            _ => Ok(parent_generic_params.to_vec()),\n        }\n    }\n}\n\nimpl TryFrom<Type> for ParamType {\n    type Error = Error;\n\n    fn try_from(value: Type) -> Result<Self> {\n        (&value).try_into()\n    }\n}\n\nimpl TryFrom<&Type> for ParamType {\n    type Error = Error;\n\n    fn try_from(the_type: &Type) -> Result<Self> {\n        let matched_param_type = [\n            try_primitive,\n            try_array,\n            try_str_array,\n            try_str_slice,\n            try_tuple,\n            try_vector,\n            try_bytes,\n            try_std_string,\n            try_raw_slice,\n            try_enum,\n            try_u128,\n            try_struct,\n        ]\n        .into_iter()\n        .map(|fun| fun(the_type))\n        .flat_map(|result| result.ok().flatten())\n        .next();\n\n        matched_param_type.map(Ok).unwrap_or_else(|| {\n            Err(error!(\n                Codec,\n                \"type {} couldn't be converted into a ParamType\", the_type.type_field\n            ))\n        })\n    }\n}\n\nfn convert_into_param_types(coll: &[Type]) -> Result<Vec<ParamType>> {\n    coll.iter().map(ParamType::try_from).collect()\n}\n\nfn named_param_types(coll: &[Type]) -> Result<Vec<NamedParamType>> {\n    coll.iter()\n        .map(|ttype| Ok((ttype.name.clone(), ttype.try_into()?)))\n        .collect()\n}\n\nfn try_struct(the_type: &Type) -> Result<Option<ParamType>> {\n    let field = &the_type.type_field;\n    if field.starts_with(\"struct \") {\n        let fields = named_param_types(&the_type.components)?;\n        let generics = param_types(&the_type.generic_params)?;\n\n        return Ok(Some(ParamType::Struct {\n            name: the_type\n                .type_field\n                .strip_prefix(\"struct \")\n                .expect(\"has `struct`\")\n                .to_string(),\n            fields,\n            generics,\n        }));\n    }\n\n    Ok(None)\n}\n\nfn try_vector(the_type: &Type) -> Result<Option<ParamType>> {\n    if ![\"struct std::vec::Vec\", \"struct Vec\"].contains(&the_type.type_field.as_str()) {\n        return Ok(None);\n    }\n\n    if the_type.generic_params.len() != 1 {\n        return Err(error!(\n            Codec,\n            \"`Vec` must have exactly one generic argument for its type. Found: `{:?}`\",\n            the_type.generic_params\n        ));\n    }\n\n    let vec_elem_type = convert_into_param_types(&the_type.generic_params)?.remove(0);\n\n    Ok(Some(ParamType::Vector(Box::new(vec_elem_type))))\n}\n\nfn try_u128(the_type: &Type) -> Result<Option<ParamType>> {\n    Ok([\"struct std::u128::U128\", \"struct U128\"]\n        .contains(&the_type.type_field.as_str())\n        .then_some(ParamType::U128))\n}\n\nfn try_bytes(the_type: &Type) -> Result<Option<ParamType>> {\n    Ok([\"struct std::bytes::Bytes\", \"struct Bytes\"]\n        .contains(&the_type.type_field.as_str())\n        .then_some(ParamType::Bytes))\n}\n\nfn try_std_string(the_type: &Type) -> Result<Option<ParamType>> {\n    Ok([\"struct std::string::String\", \"struct String\"]\n        .contains(&the_type.type_field.as_str())\n        .then_some(ParamType::String))\n}\n\nfn try_raw_slice(the_type: &Type) -> Result<Option<ParamType>> {\n    Ok((the_type.type_field == \"raw untyped slice\").then_some(ParamType::RawSlice))\n}\n\nfn try_enum(the_type: &Type) -> Result<Option<ParamType>> {\n    let field = &the_type.type_field;\n    if field.starts_with(\"enum \") {\n        let components = named_param_types(&the_type.components)?;\n        let enum_variants = EnumVariants::new(components)?;\n        let generics = param_types(&the_type.generic_params)?;\n\n        return Ok(Some(ParamType::Enum {\n            name: field.strip_prefix(\"enum \").expect(\"has `enum`\").to_string(),\n            enum_variants,\n            generics,\n        }));\n    }\n\n    Ok(None)\n}\n\nfn try_tuple(the_type: &Type) -> Result<Option<ParamType>> {\n    let result = if has_tuple_format(&the_type.type_field) {\n        let tuple_elements = param_types(&the_type.components)?;\n        Some(ParamType::Tuple(tuple_elements))\n    } else {\n        None\n    };\n\n    Ok(result)\n}\n\nfn param_types(coll: &[Type]) -> Result<Vec<ParamType>> {\n    coll.iter().map(|t| t.try_into()).collect()\n}\n\nfn try_str_array(the_type: &Type) -> Result<Option<ParamType>> {\n    Ok(extract_str_len(&the_type.type_field).map(ParamType::StringArray))\n}\n\nfn try_str_slice(the_type: &Type) -> Result<Option<ParamType>> {\n    Ok(if the_type.type_field == \"str\" {\n        Some(ParamType::StringSlice)\n    } else {\n        None\n    })\n}\n\nfn try_array(the_type: &Type) -> Result<Option<ParamType>> {\n    if let Some(len) = extract_array_len(&the_type.type_field) {\n        return match the_type.components.as_slice() {\n            [single_type] => {\n                let array_type = single_type.try_into()?;\n                Ok(Some(ParamType::Array(Box::new(array_type), len)))\n            }\n            _ => Err(error!(\n                Codec,\n                \"array must have elements of exactly one type. Array types: {:?}\",\n                the_type.components\n            )),\n        };\n    }\n    Ok(None)\n}\n\nfn try_primitive(the_type: &Type) -> Result<Option<ParamType>> {\n    let result = match the_type.type_field.as_str() {\n        \"bool\" => Some(ParamType::Bool),\n        \"u8\" => Some(ParamType::U8),\n        \"u16\" => Some(ParamType::U16),\n        \"u32\" => Some(ParamType::U32),\n        \"u64\" => Some(ParamType::U64),\n        \"u256\" => Some(ParamType::U256),\n        \"b256\" => Some(ParamType::B256),\n        \"()\" => Some(ParamType::Unit),\n        \"str\" => Some(ParamType::StringSlice),\n        _ => None,\n    };\n\n    Ok(result)\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn handles_simple_types() -> Result<()> {\n        let parse_param_type = |type_field: &str| {\n            let type_application = UnifiedTypeApplication {\n                name: \"\".to_string(),\n                type_id: 0,\n                type_arguments: None,\n                error_message: None,\n            };\n\n            let declarations = [UnifiedTypeDeclaration {\n                type_id: 0,\n                type_field: type_field.to_string(),\n                components: None,\n                type_parameters: None,\n                alias_of: None,\n            }];\n\n            let type_lookup = declarations\n                .into_iter()\n                .map(|decl| (decl.type_id, decl))\n                .collect::<HashMap<_, _>>();\n\n            ParamType::try_from_type_application(&type_application, &type_lookup)\n        };\n\n        assert_eq!(parse_param_type(\"()\")?, ParamType::Unit);\n        assert_eq!(parse_param_type(\"bool\")?, ParamType::Bool);\n        assert_eq!(parse_param_type(\"u8\")?, ParamType::U8);\n        assert_eq!(parse_param_type(\"u16\")?, ParamType::U16);\n        assert_eq!(parse_param_type(\"u32\")?, ParamType::U32);\n        assert_eq!(parse_param_type(\"u64\")?, ParamType::U64);\n        assert_eq!(parse_param_type(\"u256\")?, ParamType::U256);\n        assert_eq!(parse_param_type(\"b256\")?, ParamType::B256);\n        assert_eq!(parse_param_type(\"str[21]\")?, ParamType::StringArray(21));\n        assert_eq!(parse_param_type(\"str\")?, ParamType::StringSlice);\n\n        Ok(())\n    }\n\n    #[test]\n    fn handles_arrays() -> Result<()> {\n        // given\n        let type_application = UnifiedTypeApplication {\n            name: \"\".to_string(),\n            type_id: 0,\n            type_arguments: None,\n\n            error_message: None,\n        };\n\n        let declarations = [\n            UnifiedTypeDeclaration {\n                type_id: 0,\n                type_field: \"[_; 10]\".to_string(),\n                components: Some(vec![UnifiedTypeApplication {\n                    name: \"__array_element\".to_string(),\n                    type_id: 1,\n                    type_arguments: None,\n                    error_message: None,\n                }]),\n                type_parameters: None,\n                alias_of: None,\n            },\n            UnifiedTypeDeclaration {\n                type_id: 1,\n                type_field: \"u8\".to_string(),\n                components: None,\n                type_parameters: None,\n                alias_of: None,\n            },\n        ];\n\n        let type_lookup = declarations\n            .into_iter()\n            .map(|decl| (decl.type_id, decl))\n            .collect::<HashMap<_, _>>();\n\n        // when\n        let result = ParamType::try_from_type_application(&type_application, &type_lookup)?;\n\n        // then\n        assert_eq!(result, ParamType::Array(Box::new(ParamType::U8), 10));\n\n        Ok(())\n    }\n\n    #[test]\n    fn handles_vectors() -> Result<()> {\n        // given\n        let declarations = [\n            UnifiedTypeDeclaration {\n                type_id: 1,\n                type_field: \"generic T\".to_string(),\n                components: None,\n                type_parameters: None,\n                alias_of: None,\n            },\n            UnifiedTypeDeclaration {\n                type_id: 2,\n                type_field: \"raw untyped ptr\".to_string(),\n                components: None,\n                type_parameters: None,\n                alias_of: None,\n            },\n            UnifiedTypeDeclaration {\n                type_id: 3,\n                type_field: \"struct std::vec::RawVec\".to_string(),\n                components: Some(vec![\n                    UnifiedTypeApplication {\n                        name: \"ptr\".to_string(),\n                        type_id: 2,\n                        type_arguments: None,\n                        error_message: None,\n                    },\n                    UnifiedTypeApplication {\n                        name: \"cap\".to_string(),\n                        type_id: 5,\n                        type_arguments: None,\n                        error_message: None,\n                    },\n                ]),\n                type_parameters: Some(vec![1]),\n                alias_of: None,\n            },\n            UnifiedTypeDeclaration {\n                type_id: 4,\n                type_field: \"struct std::vec::Vec\".to_string(),\n                components: Some(vec![\n                    UnifiedTypeApplication {\n                        name: \"buf\".to_string(),\n                        type_id: 3,\n                        type_arguments: Some(vec![UnifiedTypeApplication {\n                            name: \"\".to_string(),\n                            type_id: 1,\n                            type_arguments: None,\n                            error_message: None,\n                        }]),\n                        error_message: None,\n                    },\n                    UnifiedTypeApplication {\n                        name: \"len\".to_string(),\n                        type_id: 5,\n                        type_arguments: None,\n                        error_message: None,\n                    },\n                ]),\n                type_parameters: Some(vec![1]),\n                alias_of: None,\n            },\n            UnifiedTypeDeclaration {\n                type_id: 5,\n                type_field: \"u64\".to_string(),\n                components: None,\n                type_parameters: None,\n                alias_of: None,\n            },\n            UnifiedTypeDeclaration {\n                type_id: 6,\n                type_field: \"u8\".to_string(),\n                components: None,\n                type_parameters: None,\n                alias_of: None,\n            },\n        ];\n\n        let type_application = UnifiedTypeApplication {\n            name: \"arg\".to_string(),\n            type_id: 4,\n            type_arguments: Some(vec![UnifiedTypeApplication {\n                name: \"\".to_string(),\n                type_id: 6,\n                type_arguments: None,\n                error_message: None,\n            }]),\n            error_message: None,\n        };\n\n        let type_lookup = declarations\n            .into_iter()\n            .map(|decl| (decl.type_id, decl))\n            .collect::<HashMap<_, _>>();\n\n        // when\n        let result = ParamType::try_from_type_application(&type_application, &type_lookup)?;\n\n        // then\n        assert_eq!(result, ParamType::Vector(Box::new(ParamType::U8)));\n\n        Ok(())\n    }\n\n    #[test]\n    fn handles_structs() -> Result<()> {\n        // given\n        let declarations = [\n            UnifiedTypeDeclaration {\n                type_id: 1,\n                type_field: \"generic T\".to_string(),\n                components: None,\n                type_parameters: None,\n                alias_of: None,\n            },\n            UnifiedTypeDeclaration {\n                type_id: 2,\n                type_field: \"struct SomeStruct\".to_string(),\n                components: Some(vec![UnifiedTypeApplication {\n                    name: \"field\".to_string(),\n                    type_id: 1,\n                    type_arguments: None,\n                    error_message: None,\n                }]),\n                type_parameters: Some(vec![1]),\n                alias_of: None,\n            },\n            UnifiedTypeDeclaration {\n                type_id: 3,\n                type_field: \"u8\".to_string(),\n                components: None,\n                type_parameters: None,\n                alias_of: None,\n            },\n        ];\n\n        let type_application = UnifiedTypeApplication {\n            name: \"arg\".to_string(),\n            type_id: 2,\n            type_arguments: Some(vec![UnifiedTypeApplication {\n                name: \"\".to_string(),\n                type_id: 3,\n                type_arguments: None,\n                error_message: None,\n            }]),\n            error_message: None,\n        };\n\n        let type_lookup = declarations\n            .into_iter()\n            .map(|decl| (decl.type_id, decl))\n            .collect::<HashMap<_, _>>();\n\n        // when\n        let result = ParamType::try_from_type_application(&type_application, &type_lookup)?;\n\n        // then\n        assert_eq!(\n            result,\n            ParamType::Struct {\n                name: \"SomeStruct\".to_string(),\n                fields: vec![(\"field\".to_string(), ParamType::U8)],\n                generics: vec![ParamType::U8]\n            }\n        );\n\n        Ok(())\n    }\n\n    #[test]\n    fn handles_enums() -> Result<()> {\n        // given\n        let declarations = [\n            UnifiedTypeDeclaration {\n                type_id: 1,\n                type_field: \"generic T\".to_string(),\n                components: None,\n                type_parameters: None,\n                alias_of: None,\n            },\n            UnifiedTypeDeclaration {\n                type_id: 2,\n                type_field: \"enum SomeEnum\".to_string(),\n                components: Some(vec![UnifiedTypeApplication {\n                    name: \"Variant\".to_string(),\n                    type_id: 1,\n                    type_arguments: None,\n                    error_message: None,\n                }]),\n                type_parameters: Some(vec![1]),\n                alias_of: None,\n            },\n            UnifiedTypeDeclaration {\n                type_id: 3,\n                type_field: \"u8\".to_string(),\n                components: None,\n                type_parameters: None,\n                alias_of: None,\n            },\n        ];\n\n        let type_application = UnifiedTypeApplication {\n            name: \"arg\".to_string(),\n            type_id: 2,\n            type_arguments: Some(vec![UnifiedTypeApplication {\n                name: \"\".to_string(),\n                type_id: 3,\n                type_arguments: None,\n                error_message: None,\n            }]),\n            error_message: None,\n        };\n\n        let type_lookup = declarations\n            .into_iter()\n            .map(|decl| (decl.type_id, decl))\n            .collect::<HashMap<_, _>>();\n\n        // when\n        let result = ParamType::try_from_type_application(&type_application, &type_lookup)?;\n\n        // then\n        assert_eq!(\n            result,\n            ParamType::Enum {\n                name: \"SomeEnum\".to_string(),\n                enum_variants: EnumVariants::new(vec![(\"Variant\".to_string(), ParamType::U8)])?,\n                generics: vec![ParamType::U8]\n            }\n        );\n\n        Ok(())\n    }\n\n    #[test]\n    fn handles_tuples() -> Result<()> {\n        // given\n        let declarations = [\n            UnifiedTypeDeclaration {\n                type_id: 1,\n                type_field: \"(_, _)\".to_string(),\n                components: Some(vec![\n                    UnifiedTypeApplication {\n                        name: \"__tuple_element\".to_string(),\n                        type_id: 3,\n                        type_arguments: None,\n                        error_message: None,\n                    },\n                    UnifiedTypeApplication {\n                        name: \"__tuple_element\".to_string(),\n                        type_id: 2,\n                        type_arguments: None,\n                        error_message: None,\n                    },\n                ]),\n                type_parameters: None,\n                alias_of: None,\n            },\n            UnifiedTypeDeclaration {\n                type_id: 2,\n                type_field: \"str[15]\".to_string(),\n                components: None,\n                type_parameters: None,\n                alias_of: None,\n            },\n            UnifiedTypeDeclaration {\n                type_id: 3,\n                type_field: \"u8\".to_string(),\n                components: None,\n                type_parameters: None,\n                alias_of: None,\n            },\n        ];\n\n        let type_application = UnifiedTypeApplication {\n            name: \"arg\".to_string(),\n            type_id: 1,\n            type_arguments: None,\n            error_message: None,\n        };\n        let type_lookup = declarations\n            .into_iter()\n            .map(|decl| (decl.type_id, decl))\n            .collect::<HashMap<_, _>>();\n\n        // when\n        let result = ParamType::try_from_type_application(&type_application, &type_lookup)?;\n\n        // then\n        assert_eq!(\n            result,\n            ParamType::Tuple(vec![ParamType::U8, ParamType::StringArray(15)])\n        );\n\n        Ok(())\n    }\n\n    #[test]\n    fn ultimate_example() -> Result<()> {\n        // given\n        let declarations = [\n            UnifiedTypeDeclaration {\n                type_id: 1,\n                type_field: \"(_, _)\".to_string(),\n                components: Some(vec![\n                    UnifiedTypeApplication {\n                        name: \"__tuple_element\".to_string(),\n                        type_id: 11,\n                        type_arguments: None,\n                        error_message: None,\n                    },\n                    UnifiedTypeApplication {\n                        name: \"__tuple_element\".to_string(),\n                        type_id: 11,\n                        type_arguments: None,\n                        error_message: None,\n                    },\n                ]),\n                type_parameters: None,\n                alias_of: None,\n            },\n            UnifiedTypeDeclaration {\n                type_id: 2,\n                type_field: \"(_, _)\".to_string(),\n                components: Some(vec![\n                    UnifiedTypeApplication {\n                        name: \"__tuple_element\".to_string(),\n                        type_id: 4,\n                        type_arguments: None,\n                        error_message: None,\n                    },\n                    UnifiedTypeApplication {\n                        name: \"__tuple_element\".to_string(),\n                        type_id: 24,\n                        type_arguments: None,\n                        error_message: None,\n                    },\n                ]),\n                type_parameters: None,\n                alias_of: None,\n            },\n            UnifiedTypeDeclaration {\n                type_id: 3,\n                type_field: \"(_, _)\".to_string(),\n                components: Some(vec![\n                    UnifiedTypeApplication {\n                        name: \"__tuple_element\".to_string(),\n                        type_id: 5,\n                        type_arguments: None,\n                        error_message: None,\n                    },\n                    UnifiedTypeApplication {\n                        name: \"__tuple_element\".to_string(),\n                        type_id: 13,\n                        type_arguments: None,\n                        error_message: None,\n                    },\n                ]),\n                type_parameters: None,\n                alias_of: None,\n            },\n            UnifiedTypeDeclaration {\n                type_id: 4,\n                type_field: \"[_; 1]\".to_string(),\n                components: Some(vec![UnifiedTypeApplication {\n                    name: \"__array_element\".to_string(),\n                    type_id: 8,\n                    type_arguments: Some(vec![UnifiedTypeApplication {\n                        name: \"\".to_string(),\n                        type_id: 22,\n                        type_arguments: Some(vec![UnifiedTypeApplication {\n                            name: \"\".to_string(),\n                            type_id: 21,\n                            type_arguments: Some(vec![UnifiedTypeApplication {\n                                name: \"\".to_string(),\n                                type_id: 18,\n                                type_arguments: Some(vec![UnifiedTypeApplication {\n                                    name: \"\".to_string(),\n                                    type_id: 13,\n                                    type_arguments: None,\n                                    error_message: None,\n                                }]),\n                                error_message: None,\n                            }]),\n                            error_message: None,\n                        }]),\n                        error_message: None,\n                    }]),\n                    error_message: None,\n                }]),\n                type_parameters: None,\n                alias_of: None,\n            },\n            UnifiedTypeDeclaration {\n                type_id: 5,\n                type_field: \"[_; 2]\".to_string(),\n                components: Some(vec![UnifiedTypeApplication {\n                    name: \"__array_element\".to_string(),\n                    type_id: 14,\n                    type_arguments: None,\n                    error_message: None,\n                }]),\n                type_parameters: None,\n                alias_of: None,\n            },\n            UnifiedTypeDeclaration {\n                type_id: 6,\n                type_field: \"[_; 2]\".to_string(),\n                components: Some(vec![UnifiedTypeApplication {\n                    name: \"__array_element\".to_string(),\n                    type_id: 10,\n                    type_arguments: None,\n                    error_message: None,\n                }]),\n                type_parameters: None,\n                alias_of: None,\n            },\n            UnifiedTypeDeclaration {\n                type_id: 7,\n                type_field: \"b256\".to_string(),\n                components: None,\n                type_parameters: None,\n                alias_of: None,\n            },\n            UnifiedTypeDeclaration {\n                type_id: 8,\n                type_field: \"enum EnumWGeneric\".to_string(),\n                components: Some(vec![\n                    UnifiedTypeApplication {\n                        name: \"A\".to_string(),\n                        type_id: 25,\n                        type_arguments: None,\n                        error_message: None,\n                    },\n                    UnifiedTypeApplication {\n                        name: \"B\".to_string(),\n                        type_id: 12,\n                        type_arguments: None,\n                        error_message: None,\n                    },\n                ]),\n                type_parameters: Some(vec![12]),\n                alias_of: None,\n            },\n            UnifiedTypeDeclaration {\n                type_id: 9,\n                type_field: \"generic K\".to_string(),\n                components: None,\n                type_parameters: None,\n                alias_of: None,\n            },\n            UnifiedTypeDeclaration {\n                type_id: 10,\n                type_field: \"generic L\".to_string(),\n                components: None,\n                type_parameters: None,\n                alias_of: None,\n            },\n            UnifiedTypeDeclaration {\n                type_id: 11,\n                type_field: \"generic M\".to_string(),\n                components: None,\n                type_parameters: None,\n                alias_of: None,\n            },\n            UnifiedTypeDeclaration {\n                type_id: 12,\n                type_field: \"generic N\".to_string(),\n                components: None,\n                type_parameters: None,\n                alias_of: None,\n            },\n            UnifiedTypeDeclaration {\n                type_id: 13,\n                type_field: \"generic T\".to_string(),\n                components: None,\n                type_parameters: None,\n                alias_of: None,\n            },\n            UnifiedTypeDeclaration {\n                type_id: 14,\n                type_field: \"generic U\".to_string(),\n                components: None,\n                type_parameters: None,\n                alias_of: None,\n            },\n            UnifiedTypeDeclaration {\n                type_id: 15,\n                type_field: \"raw untyped ptr\".to_string(),\n                components: None,\n                type_parameters: None,\n                alias_of: None,\n            },\n            UnifiedTypeDeclaration {\n                type_id: 16,\n                type_field: \"str[2]\".to_string(),\n                components: None,\n                type_parameters: None,\n                alias_of: None,\n            },\n            UnifiedTypeDeclaration {\n                type_id: 17,\n                type_field: \"struct MegaExample\".to_string(),\n                components: Some(vec![\n                    UnifiedTypeApplication {\n                        name: \"a\".to_string(),\n                        type_id: 3,\n                        type_arguments: None,\n                        error_message: None,\n                    },\n                    UnifiedTypeApplication {\n                        name: \"b\".to_string(),\n                        type_id: 23,\n                        type_arguments: Some(vec![UnifiedTypeApplication {\n                            name: \"\".to_string(),\n                            type_id: 2,\n                            type_arguments: None,\n                            error_message: None,\n                        }]),\n                        error_message: None,\n                    },\n                ]),\n                type_parameters: Some(vec![13, 14]),\n                alias_of: None,\n            },\n            UnifiedTypeDeclaration {\n                type_id: 18,\n                type_field: \"struct PassTheGenericOn\".to_string(),\n                components: Some(vec![UnifiedTypeApplication {\n                    name: \"one\".to_string(),\n                    type_id: 20,\n                    type_arguments: Some(vec![UnifiedTypeApplication {\n                        name: \"\".to_string(),\n                        type_id: 9,\n                        type_arguments: None,\n                        error_message: None,\n                    }]),\n                    error_message: None,\n                }]),\n                type_parameters: Some(vec![9]),\n                alias_of: None,\n            },\n            UnifiedTypeDeclaration {\n                type_id: 19,\n                type_field: \"struct std::vec::RawVec\".to_string(),\n                components: Some(vec![\n                    UnifiedTypeApplication {\n                        name: \"ptr\".to_string(),\n                        type_id: 15,\n                        type_arguments: None,\n                        error_message: None,\n                    },\n                    UnifiedTypeApplication {\n                        name: \"cap\".to_string(),\n                        type_id: 25,\n                        type_arguments: None,\n                        error_message: None,\n                    },\n                ]),\n                type_parameters: Some(vec![13]),\n                alias_of: None,\n            },\n            UnifiedTypeDeclaration {\n                type_id: 20,\n                type_field: \"struct SimpleGeneric\".to_string(),\n                components: Some(vec![UnifiedTypeApplication {\n                    name: \"single_generic_param\".to_string(),\n                    type_id: 13,\n                    type_arguments: None,\n                    error_message: None,\n                }]),\n                type_parameters: Some(vec![13]),\n                alias_of: None,\n            },\n            UnifiedTypeDeclaration {\n                type_id: 21,\n                type_field: \"struct StructWArrayGeneric\".to_string(),\n                components: Some(vec![UnifiedTypeApplication {\n                    name: \"a\".to_string(),\n                    type_id: 6,\n                    type_arguments: None,\n                    error_message: None,\n                }]),\n                type_parameters: Some(vec![10]),\n                alias_of: None,\n            },\n            UnifiedTypeDeclaration {\n                type_id: 22,\n                type_field: \"struct StructWTupleGeneric\".to_string(),\n                components: Some(vec![UnifiedTypeApplication {\n                    name: \"a\".to_string(),\n                    type_id: 1,\n                    type_arguments: None,\n                    error_message: None,\n                }]),\n                type_parameters: Some(vec![11]),\n                alias_of: None,\n            },\n            UnifiedTypeDeclaration {\n                type_id: 23,\n                type_field: \"struct std::vec::Vec\".to_string(),\n                components: Some(vec![\n                    UnifiedTypeApplication {\n                        name: \"buf\".to_string(),\n                        type_id: 19,\n                        type_arguments: Some(vec![UnifiedTypeApplication {\n                            name: \"\".to_string(),\n                            type_id: 13,\n                            type_arguments: None,\n                            error_message: None,\n                        }]),\n                        error_message: None,\n                    },\n                    UnifiedTypeApplication {\n                        name: \"len\".to_string(),\n                        type_id: 25,\n                        type_arguments: None,\n                        error_message: None,\n                    },\n                ]),\n                type_parameters: Some(vec![13]),\n                alias_of: None,\n            },\n            UnifiedTypeDeclaration {\n                type_id: 24,\n                type_field: \"u32\".to_string(),\n                components: None,\n                type_parameters: None,\n                alias_of: None,\n            },\n            UnifiedTypeDeclaration {\n                type_id: 25,\n                type_field: \"u64\".to_string(),\n                components: None,\n                type_parameters: None,\n                alias_of: None,\n            },\n        ];\n\n        let type_lookup = declarations\n            .into_iter()\n            .map(|decl| (decl.type_id, decl))\n            .collect::<HashMap<_, _>>();\n\n        let type_application = UnifiedTypeApplication {\n            name: \"arg1\".to_string(),\n            type_id: 17,\n            type_arguments: Some(vec![\n                UnifiedTypeApplication {\n                    name: \"\".to_string(),\n                    type_id: 16,\n                    type_arguments: None,\n                    error_message: None,\n                },\n                UnifiedTypeApplication {\n                    name: \"\".to_string(),\n                    type_id: 7,\n                    type_arguments: None,\n                    error_message: None,\n                },\n            ]),\n            error_message: None,\n        };\n\n        // when\n        let result = ParamType::try_from_type_application(&type_application, &type_lookup)?;\n\n        // then\n        let expected_param_type = {\n            let fields = vec![(\n                \"one\".to_string(),\n                ParamType::Struct {\n                    name: \"SimpleGeneric\".to_string(),\n                    fields: vec![(\n                        \"single_generic_param\".to_string(),\n                        ParamType::StringArray(2),\n                    )],\n                    generics: vec![ParamType::StringArray(2)],\n                },\n            )];\n            let pass_the_generic_on = ParamType::Struct {\n                name: \"PassTheGenericOn\".to_string(),\n                fields,\n                generics: vec![ParamType::StringArray(2)],\n            };\n\n            let fields = vec![(\n                \"a\".to_string(),\n                ParamType::Array(Box::from(pass_the_generic_on.clone()), 2),\n            )];\n            let struct_w_array_generic = ParamType::Struct {\n                name: \"StructWArrayGeneric\".to_string(),\n                fields,\n                generics: vec![pass_the_generic_on],\n            };\n\n            let fields = vec![(\n                \"a\".to_string(),\n                ParamType::Tuple(vec![\n                    struct_w_array_generic.clone(),\n                    struct_w_array_generic.clone(),\n                ]),\n            )];\n            let struct_w_tuple_generic = ParamType::Struct {\n                name: \"StructWTupleGeneric\".to_string(),\n                fields,\n                generics: vec![struct_w_array_generic],\n            };\n\n            let types = vec![\n                (\"A\".to_string(), ParamType::U64),\n                (\"B\".to_string(), struct_w_tuple_generic.clone()),\n            ];\n            let fields = vec![\n                (\n                    \"a\".to_string(),\n                    ParamType::Tuple(vec![\n                        ParamType::Array(Box::from(ParamType::B256), 2),\n                        ParamType::StringArray(2),\n                    ]),\n                ),\n                (\n                    \"b\".to_string(),\n                    ParamType::Vector(Box::from(ParamType::Tuple(vec![\n                        ParamType::Array(\n                            Box::from(ParamType::Enum {\n                                name: \"EnumWGeneric\".to_string(),\n                                enum_variants: EnumVariants::new(types).unwrap(),\n                                generics: vec![struct_w_tuple_generic],\n                            }),\n                            1,\n                        ),\n                        ParamType::U32,\n                    ]))),\n                ),\n            ];\n            ParamType::Struct {\n                name: \"MegaExample\".to_string(),\n                fields,\n                generics: vec![ParamType::StringArray(2), ParamType::B256],\n            }\n        };\n\n        assert_eq!(result, expected_param_type);\n\n        Ok(())\n    }\n\n    #[test]\n    fn try_vector_correctly_resolves_param_type() {\n        let the_type = given_generic_type_with_path(\"std::vec::Vec\");\n\n        let param_type = try_vector(&the_type).unwrap().unwrap();\n\n        assert_eq!(param_type, ParamType::Vector(Box::new(ParamType::U8)));\n    }\n\n    #[test]\n    fn try_bytes_correctly_resolves_param_type() {\n        let the_type = given_type_with_path(\"std::bytes::Bytes\");\n\n        let param_type = try_bytes(&the_type).unwrap().unwrap();\n\n        assert_eq!(param_type, ParamType::Bytes);\n    }\n\n    #[test]\n    fn try_raw_slice_correctly_resolves_param_type() {\n        let the_type = Type {\n            name: \"\".to_string(),\n            type_field: \"raw untyped slice\".to_string(),\n            generic_params: vec![],\n            components: vec![],\n        };\n\n        let param_type = try_raw_slice(&the_type).unwrap().unwrap();\n\n        assert_eq!(param_type, ParamType::RawSlice);\n    }\n\n    #[test]\n    fn try_std_string_correctly_resolves_param_type() {\n        let the_type = given_type_with_path(\"std::string::String\");\n\n        let param_type = try_std_string(&the_type).unwrap().unwrap();\n\n        assert_eq!(param_type, ParamType::String);\n    }\n\n    fn given_type_with_path(path: &str) -> Type {\n        Type {\n            name: \"\".to_string(),\n            type_field: format!(\"struct {path}\"),\n            generic_params: vec![],\n            components: vec![],\n        }\n    }\n\n    fn given_generic_type_with_path(path: &str) -> Type {\n        Type {\n            name: \"\".to_string(),\n            type_field: format!(\"struct {path}\"),\n            generic_params: vec![Type {\n                name: \"\".to_string(),\n                type_field: \"u8\".to_string(),\n                generic_params: vec![],\n                components: vec![],\n            }],\n            components: vec![],\n        }\n    }\n}\n"
  },
  {
    "path": "packages/fuels-core/src/types/param_types/param_type.rs",
    "content": "use crate::types::errors::{Result, error};\n\npub type NamedParamType = (String, ParamType);\n\n#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]\npub enum ParamType {\n    Unit,\n    Bool,\n    U8,\n    U16,\n    U32,\n    U64,\n    U128,\n    U256,\n    B256,\n    Bytes,\n    String,\n    RawSlice,\n    StringArray(usize),\n    StringSlice,\n    Tuple(Vec<ParamType>),\n    Array(Box<ParamType>, usize),\n    Vector(Box<ParamType>),\n    Struct {\n        name: String,\n        fields: Vec<NamedParamType>,\n        generics: Vec<ParamType>,\n    },\n    Enum {\n        name: String,\n        enum_variants: EnumVariants,\n        generics: Vec<ParamType>,\n    },\n}\n\npub enum ReturnLocation {\n    Return,\n    ReturnData,\n}\n\n#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]\npub struct EnumVariants {\n    variants: Vec<NamedParamType>,\n}\n\nimpl EnumVariants {\n    pub fn new(variants: Vec<NamedParamType>) -> Result<EnumVariants> {\n        if variants.is_empty() {\n            return Err(error!(Other, \"enum variants cannot be empty!\"));\n        }\n\n        Ok(EnumVariants { variants })\n    }\n\n    pub fn variants(&self) -> &Vec<NamedParamType> {\n        &self.variants\n    }\n\n    pub fn param_types(&self) -> impl Iterator<Item = &ParamType> {\n        self.variants.iter().map(|(_, param_type)| param_type)\n    }\n\n    pub fn select_variant(&self, discriminant: u64) -> Result<&NamedParamType> {\n        self.variants.get(discriminant as usize).ok_or_else(|| {\n            error!(\n                Other,\n                \"discriminant `{discriminant}` doesn't point to any variant: {:?}\",\n                self.variants()\n            )\n        })\n    }\n}\n"
  },
  {
    "path": "packages/fuels-core/src/types/param_types.rs",
    "content": "mod from_type_application;\nmod param_type;\n\npub use param_type::*;\n"
  },
  {
    "path": "packages/fuels-core/src/types/token.rs",
    "content": "use std::fmt;\n\nuse crate::types::{\n    core::U256,\n    errors::{Error, Result, error},\n    param_types::EnumVariants,\n};\n\npub type EnumSelector = (u64, Token, EnumVariants);\n\n#[derive(Debug, Clone, PartialEq, Eq, Default, serde::Serialize, serde::Deserialize)]\npub struct StaticStringToken {\n    pub(crate) data: String,\n    expected_len: Option<usize>,\n}\n\nimpl StaticStringToken {\n    pub fn new(data: String, expected_len: Option<usize>) -> Self {\n        StaticStringToken { data, expected_len }\n    }\n\n    fn validate(&self) -> Result<()> {\n        if !self.data.is_ascii() {\n            return Err(error!(Codec, \"string data can only have ascii values\"));\n        }\n\n        if let Some(expected_len) = self.expected_len\n            && self.data.len() != expected_len\n        {\n            return Err(error!(\n                Codec,\n                \"string data has len {}, but the expected len is {}\",\n                self.data.len(),\n                expected_len\n            ));\n        }\n\n        Ok(())\n    }\n\n    pub fn get_encodable_str(&self) -> Result<&str> {\n        self.validate()?;\n        Ok(self.data.as_str())\n    }\n}\n\nimpl TryFrom<StaticStringToken> for String {\n    type Error = Error;\n    fn try_from(string_token: StaticStringToken) -> Result<String> {\n        string_token.validate()?;\n        Ok(string_token.data)\n    }\n}\n\n#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]\npub enum Token {\n    // Used for unit type variants in Enum. An \"empty\" enum is not represented as Enum<empty box>,\n    // because this way we can have both unit and non-unit type variants.\n    Unit,\n    Bool(bool),\n    U8(u8),\n    U16(u16),\n    U32(u32),\n    U64(u64),\n    U128(u128),\n    U256(U256),\n    B256([u8; 32]),\n    Bytes(Vec<u8>),\n    String(String),\n    RawSlice(Vec<u8>),\n    StringArray(StaticStringToken),\n    StringSlice(StaticStringToken),\n    Tuple(Vec<Token>),\n    Array(Vec<Token>),\n    Vector(Vec<Token>),\n    Struct(Vec<Token>),\n    Enum(Box<EnumSelector>),\n}\n\nimpl fmt::Display for Token {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        write!(f, \"{self:?}\")\n    }\n}\n\nimpl Default for Token {\n    fn default() -> Self {\n        Token::U8(0)\n    }\n}\n"
  },
  {
    "path": "packages/fuels-core/src/types/transaction_builders/blob.rs",
    "content": "use std::{fmt::Debug, iter::repeat, sync::Arc};\n\nuse async_trait::async_trait;\nuse fuel_crypto::Signature;\nuse fuel_tx::{\n    BlobIdExt, Chargeable, Output, Transaction as FuelTransaction, UniqueIdentifier, Witness,\n    field::{Policies as PoliciesField, Witnesses},\n    policies::{Policies, PolicyType},\n};\nuse fuel_types::bytes::padded_len_usize;\nuse itertools::Itertools;\n\nuse super::{\n    BuildableTransaction, GAS_ESTIMATION_BLOCK_HORIZON, Strategy, TransactionBuilder,\n    UnresolvedWitnessIndexes, generate_missing_witnesses, impl_tx_builder_trait,\n    resolve_fuel_inputs,\n};\nuse crate::{\n    constants::SIGNATURE_WITNESS_SIZE,\n    traits::Signer,\n    types::{\n        DryRunner,\n        errors::{Result, error, error_transaction},\n        input::Input,\n        transaction::{BlobTransaction, EstimablePredicates, Transaction, TxPolicies},\n    },\n    utils::{calculate_witnesses_size, sealed},\n};\n\n#[derive(Default, Clone, Debug, PartialEq)]\npub struct Blob {\n    data: Vec<u8>,\n}\n\npub type BlobId = [u8; 32];\n\nimpl From<Vec<u8>> for Blob {\n    fn from(data: Vec<u8>) -> Self {\n        Self { data }\n    }\n}\n\nimpl AsRef<[u8]> for Blob {\n    fn as_ref(&self) -> &[u8] {\n        &self.data\n    }\n}\n\nimpl Blob {\n    pub fn new(data: Vec<u8>) -> Self {\n        Self { data }\n    }\n\n    pub fn len(&self) -> usize {\n        self.data.len()\n    }\n\n    pub fn is_empty(&self) -> bool {\n        self.data.is_empty()\n    }\n\n    pub fn id(&self) -> BlobId {\n        fuel_tx::BlobId::compute(&self.data).into()\n    }\n\n    pub fn bytes(&self) -> &[u8] {\n        self.data.as_slice()\n    }\n\n    fn as_blob_body(&self, witness_index: u16) -> fuel_tx::BlobBody {\n        fuel_tx::BlobBody {\n            id: self.id().into(),\n            witness_index,\n        }\n    }\n}\n\nimpl From<Blob> for Vec<u8> {\n    fn from(value: Blob) -> Self {\n        value.data\n    }\n}\n\nimpl From<Blob> for fuel_tx::Witness {\n    fn from(blob: Blob) -> Self {\n        blob.data.into()\n    }\n}\n\n#[derive(Debug, Clone)]\npub struct BlobTransactionBuilder {\n    pub inputs: Vec<Input>,\n    pub outputs: Vec<Output>,\n    pub witnesses: Vec<Witness>,\n    pub tx_policies: TxPolicies,\n    pub gas_price_estimation_block_horizon: u32,\n    pub max_fee_estimation_tolerance: f32,\n    pub build_strategy: Strategy,\n    pub blob: Blob,\n    unresolved_witness_indexes: UnresolvedWitnessIndexes,\n    unresolved_signers: Vec<Arc<dyn Signer + Send + Sync>>,\n    enable_burn: bool,\n}\n\nimpl Default for BlobTransactionBuilder {\n    fn default() -> Self {\n        Self {\n            inputs: Default::default(),\n            outputs: Default::default(),\n            witnesses: Default::default(),\n            tx_policies: Default::default(),\n            gas_price_estimation_block_horizon: GAS_ESTIMATION_BLOCK_HORIZON,\n            max_fee_estimation_tolerance: Default::default(),\n            build_strategy: Default::default(),\n            blob: Default::default(),\n            unresolved_witness_indexes: Default::default(),\n            unresolved_signers: Default::default(),\n            enable_burn: false,\n        }\n    }\n}\nimpl_tx_builder_trait!(BlobTransactionBuilder, BlobTransaction);\n\nimpl BlobTransactionBuilder {\n    /// Calculates the maximum possible blob size by determining the remaining space available in the current transaction before it reaches the maximum allowed size.\n    /// Note: This calculation only considers the transaction size limit and does not account for the maximum gas per transaction.\n    pub async fn estimate_max_blob_size(&self, provider: &impl DryRunner) -> Result<usize> {\n        let mut tb = self.clone();\n        tb.blob = Blob::new(vec![]);\n\n        let tx = tb\n            .with_build_strategy(Strategy::NoSignatures)\n            .build(provider)\n            .await?;\n\n        let current_tx_size = tx.size();\n        let max_tx_size = usize::try_from(\n            provider\n                .consensus_parameters()\n                .await?\n                .tx_params()\n                .max_size(),\n        )\n        .unwrap_or(usize::MAX);\n\n        Ok(max_tx_size.saturating_sub(current_tx_size))\n    }\n\n    pub async fn build(mut self, provider: impl DryRunner) -> Result<BlobTransaction> {\n        let consensus_parameters = provider.consensus_parameters().await?;\n        self.intercept_burn(consensus_parameters.base_asset_id())?;\n\n        let is_using_predicates = self.is_using_predicates();\n\n        let tx = match self.build_strategy {\n            Strategy::Complete => self.resolve_fuel_tx(&provider).await?,\n            Strategy::NoSignatures => {\n                self.set_witness_indexes();\n                self.unresolved_signers = Default::default();\n                self.resolve_fuel_tx(&provider).await?\n            }\n        };\n\n        Ok(BlobTransaction {\n            is_using_predicates,\n            tx,\n        })\n    }\n\n    async fn resolve_fuel_tx(mut self, provider: &impl DryRunner) -> Result<fuel_tx::Blob> {\n        let chain_id = provider.consensus_parameters().await?.chain_id();\n\n        let free_witness_index = self.num_witnesses()?;\n        let body = self.blob.as_blob_body(free_witness_index);\n\n        let blob_witness = std::mem::take(&mut self.blob).into();\n        self.witnesses_mut().push(blob_witness);\n\n        let num_witnesses = self.num_witnesses()?;\n        let policies = self.generate_fuel_policies()?;\n        let is_using_predicates = self.is_using_predicates();\n\n        let mut tx = FuelTransaction::blob(\n            body,\n            policies,\n            resolve_fuel_inputs(self.inputs, num_witnesses, &self.unresolved_witness_indexes)?,\n            self.outputs,\n            self.witnesses,\n        );\n\n        if let Some(max_fee) = self.tx_policies.max_fee() {\n            tx.policies_mut().set(PolicyType::MaxFee, Some(max_fee));\n        } else {\n            Self::set_max_fee_policy(\n                &mut tx,\n                &provider,\n                self.gas_price_estimation_block_horizon,\n                is_using_predicates,\n                self.max_fee_estimation_tolerance,\n            )\n            .await?;\n        }\n\n        let signatures =\n            generate_missing_witnesses(tx.id(&chain_id), &self.unresolved_signers).await?;\n        tx.witnesses_mut().extend(signatures);\n\n        Ok(tx)\n    }\n\n    pub fn with_blob(mut self, blob: Blob) -> Self {\n        self.blob = blob;\n        self\n    }\n\n    pub fn with_max_fee_estimation_tolerance(mut self, max_fee_estimation_tolerance: f32) -> Self {\n        self.max_fee_estimation_tolerance = max_fee_estimation_tolerance;\n        self\n    }\n}\n\nimpl sealed::Sealed for BlobTransactionBuilder {}\n\n#[cfg_attr(not(target_arch = \"wasm32\"), async_trait)]\nimpl BuildableTransaction for BlobTransactionBuilder {\n    type TxType = BlobTransaction;\n    type Strategy = Strategy;\n\n    fn with_build_strategy(mut self, strategy: Self::Strategy) -> Self {\n        self.build_strategy = strategy;\n        self\n    }\n\n    async fn build(self, provider: impl DryRunner) -> Result<Self::TxType> {\n        BlobTransactionBuilder::build(self, provider).await\n    }\n}\n"
  },
  {
    "path": "packages/fuels-core/src/types/transaction_builders/script_tx_estimator.rs",
    "content": "use std::iter::repeat_n;\n\nuse fuel_crypto::Signature;\nuse fuel_tx::{\n    AssetId, Chargeable, ConsensusParameters, Input as FuelInput, TxPointer, Witness,\n    field::{Inputs, Outputs, ScriptGasLimit, WitnessLimit, Witnesses},\n    input::coin::{CoinPredicate, CoinSigned},\n};\nuse itertools::Itertools;\n\nuse crate::{\n    constants::WITNESS_STATIC_SIZE,\n    types::{DryRun, DryRunner, errors::Result},\n};\n\npub(crate) struct ScriptTxEstimator<R> {\n    dry_runner: R,\n    predefined_witnesses: Vec<Witness>,\n    num_unresolved_witnesses: usize,\n    last_dry_run: Option<DryRun>,\n}\n\nimpl<R> ScriptTxEstimator<R> {\n    pub fn new(\n        dry_runner: R,\n        predefined_witnesses: Vec<Witness>,\n        num_unresolved_witnesses: usize,\n    ) -> Self {\n        Self {\n            dry_runner,\n            predefined_witnesses,\n            num_unresolved_witnesses,\n            last_dry_run: None,\n        }\n    }\n}\n\nimpl<R: DryRunner> ScriptTxEstimator<R> {\n    pub async fn run(\n        &mut self,\n        mut tx: fuel_tx::Script,\n        saturate_variable_outputs: bool,\n    ) -> Result<DryRun> {\n        self.prepare_for_estimation(&mut tx, saturate_variable_outputs)\n            .await?;\n\n        self._run(tx).await\n    }\n\n    pub async fn prepare_for_estimation(\n        &mut self,\n        tx: &mut fuel_tx::Script,\n        saturate_variable_outputs: bool,\n    ) -> Result<()> {\n        let consensus_params = self.dry_runner.consensus_parameters().await?;\n        self.add_fake_witnesses(tx);\n        self.add_fake_coins(tx, &consensus_params);\n        if saturate_variable_outputs {\n            self.saturate_with_variable_outputs(tx, &consensus_params);\n        }\n        self.set_script_gas_limit_to_max(tx, &consensus_params);\n\n        Ok(())\n    }\n\n    pub fn last_dry_run(&self) -> Option<DryRun> {\n        self.last_dry_run\n    }\n\n    async fn _run(&mut self, tx: fuel_tx::Script) -> Result<DryRun> {\n        let dry_run = self.dry_runner.dry_run(tx.clone().into()).await?;\n        self.last_dry_run = Some(dry_run);\n\n        Ok(dry_run)\n    }\n\n    fn set_script_gas_limit_to_max(\n        &self,\n        tx: &mut fuel_tx::Script,\n        consensus_params: &ConsensusParameters,\n    ) {\n        let max_gas = tx.max_gas(consensus_params.gas_costs(), consensus_params.fee_params()) + 1;\n        *tx.script_gas_limit_mut() = consensus_params.tx_params().max_gas_per_tx() - max_gas;\n    }\n\n    fn saturate_with_variable_outputs(\n        &self,\n        tx: &mut fuel_tx::Script,\n        consensus_params: &ConsensusParameters,\n    ) {\n        let max_outputs = usize::from(consensus_params.tx_params().max_outputs());\n        let used_outputs = tx.outputs().len();\n\n        let unused_outputs = max_outputs.saturating_sub(used_outputs);\n\n        super::add_variable_outputs(tx, unused_outputs);\n    }\n\n    // When dry running a tx with `utxo_validation` off, the node will not validate signatures.\n    // However, the node will check if the right number of witnesses is present.\n    // This function will create witnesses from a default `Signature` such that the total length matches the expected one.\n    // Using a `Signature` ensures that the calculated fee includes the fee generated by the witnesses.\n    fn add_fake_witnesses(&self, tx: &mut fuel_tx::Script) {\n        let witness: Witness = Signature::default().as_ref().into();\n        let dry_run_witnesses: Vec<_> = repeat_n(witness, self.num_unresolved_witnesses).collect();\n\n        *tx.witnesses_mut() = [self.predefined_witnesses.clone(), dry_run_witnesses].concat();\n    }\n\n    fn add_fake_coins(&self, tx: &mut fuel_tx::Script, consensus_params: &ConsensusParameters) {\n        if let Some(fake_input) =\n            Self::needs_fake_base_input(tx.inputs(), consensus_params.base_asset_id())\n        {\n            tx.inputs_mut().push(fake_input);\n\n            // Add an empty `Witness` for the `coin_signed` we just added\n            tx.witnesses_mut().push(Witness::default());\n            tx.set_witness_limit(tx.witness_limit() + WITNESS_STATIC_SIZE as u64);\n        }\n    }\n\n    fn needs_fake_base_input(\n        inputs: &[FuelInput],\n        base_asset_id: &AssetId,\n    ) -> Option<fuel_tx::Input> {\n        let has_base_asset = inputs.iter().any(|i| match i {\n            FuelInput::CoinSigned(CoinSigned { asset_id, .. })\n            | FuelInput::CoinPredicate(CoinPredicate { asset_id, .. })\n                if asset_id == base_asset_id =>\n            {\n                true\n            }\n            FuelInput::MessageCoinSigned(_) | FuelInput::MessageCoinPredicate(_) => true,\n            _ => false,\n        });\n\n        if has_base_asset {\n            return None;\n        }\n\n        let unique_owners = inputs\n            .iter()\n            .filter_map(|input| match input {\n                FuelInput::CoinSigned(CoinSigned { owner, .. })\n                | FuelInput::CoinPredicate(CoinPredicate { owner, .. }) => Some(owner),\n                _ => None,\n            })\n            .unique()\n            .collect::<Vec<_>>();\n\n        let fake_owner = if let [single_owner] = unique_owners.as_slice() {\n            **single_owner\n        } else {\n            Default::default()\n        };\n\n        Some(FuelInput::coin_signed(\n            Default::default(),\n            fake_owner,\n            1_000_000_000,\n            *base_asset_id,\n            TxPointer::default(),\n            0,\n        ))\n    }\n}\n"
  },
  {
    "path": "packages/fuels-core/src/types/transaction_builders.rs",
    "content": "#![cfg(feature = \"std\")]\n\nuse async_trait::async_trait;\nuse fuel_asm::{GTFArgs, RegId, op};\nuse fuel_crypto::{Hasher, Message as CryptoMessage, Signature};\nuse fuel_tx::{\n    Chargeable, ConsensusParameters, Create, Input as FuelInput, Output, Script, StorageSlot,\n    Transaction as FuelTransaction, TransactionFee, TxPointer, UniqueIdentifier, Upgrade, Upload,\n    UploadBody, Witness,\n    field::{Outputs, Policies as PoliciesField, ScriptGasLimit, Witnesses},\n    policies::{Policies, PolicyType},\n};\npub use fuel_tx::{UpgradePurpose, UploadSubsection};\nuse fuel_types::{Bytes32, Salt, bytes::padded_len_usize};\nuse itertools::Itertools;\nuse script_tx_estimator::ScriptTxEstimator;\nuse std::iter::repeat_n;\nuse std::{\n    collections::HashMap,\n    fmt::{Debug, Formatter},\n    iter::repeat,\n    sync::Arc,\n};\n\nuse crate::{\n    constants::{DEFAULT_GAS_ESTIMATION_BLOCK_HORIZON, SIGNATURE_WITNESS_SIZE, WORD_SIZE},\n    traits::Signer,\n    types::{\n        Address, AssetId, ContractId, DryRunner,\n        coin::Coin,\n        coin_type::CoinType,\n        errors::{Result, error, error_transaction},\n        input::Input,\n        message::Message,\n        transaction::{\n            CreateTransaction, EstimablePredicates, ScriptTransaction, Transaction, TxPolicies,\n            UpgradeTransaction, UploadTransaction,\n        },\n    },\n    utils::{calculate_witnesses_size, sealed},\n};\n\nmod blob;\nmod script_tx_estimator;\n\npub use blob::*;\n\nconst GAS_ESTIMATION_BLOCK_HORIZON: u32 = DEFAULT_GAS_ESTIMATION_BLOCK_HORIZON;\n\n#[derive(Debug, Clone, Default)]\nstruct UnresolvedWitnessIndexes {\n    owner_to_idx_offset: HashMap<Address, u64>,\n}\n\n#[cfg_attr(not(target_arch = \"wasm32\"), async_trait)]\npub trait BuildableTransaction: sealed::Sealed {\n    type TxType: Transaction;\n    type Strategy;\n\n    fn with_build_strategy(self, strategy: Self::Strategy) -> Self;\n    async fn build(self, provider: impl DryRunner) -> Result<Self::TxType>;\n}\n\nimpl sealed::Sealed for ScriptTransactionBuilder {}\n\n#[derive(Debug, Clone, Default)]\npub enum ScriptBuildStrategy {\n    /// Transaction is estimated and signatures are automatically added.\n    #[default]\n    Complete,\n    /// Transaction is estimated but no signatures are added.\n    /// Building without signatures will set the witness indexes of signed coins in the\n    /// order as they appear in the inputs. Multiple coins with the same owner will have\n    /// the same witness index. Make sure you sign the built transaction in the expected order.\n    NoSignatures,\n    /// No estimation is done and no signatures are added. Fake coins are added if no spendable inputs\n    /// are present. Meant only for transactions that are to be dry-run with validations off.\n    /// Useful for reading state with unfunded accounts.\n    StateReadOnly,\n}\n\n#[derive(Debug, Clone, Default)]\npub enum Strategy {\n    /// Transaction is estimated and signatures are automatically added.\n    #[default]\n    Complete,\n    /// Transaction is estimated but no signatures are added.\n    /// Building without signatures will set the witness indexes of signed coins in the\n    /// order as they appear in the inputs. Multiple coins with the same owner will have\n    /// the same witness index. Make sure you sign the built transaction in the expected order.\n    NoSignatures,\n}\n\n#[cfg_attr(not(target_arch = \"wasm32\"), async_trait)]\nimpl BuildableTransaction for ScriptTransactionBuilder {\n    type TxType = ScriptTransaction;\n    type Strategy = ScriptBuildStrategy;\n\n    fn with_build_strategy(mut self, strategy: Self::Strategy) -> Self {\n        self.build_strategy = strategy;\n        self\n    }\n\n    async fn build(self, provider: impl DryRunner) -> Result<Self::TxType> {\n        self.build(provider).await\n    }\n}\n\nimpl sealed::Sealed for CreateTransactionBuilder {}\n\n#[cfg_attr(not(target_arch = \"wasm32\"), async_trait)]\nimpl BuildableTransaction for CreateTransactionBuilder {\n    type TxType = CreateTransaction;\n    type Strategy = Strategy;\n\n    fn with_build_strategy(mut self, strategy: Self::Strategy) -> Self {\n        self.build_strategy = strategy;\n        self\n    }\n\n    async fn build(self, provider: impl DryRunner) -> Result<Self::TxType> {\n        self.build(provider).await\n    }\n}\n\nimpl sealed::Sealed for UploadTransactionBuilder {}\n\n#[cfg_attr(not(target_arch = \"wasm32\"), async_trait)]\nimpl BuildableTransaction for UploadTransactionBuilder {\n    type TxType = UploadTransaction;\n    type Strategy = Strategy;\n\n    fn with_build_strategy(mut self, strategy: Self::Strategy) -> Self {\n        self.build_strategy = strategy;\n        self\n    }\n\n    async fn build(self, provider: impl DryRunner) -> Result<Self::TxType> {\n        self.build(provider).await\n    }\n}\n\nimpl sealed::Sealed for UpgradeTransactionBuilder {}\n\n#[cfg_attr(not(target_arch = \"wasm32\"), async_trait)]\nimpl BuildableTransaction for UpgradeTransactionBuilder {\n    type TxType = UpgradeTransaction;\n    type Strategy = Strategy;\n\n    fn with_build_strategy(mut self, strategy: Self::Strategy) -> Self {\n        self.build_strategy = strategy;\n        self\n    }\n\n    async fn build(self, provider: impl DryRunner) -> Result<Self::TxType> {\n        self.build(provider).await\n    }\n}\n\n#[cfg_attr(not(target_arch = \"wasm32\"), async_trait)]\npub trait TransactionBuilder: BuildableTransaction + Send + sealed::Sealed {\n    type TxType: Transaction;\n\n    fn add_signer(&mut self, signer: impl Signer + Send + Sync + 'static) -> Result<&mut Self>;\n    fn add_signers<'a>(\n        &mut self,\n        signers: impl IntoIterator<Item = &'a std::sync::Arc<dyn Signer + Send + Sync>>,\n    ) -> Result<&mut Self>;\n    async fn estimate_max_fee(&self, provider: impl DryRunner) -> Result<u64>;\n    fn enable_burn(self, enable: bool) -> Self;\n    fn with_tx_policies(self, tx_policies: TxPolicies) -> Self;\n    fn with_inputs(self, inputs: Vec<Input>) -> Self;\n    fn with_outputs(self, outputs: Vec<Output>) -> Self;\n    fn with_witnesses(self, witnesses: Vec<Witness>) -> Self;\n    fn inputs(&self) -> &Vec<Input>;\n    fn inputs_mut(&mut self) -> &mut Vec<Input>;\n    fn outputs(&self) -> &Vec<Output>;\n    fn outputs_mut(&mut self) -> &mut Vec<Output>;\n    fn witnesses(&self) -> &Vec<Witness>;\n    fn witnesses_mut(&mut self) -> &mut Vec<Witness>;\n    fn with_estimation_horizon(self, block_horizon: u32) -> Self;\n}\n\nmacro_rules! impl_tx_builder_trait {\n    ($ty: ty, $tx_ty: ident) => {\n        #[cfg_attr(not(target_arch = \"wasm32\"), async_trait)]\n        impl $crate::types::transaction_builders::TransactionBuilder for $ty {\n            type TxType = $tx_ty;\n\n\n            fn add_signer(&mut self, signer: impl Signer + Send + Sync + 'static) -> Result<&mut Self> {\n                self.validate_no_signer_available(&signer.address())?;\n\n\n                let index_offset = self.unresolved_signers.len() as u64;\n                self.unresolved_witness_indexes\n                    .owner_to_idx_offset\n                    .insert(signer.address().clone(), index_offset);\n                self.unresolved_signers.push(std::sync::Arc::new(signer));\n\n                Ok(self)\n            }\n\n            fn add_signers<'a>(&mut self, signers: impl IntoIterator<Item=&'a std::sync::Arc<dyn Signer + Send + Sync>>) -> Result<&mut Self> {\n                for signer in signers {\n                    self.validate_no_signer_available(&signer.address())?;\n\n                    let index_offset = self.unresolved_signers.len() as u64;\n                    self.unresolved_witness_indexes\n                        .owner_to_idx_offset\n                        .insert(signer.address().clone(), index_offset);\n                    self.unresolved_signers.push(signer.clone());\n                }\n\n                Ok(self)\n            }\n\n            async fn estimate_max_fee(&self, provider: impl DryRunner) -> Result<u64> {\n                let mut fee_estimation_tb = self\n                    .clone()\n                    .with_build_strategy(Self::Strategy::NoSignatures);\n\n                // Add a temporary witness for every `Signer` to include them in the fee\n                // estimation.\n                let witness: Witness = Signature::default().as_ref().into();\n                fee_estimation_tb\n                    .witnesses_mut()\n                    .extend(repeat(witness).take(self.unresolved_signers.len()));\n\n                // Temporarily enable burning to avoid errors when calculating the fee.\n                let fee_estimation_tb = fee_estimation_tb.enable_burn(true);\n\n                let mut tx = $crate::types::transaction_builders::BuildableTransaction::build(\n                    fee_estimation_tb,\n                    &provider,\n                )\n                .await?;\n\n                if tx.is_using_predicates() {\n                    tx.estimate_predicates(&provider, None).await?;\n                }\n\n                let consensus_parameters = provider.consensus_parameters().await?;\n\n                let gas_price = provider\n                    .estimate_gas_price(self.gas_price_estimation_block_horizon)\n                    .await?;\n\n                $crate::types::transaction_builders::estimate_max_fee_w_tolerance(\n                    tx.tx,\n                    self.max_fee_estimation_tolerance,\n                    gas_price,\n                    &consensus_parameters,\n                )\n            }\n\n            fn enable_burn(mut self, enable: bool) -> Self {\n                self.enable_burn = enable;\n                self\n            }\n\n            fn with_tx_policies(mut self, tx_policies: TxPolicies) -> Self {\n                self.tx_policies = tx_policies;\n\n                self\n            }\n\n            fn with_inputs(mut self, inputs: Vec<Input>) -> Self {\n                self.inputs = inputs;\n                self\n            }\n\n            fn with_outputs(mut self, outputs: Vec<Output>) -> Self {\n                self.outputs = outputs;\n                self\n            }\n\n            fn with_witnesses(mut self, witnesses: Vec<Witness>) -> Self {\n                self.witnesses = witnesses;\n                self\n            }\n\n            fn inputs(&self) -> &Vec<Input> {\n                self.inputs.as_ref()\n            }\n\n            fn inputs_mut(&mut self) -> &mut Vec<Input> {\n                &mut self.inputs\n            }\n\n            fn outputs(&self) -> &Vec<Output> {\n                self.outputs.as_ref()\n            }\n\n            fn outputs_mut(&mut self) -> &mut Vec<Output> {\n                &mut self.outputs\n            }\n\n            fn witnesses(&self) -> &Vec<Witness> {\n                self.witnesses.as_ref()\n            }\n\n            fn witnesses_mut(&mut self) -> &mut Vec<Witness> {\n                &mut self.witnesses\n            }\n\n            fn with_estimation_horizon(mut self, block_horizon: u32) -> Self {\n                self.gas_price_estimation_block_horizon = block_horizon;\n\n                self\n            }\n        }\n\n        impl $ty {\n            fn validate_no_signer_available(&self, address: &$crate::types::Address) -> Result<()> {\n                if self\n                    .unresolved_witness_indexes\n                    .owner_to_idx_offset\n                    .contains_key(address)\n                {\n                    return Err(error_transaction!(\n                        Builder,\n                        \"already added `Signer` with address: `{address}`\"\n                    ));\n                }\n\n                Ok(())\n            }\n\n            fn set_witness_indexes(&mut self) {\n                use $crate::types::transaction_builders::TransactionBuilder;\n                self.unresolved_witness_indexes.owner_to_idx_offset = self\n                    .inputs()\n                    .iter()\n                    .filter_map(|input| match input {\n                        Input::ResourceSigned { resource } => resource.owner(),\n                        _ => None,\n                    })\n                    .unique()\n                    .cloned()\n                    .enumerate()\n                    .map(|(idx, owner)| (owner, idx as u64))\n                    .collect();\n            }\n\n            fn generate_fuel_policies(&self) -> Result<Policies> {\n                let witness_limit = match self.tx_policies.witness_limit() {\n                    Some(limit) => limit,\n                    None => self.calculate_witnesses_size()?,\n                };\n                let mut policies = Policies::default().with_witness_limit(witness_limit);\n\n                // `MaxFee` set to `tip` or `0` for `dry_run`\n                policies.set(PolicyType::MaxFee, self.tx_policies.tip().or(Some(0)));\n                policies.set(PolicyType::Maturity, self.tx_policies.maturity());\n                policies.set(PolicyType::Tip, self.tx_policies.tip());\n                policies.set(PolicyType::Expiration, self.tx_policies.expiration());\n                policies.set(PolicyType::Owner, self.tx_policies.owner());\n\n                Ok(policies)\n            }\n\n            fn is_using_predicates(&self) -> bool {\n                use $crate::types::transaction_builders::TransactionBuilder;\n                self.inputs()\n                    .iter()\n                    .any(|input| matches!(input, Input::ResourcePredicate { .. }))\n            }\n\n            fn intercept_burn(&self, base_asset_id: &$crate::types::AssetId) -> Result<()> {\n                use std::collections::HashSet;\n\n                if self.enable_burn {\n                    return Ok(());\n                }\n\n                let assets_w_change = self\n                    .outputs\n                    .iter()\n                    .filter_map(|output| match output {\n                        Output::Change { asset_id, .. } => Some(*asset_id),\n                        _ => None,\n                    })\n                    .collect::<HashSet<_>>();\n\n                let input_assets = self\n                    .inputs\n                    .iter()\n                    .filter_map(|input| match input {\n                        Input::ResourceSigned { resource } |\n                        Input::ResourcePredicate { resource, .. } => resource.asset_id(*base_asset_id),\n                        _ => None,\n                    })\n                    .collect::<HashSet<_>>();\n\n                let diff = input_assets.difference(&assets_w_change).collect_vec();\n                if !diff.is_empty() {\n                    return Err(error_transaction!(\n                        Builder,\n                        \"the following assets have no change outputs and may be burned unintentionally: {:?}. \\\n                        To resolve this, either add the necessary change outputs manually or explicitly allow asset burning \\\n                        by calling `.enable_burn(true)` on the transaction builder.\",\n                        diff\n                    ));\n                }\n\n                Ok(())\n            }\n\n            fn num_witnesses(&self) -> Result<u16> {\n                use $crate::types::transaction_builders::TransactionBuilder;\n                let num_witnesses = self.witnesses().len();\n\n                if num_witnesses + self.unresolved_signers.len() > u16::MAX as usize {\n                    return Err(error_transaction!(\n                        Builder,\n                        \"tx exceeds maximum number of witnesses\"\n                    ));\n                }\n\n                Ok(num_witnesses as u16)\n            }\n\n            fn calculate_witnesses_size(&self) -> Result<u64> {\n                let witnesses_size = calculate_witnesses_size(&self.witnesses);\n                let signature_size = SIGNATURE_WITNESS_SIZE\n                    * self.unresolved_witness_indexes.owner_to_idx_offset.len();\n\n                let padded_len = padded_len_usize(witnesses_size + signature_size)\n                    .ok_or_else(|| error!(Other, \"witnesses size overflow\"))?;\n                Ok(padded_len as u64)\n            }\n\n            async fn set_max_fee_policy<T: Clone + PoliciesField + Chargeable + Into<$tx_ty>>(\n                tx: &mut T,\n                provider: impl DryRunner,\n                block_horizon: u32,\n                is_using_predicates: bool,\n                max_fee_estimation_tolerance: f32,\n            ) -> Result<()> {\n                let mut wrapper_tx: $tx_ty = tx.clone().into();\n\n                if is_using_predicates {\n                    wrapper_tx.estimate_predicates(&provider, None).await?;\n                }\n\n                let gas_price = provider.estimate_gas_price(block_horizon).await?;\n                let consensus_parameters = provider.consensus_parameters().await?;\n\n                let max_fee = $crate::types::transaction_builders::estimate_max_fee_w_tolerance(\n                    wrapper_tx.tx,\n                    max_fee_estimation_tolerance,\n                    gas_price,\n                    &consensus_parameters,\n                )?;\n\n                tx.policies_mut().set(PolicyType::MaxFee, Some(max_fee));\n\n                Ok(())\n            }\n        }\n    };\n}\n\npub(crate) use impl_tx_builder_trait;\n\npub(crate) fn estimate_max_fee_w_tolerance<T: Chargeable>(\n    tx: T,\n    tolerance: f32,\n    gas_price: u64,\n    consensus_parameters: &ConsensusParameters,\n) -> Result<u64> {\n    let gas_costs = &consensus_parameters.gas_costs();\n\n    let fee_params = consensus_parameters.fee_params();\n\n    let tx_fee = TransactionFee::checked_from_tx(gas_costs, fee_params, &tx, gas_price).ok_or(\n        error_transaction!(\n            Builder,\n            \"error calculating `TransactionFee` in `TransactionBuilder`\"\n        ),\n    )?;\n\n    let max_fee_w_tolerance = tx_fee.max_fee() as f64 * (1.0 + f64::from(tolerance));\n\n    Ok(max_fee_w_tolerance.ceil() as u64)\n}\n\nimpl Debug for dyn Signer + Send + Sync {\n    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {\n        f.debug_struct(\"Signer\")\n            .field(\"address\", &self.address())\n            .finish()\n    }\n}\n\n/// Controls the SDK behavior regarding variable transaction outputs.\n///\n/// # Warning\n///\n/// Estimation of variable outputs is performed by saturating the transaction with variable outputs\n/// and counting the number of outputs used. This process can be particularly unreliable in cases\n/// where the script introspects the number of variable outputs and adjusts its logic accordingly.\n/// The script could theoretically mint outputs until all variable outputs are utilized.\n///\n/// In such scenarios, estimation of necessary variable outputs becomes nearly impossible.\n///\n/// It is advised to avoid relying on automatic estimation of variable outputs if the script\n/// contains logic that dynamically adjusts based on the number of outputs.\n#[derive(Debug, Clone, Copy, PartialEq)]\npub enum VariableOutputPolicy {\n    /// Perform a dry run of the transaction estimating the minimum number of variable outputs to\n    /// add.\n    EstimateMinimum,\n    /// Add exactly these many variable outputs to the transaction.\n    Exactly(usize),\n}\n\nimpl Default for VariableOutputPolicy {\n    fn default() -> Self {\n        Self::Exactly(0)\n    }\n}\n\n#[derive(Debug, Clone)]\npub struct ScriptTransactionBuilder {\n    pub script: Vec<u8>,\n    pub script_data: Vec<u8>,\n    pub inputs: Vec<Input>,\n    pub outputs: Vec<Output>,\n    pub witnesses: Vec<Witness>,\n    pub tx_policies: TxPolicies,\n    pub gas_estimation_tolerance: f32,\n    pub max_fee_estimation_tolerance: f32,\n    pub gas_price_estimation_block_horizon: u32,\n    pub variable_output_policy: VariableOutputPolicy,\n    pub build_strategy: ScriptBuildStrategy,\n    unresolved_witness_indexes: UnresolvedWitnessIndexes,\n    unresolved_signers: Vec<Arc<dyn Signer + Send + Sync>>,\n    enable_burn: bool,\n}\n\nimpl Default for ScriptTransactionBuilder {\n    fn default() -> Self {\n        Self {\n            script: Default::default(),\n            script_data: Default::default(),\n            inputs: Default::default(),\n            outputs: Default::default(),\n            witnesses: Default::default(),\n            tx_policies: Default::default(),\n            gas_estimation_tolerance: Default::default(),\n            max_fee_estimation_tolerance: Default::default(),\n            gas_price_estimation_block_horizon: GAS_ESTIMATION_BLOCK_HORIZON,\n            variable_output_policy: Default::default(),\n            build_strategy: Default::default(),\n            unresolved_witness_indexes: Default::default(),\n            unresolved_signers: Default::default(),\n            enable_burn: false,\n        }\n    }\n}\n\n#[derive(Debug, Clone)]\npub struct CreateTransactionBuilder {\n    pub bytecode_length: u64,\n    pub bytecode_witness_index: u16,\n    pub storage_slots: Vec<StorageSlot>,\n    pub inputs: Vec<Input>,\n    pub outputs: Vec<Output>,\n    pub witnesses: Vec<Witness>,\n    pub tx_policies: TxPolicies,\n    pub salt: Salt,\n    pub gas_price_estimation_block_horizon: u32,\n    pub max_fee_estimation_tolerance: f32,\n    pub build_strategy: Strategy,\n    unresolved_witness_indexes: UnresolvedWitnessIndexes,\n    unresolved_signers: Vec<Arc<dyn Signer + Send + Sync>>,\n    enable_burn: bool,\n}\n\nimpl Default for CreateTransactionBuilder {\n    fn default() -> Self {\n        Self {\n            bytecode_length: Default::default(),\n            bytecode_witness_index: Default::default(),\n            storage_slots: Default::default(),\n            inputs: Default::default(),\n            outputs: Default::default(),\n            witnesses: Default::default(),\n            tx_policies: Default::default(),\n            salt: Default::default(),\n            gas_price_estimation_block_horizon: GAS_ESTIMATION_BLOCK_HORIZON,\n            max_fee_estimation_tolerance: Default::default(),\n            build_strategy: Default::default(),\n            unresolved_witness_indexes: Default::default(),\n            unresolved_signers: Default::default(),\n            enable_burn: false,\n        }\n    }\n}\n\n#[derive(Debug, Clone)]\npub struct UploadTransactionBuilder {\n    /// The root of the Merkle tree is created over the bytecode.\n    pub root: Bytes32,\n    /// The witness index of the subsection of the bytecode.\n    pub witness_index: u16,\n    /// The index of the subsection of the bytecode.\n    pub subsection_index: u16,\n    /// The total number of subsections on which bytecode was divided.\n    pub subsections_number: u16,\n    /// The proof set helps to verify the connection of the subsection to the `root`.\n    pub proof_set: Vec<Bytes32>,\n    pub inputs: Vec<Input>,\n    pub outputs: Vec<Output>,\n    pub witnesses: Vec<Witness>,\n    pub tx_policies: TxPolicies,\n    pub gas_price_estimation_block_horizon: u32,\n    pub max_fee_estimation_tolerance: f32,\n    pub build_strategy: Strategy,\n    unresolved_witness_indexes: UnresolvedWitnessIndexes,\n    unresolved_signers: Vec<Arc<dyn Signer + Send + Sync>>,\n    enable_burn: bool,\n}\n\nimpl Default for UploadTransactionBuilder {\n    fn default() -> Self {\n        Self {\n            root: Default::default(),\n            witness_index: Default::default(),\n            subsection_index: Default::default(),\n            subsections_number: Default::default(),\n            proof_set: Default::default(),\n            inputs: Default::default(),\n            outputs: Default::default(),\n            witnesses: Default::default(),\n            tx_policies: Default::default(),\n            gas_price_estimation_block_horizon: GAS_ESTIMATION_BLOCK_HORIZON,\n            max_fee_estimation_tolerance: Default::default(),\n            build_strategy: Default::default(),\n            unresolved_witness_indexes: Default::default(),\n            unresolved_signers: Default::default(),\n            enable_burn: false,\n        }\n    }\n}\n\n#[derive(Debug, Clone)]\npub struct UpgradeTransactionBuilder {\n    /// The purpose of the upgrade.\n    pub purpose: UpgradePurpose,\n    pub inputs: Vec<Input>,\n    pub outputs: Vec<Output>,\n    pub witnesses: Vec<Witness>,\n    pub tx_policies: TxPolicies,\n    pub gas_price_estimation_block_horizon: u32,\n    pub max_fee_estimation_tolerance: f32,\n    pub build_strategy: Strategy,\n    unresolved_witness_indexes: UnresolvedWitnessIndexes,\n    unresolved_signers: Vec<Arc<dyn Signer + Send + Sync>>,\n    enable_burn: bool,\n}\n\nimpl Default for UpgradeTransactionBuilder {\n    fn default() -> Self {\n        Self {\n            purpose: UpgradePurpose::StateTransition {\n                root: Default::default(),\n            },\n            inputs: Default::default(),\n            outputs: Default::default(),\n            witnesses: Default::default(),\n            tx_policies: Default::default(),\n            gas_price_estimation_block_horizon: GAS_ESTIMATION_BLOCK_HORIZON,\n            unresolved_witness_indexes: Default::default(),\n            unresolved_signers: Default::default(),\n            max_fee_estimation_tolerance: Default::default(),\n            build_strategy: Default::default(),\n            enable_burn: false,\n        }\n    }\n}\n\nimpl_tx_builder_trait!(ScriptTransactionBuilder, ScriptTransaction);\nimpl_tx_builder_trait!(CreateTransactionBuilder, CreateTransaction);\nimpl_tx_builder_trait!(UploadTransactionBuilder, UploadTransaction);\nimpl_tx_builder_trait!(UpgradeTransactionBuilder, UpgradeTransaction);\n\nimpl ScriptTransactionBuilder {\n    async fn build(mut self, provider: impl DryRunner) -> Result<ScriptTransaction> {\n        let consensus_parameters = provider.consensus_parameters().await?;\n        self.intercept_burn(consensus_parameters.base_asset_id())?;\n\n        let is_using_predicates = self.is_using_predicates();\n\n        let tx = match self.build_strategy {\n            ScriptBuildStrategy::Complete => self.resolve_fuel_tx(&provider).await?,\n            ScriptBuildStrategy::NoSignatures => {\n                self.set_witness_indexes();\n                self.unresolved_signers = Default::default();\n\n                self.resolve_fuel_tx(&provider).await?\n            }\n            ScriptBuildStrategy::StateReadOnly => {\n                self.resolve_fuel_tx_for_state_reading(provider).await?\n            }\n        };\n\n        Ok(ScriptTransaction {\n            is_using_predicates,\n            tx,\n        })\n    }\n\n    async fn resolve_fuel_tx(self, dry_runner: impl DryRunner) -> Result<Script> {\n        let predefined_witnesses = self.witnesses.clone();\n        let mut script_tx_estimator = self.script_tx_estimator(predefined_witnesses, &dry_runner);\n\n        let mut tx = FuelTransaction::script(\n            0, // default value - will be overwritten\n            self.script.clone(),\n            self.script_data.clone(),\n            self.generate_fuel_policies()?,\n            resolve_fuel_inputs(\n                self.inputs.clone(),\n                self.num_witnesses()?,\n                &self.unresolved_witness_indexes,\n            )?,\n            self.outputs.clone(),\n            vec![],\n        );\n\n        self.add_variable_outputs(&mut script_tx_estimator, &mut tx)\n            .await?;\n\n        // should come after variable outputs because it can then reuse the dry run made for variable outputs\n        self.set_script_gas_limit(&mut script_tx_estimator, &mut tx)\n            .await?;\n\n        if let Some(max_fee) = self.tx_policies.max_fee() {\n            tx.policies_mut().set(PolicyType::MaxFee, Some(max_fee));\n        } else {\n            Self::set_max_fee_policy(\n                &mut tx,\n                &dry_runner,\n                self.gas_price_estimation_block_horizon,\n                self.is_using_predicates(),\n                self.max_fee_estimation_tolerance,\n            )\n            .await?;\n        }\n\n        self.set_witnesses(&mut tx, dry_runner).await?;\n\n        Ok(tx)\n    }\n\n    async fn resolve_fuel_tx_for_state_reading(self, dry_runner: impl DryRunner) -> Result<Script> {\n        let predefined_witnesses = self.witnesses.clone();\n        let mut script_tx_estimator = self.script_tx_estimator(predefined_witnesses, &dry_runner);\n\n        let mut tx = FuelTransaction::script(\n            0, // default value - will be overwritten\n            self.script.clone(),\n            self.script_data.clone(),\n            self.generate_fuel_policies()?,\n            resolve_fuel_inputs(\n                self.inputs.clone(),\n                self.num_witnesses()?,\n                &self.unresolved_witness_indexes,\n            )?,\n            self.outputs.clone(),\n            vec![],\n        );\n\n        let should_saturate_variable_outputs =\n            if let VariableOutputPolicy::Exactly(n) = self.variable_output_policy {\n                add_variable_outputs(&mut tx, n);\n                false\n            } else {\n                true\n            };\n\n        if let Some(max_fee) = self.tx_policies.max_fee() {\n            tx.policies_mut().set(PolicyType::MaxFee, Some(max_fee));\n        } else {\n            Self::set_max_fee_policy(\n                &mut tx,\n                &dry_runner,\n                self.gas_price_estimation_block_horizon,\n                self.is_using_predicates(),\n                self.max_fee_estimation_tolerance,\n            )\n            .await?;\n        }\n\n        script_tx_estimator\n            .prepare_for_estimation(&mut tx, should_saturate_variable_outputs)\n            .await?;\n\n        Ok(tx)\n    }\n\n    async fn set_witnesses(self, tx: &mut fuel_tx::Script, provider: impl DryRunner) -> Result<()> {\n        let missing_witnesses = generate_missing_witnesses(\n            tx.id(&provider.consensus_parameters().await?.chain_id()),\n            &self.unresolved_signers,\n        )\n        .await?;\n        *tx.witnesses_mut() = [self.witnesses, missing_witnesses].concat();\n        Ok(())\n    }\n\n    async fn set_script_gas_limit(\n        &self,\n        dry_runner: &mut ScriptTxEstimator<&impl DryRunner>,\n        tx: &mut fuel_tx::Script,\n    ) -> Result<()> {\n        let has_no_code = self.script.is_empty();\n        let script_gas_limit = if let Some(gas_limit) = self.tx_policies.script_gas_limit() {\n            // Use the user defined value even if it makes the transaction revert.\n            gas_limit\n        } else if has_no_code {\n            0\n        } else {\n            let dry_run = if let Some(dry_run) = dry_runner.last_dry_run() {\n                // Even if the last dry run included variable outputs they only affect the transaction fee,\n                // the script's gas usage remains unchanged. By opting into variable output estimation, the user\n                // acknowledges the issues with tx introspection and asserts that there is no introspective logic\n                // based on the number of variable outputs.\n                //\n                // Therefore, we can trust the gas usage from the last dry run and reuse it, avoiding the need\n                // for an additional dry run.\n                dry_run\n            } else {\n                dry_runner.run(tx.clone(), false).await?\n            };\n            dry_run.gas_with_tolerance(self.gas_estimation_tolerance)\n        };\n\n        *tx.script_gas_limit_mut() = script_gas_limit;\n        Ok(())\n    }\n\n    fn script_tx_estimator<D>(\n        &self,\n        predefined_witnesses: Vec<Witness>,\n        dry_runner: D,\n    ) -> ScriptTxEstimator<D>\n    where\n        D: DryRunner,\n    {\n        let num_unresolved_witnesses = self.unresolved_witness_indexes.owner_to_idx_offset.len();\n        ScriptTxEstimator::new(dry_runner, predefined_witnesses, num_unresolved_witnesses)\n    }\n\n    async fn add_variable_outputs(\n        &self,\n        dry_runner: &mut ScriptTxEstimator<&impl DryRunner>,\n        tx: &mut fuel_tx::Script,\n    ) -> Result<()> {\n        let variable_outputs = match self.variable_output_policy {\n            VariableOutputPolicy::Exactly(num) => num,\n            VariableOutputPolicy::EstimateMinimum => {\n                dry_runner.run(tx.clone(), true).await?.variable_outputs\n            }\n        };\n        add_variable_outputs(tx, variable_outputs);\n\n        Ok(())\n    }\n\n    pub fn with_variable_output_policy(mut self, variable_outputs: VariableOutputPolicy) -> Self {\n        self.variable_output_policy = variable_outputs;\n        self\n    }\n\n    pub fn with_script(mut self, script: Vec<u8>) -> Self {\n        self.script = script;\n        self\n    }\n\n    pub fn with_script_data(mut self, script_data: Vec<u8>) -> Self {\n        self.script_data = script_data;\n        self\n    }\n\n    pub fn with_gas_estimation_tolerance(mut self, tolerance: f32) -> Self {\n        self.gas_estimation_tolerance = tolerance;\n        self\n    }\n\n    pub fn with_max_fee_estimation_tolerance(mut self, max_fee_estimation_tolerance: f32) -> Self {\n        self.max_fee_estimation_tolerance = max_fee_estimation_tolerance;\n        self\n    }\n\n    pub fn prepare_transfer(\n        inputs: Vec<Input>,\n        outputs: Vec<Output>,\n        tx_policies: TxPolicies,\n    ) -> Self {\n        ScriptTransactionBuilder::default()\n            .with_inputs(inputs)\n            .with_outputs(outputs)\n            .with_tx_policies(tx_policies)\n    }\n\n    /// Craft a transaction used to transfer funds to a contract.\n    pub fn prepare_contract_transfer(\n        to: ContractId,\n        amount: u64,\n        asset_id: AssetId,\n        inputs: Vec<Input>,\n        outputs: Vec<Output>,\n        tx_policies: TxPolicies,\n    ) -> Self {\n        let script_data: Vec<u8> = [\n            to.to_vec(),\n            amount.to_be_bytes().to_vec(),\n            asset_id.to_vec(),\n        ]\n        .into_iter()\n        .flatten()\n        .collect();\n\n        // This script loads:\n        //  - a pointer to the contract id,\n        //  - the actual amount\n        //  - a pointer to the asset id\n        // into the registers 0x10, 0x12, 0x13\n        // and calls the TR instruction\n        let script = vec![\n            op::gtf(0x10, 0x00, GTFArgs::ScriptData.into()),\n            op::addi(0x11, 0x10, ContractId::LEN as u16),\n            op::lw(0x12, 0x11, 0),\n            op::addi(0x13, 0x11, WORD_SIZE as u16),\n            op::tr(0x10, 0x12, 0x13),\n            op::ret(RegId::ONE),\n        ]\n        .into_iter()\n        .collect();\n\n        ScriptTransactionBuilder::default()\n            .with_script(script)\n            .with_script_data(script_data)\n            .with_inputs(inputs)\n            .with_outputs(outputs)\n            .with_tx_policies(tx_policies)\n    }\n\n    /// Craft a transaction used to transfer funds to the base chain.\n    pub fn prepare_message_to_output(\n        to: Address,\n        amount: u64,\n        inputs: Vec<Input>,\n        tx_policies: TxPolicies,\n        base_asset_id: AssetId,\n    ) -> Self {\n        let script_data: Vec<u8> = [to.to_vec(), amount.to_be_bytes().to_vec()]\n            .into_iter()\n            .flatten()\n            .collect();\n\n        // This script loads:\n        //  - a pointer to the recipient address,\n        //  - the amount\n        // into the registers 0x10, 0x11\n        // and calls the SMO instruction\n        let script: Vec<u8> = vec![\n            op::gtf(0x10, 0x00, GTFArgs::ScriptData.into()),\n            op::addi(0x11, 0x10, Bytes32::LEN as u16),\n            op::lw(0x11, 0x11, 0),\n            op::smo(0x10, 0x00, 0x00, 0x11),\n            op::ret(RegId::ONE),\n        ]\n        .into_iter()\n        .collect();\n\n        let outputs = vec![Output::change(to, 0, base_asset_id)];\n\n        ScriptTransactionBuilder::default()\n            .with_tx_policies(tx_policies)\n            .with_script(script)\n            .with_script_data(script_data)\n            .with_inputs(inputs)\n            .with_outputs(outputs)\n    }\n}\n\nfn add_variable_outputs(tx: &mut fuel_tx::Script, variable_outputs: usize) {\n    tx.outputs_mut().extend(repeat_n(\n        Output::Variable {\n            amount: 0,\n            to: Address::zeroed(),\n            asset_id: AssetId::zeroed(),\n        },\n        variable_outputs,\n    ));\n}\n\nimpl CreateTransactionBuilder {\n    pub async fn build(mut self, provider: impl DryRunner) -> Result<CreateTransaction> {\n        let consensus_parameters = provider.consensus_parameters().await?;\n        self.intercept_burn(consensus_parameters.base_asset_id())?;\n\n        let is_using_predicates = self.is_using_predicates();\n\n        let tx = match self.build_strategy {\n            Strategy::Complete => self.resolve_fuel_tx(&provider).await?,\n            Strategy::NoSignatures => {\n                self.set_witness_indexes();\n                self.unresolved_signers = Default::default();\n                self.resolve_fuel_tx(&provider).await?\n            }\n        };\n\n        Ok(CreateTransaction {\n            is_using_predicates,\n            tx,\n        })\n    }\n\n    async fn resolve_fuel_tx(self, provider: impl DryRunner) -> Result<Create> {\n        let chain_id = provider.consensus_parameters().await?.chain_id();\n        let num_witnesses = self.num_witnesses()?;\n        let policies = self.generate_fuel_policies()?;\n        let is_using_predicates = self.is_using_predicates();\n\n        let mut tx = FuelTransaction::create(\n            self.bytecode_witness_index,\n            policies,\n            self.salt,\n            self.storage_slots,\n            resolve_fuel_inputs(self.inputs, num_witnesses, &self.unresolved_witness_indexes)?,\n            self.outputs,\n            self.witnesses,\n        );\n\n        if let Some(max_fee) = self.tx_policies.max_fee() {\n            tx.policies_mut().set(PolicyType::MaxFee, Some(max_fee));\n        } else {\n            Self::set_max_fee_policy(\n                &mut tx,\n                &provider,\n                self.gas_price_estimation_block_horizon,\n                is_using_predicates,\n                self.max_fee_estimation_tolerance,\n            )\n            .await?;\n        }\n\n        let missing_witnesses =\n            generate_missing_witnesses(tx.id(&chain_id), &self.unresolved_signers).await?;\n        tx.witnesses_mut().extend(missing_witnesses);\n\n        Ok(tx)\n    }\n\n    pub fn with_bytecode_length(mut self, bytecode_length: u64) -> Self {\n        self.bytecode_length = bytecode_length;\n        self\n    }\n\n    pub fn with_bytecode_witness_index(mut self, bytecode_witness_index: u16) -> Self {\n        self.bytecode_witness_index = bytecode_witness_index;\n        self\n    }\n\n    pub fn with_storage_slots(mut self, mut storage_slots: Vec<StorageSlot>) -> Self {\n        // Storage slots have to be sorted otherwise we'd get a `TransactionCreateStorageSlotOrder`\n        // error.\n        storage_slots.sort();\n        self.storage_slots = storage_slots;\n        self\n    }\n\n    pub fn with_salt(mut self, salt: impl Into<Salt>) -> Self {\n        self.salt = salt.into();\n        self\n    }\n\n    pub fn with_max_fee_estimation_tolerance(mut self, max_fee_estimation_tolerance: f32) -> Self {\n        self.max_fee_estimation_tolerance = max_fee_estimation_tolerance;\n        self\n    }\n\n    pub fn prepare_contract_deployment(\n        binary: Vec<u8>,\n        contract_id: ContractId,\n        state_root: Bytes32,\n        salt: Salt,\n        storage_slots: Vec<StorageSlot>,\n        tx_policies: TxPolicies,\n    ) -> Self {\n        let bytecode_witness_index = 0;\n        let outputs = vec![Output::contract_created(contract_id, state_root)];\n        let witnesses = vec![binary.into()];\n\n        CreateTransactionBuilder::default()\n            .with_tx_policies(tx_policies)\n            .with_bytecode_witness_index(bytecode_witness_index)\n            .with_salt(salt)\n            .with_storage_slots(storage_slots)\n            .with_outputs(outputs)\n            .with_witnesses(witnesses)\n    }\n}\n\nimpl UploadTransactionBuilder {\n    pub async fn build(mut self, provider: impl DryRunner) -> Result<UploadTransaction> {\n        let consensus_parameters = provider.consensus_parameters().await?;\n        self.intercept_burn(consensus_parameters.base_asset_id())?;\n\n        let is_using_predicates = self.is_using_predicates();\n\n        let tx = match self.build_strategy {\n            Strategy::Complete => self.resolve_fuel_tx(&provider).await?,\n            Strategy::NoSignatures => {\n                self.set_witness_indexes();\n                self.unresolved_signers = Default::default();\n                self.resolve_fuel_tx(&provider).await?\n            }\n        };\n\n        Ok(UploadTransaction {\n            is_using_predicates,\n            tx,\n        })\n    }\n\n    async fn resolve_fuel_tx(self, provider: impl DryRunner) -> Result<Upload> {\n        let chain_id = provider.consensus_parameters().await?.chain_id();\n        let num_witnesses = self.num_witnesses()?;\n        let policies = self.generate_fuel_policies()?;\n        let is_using_predicates = self.is_using_predicates();\n\n        let mut tx = FuelTransaction::upload(\n            UploadBody {\n                root: self.root,\n                witness_index: self.witness_index,\n                subsection_index: self.subsection_index,\n                subsections_number: self.subsections_number,\n                proof_set: self.proof_set,\n            },\n            policies,\n            resolve_fuel_inputs(self.inputs, num_witnesses, &self.unresolved_witness_indexes)?,\n            self.outputs,\n            self.witnesses,\n        );\n\n        if let Some(max_fee) = self.tx_policies.max_fee() {\n            tx.policies_mut().set(PolicyType::MaxFee, Some(max_fee));\n        } else {\n            Self::set_max_fee_policy(\n                &mut tx,\n                &provider,\n                self.gas_price_estimation_block_horizon,\n                is_using_predicates,\n                self.max_fee_estimation_tolerance,\n            )\n            .await?;\n        }\n\n        let missing_witnesses =\n            generate_missing_witnesses(tx.id(&chain_id), &self.unresolved_signers).await?;\n        tx.witnesses_mut().extend(missing_witnesses);\n\n        Ok(tx)\n    }\n\n    pub fn with_root(mut self, root: Bytes32) -> Self {\n        self.root = root;\n        self\n    }\n\n    pub fn with_witness_index(mut self, witness_index: u16) -> Self {\n        self.witness_index = witness_index;\n        self\n    }\n\n    pub fn with_subsection_index(mut self, subsection_index: u16) -> Self {\n        self.subsection_index = subsection_index;\n        self\n    }\n\n    pub fn with_subsections_number(mut self, subsections_number: u16) -> Self {\n        self.subsections_number = subsections_number;\n        self\n    }\n\n    pub fn with_proof_set(mut self, proof_set: Vec<Bytes32>) -> Self {\n        self.proof_set = proof_set;\n        self\n    }\n\n    pub fn with_max_fee_estimation_tolerance(mut self, max_fee_estimation_tolerance: f32) -> Self {\n        self.max_fee_estimation_tolerance = max_fee_estimation_tolerance;\n        self\n    }\n\n    pub fn prepare_subsection_upload(\n        subsection: UploadSubsection,\n        tx_policies: TxPolicies,\n    ) -> Self {\n        let subsection_witness_index = 0;\n        let outputs = vec![];\n        let UploadSubsection {\n            root,\n            subsection,\n            subsection_index,\n            subsections_number,\n            proof_set,\n        } = subsection;\n        let witnesses = vec![subsection.into()];\n\n        Self::default()\n            .with_tx_policies(tx_policies)\n            .with_root(root)\n            .with_witness_index(subsection_witness_index)\n            .with_subsection_index(subsection_index)\n            .with_subsections_number(subsections_number)\n            .with_proof_set(proof_set)\n            .with_outputs(outputs)\n            .with_witnesses(witnesses)\n    }\n}\n\nimpl UpgradeTransactionBuilder {\n    pub async fn build(mut self, provider: impl DryRunner) -> Result<UpgradeTransaction> {\n        let consensus_parameters = provider.consensus_parameters().await?;\n        self.intercept_burn(consensus_parameters.base_asset_id())?;\n\n        let is_using_predicates = self.is_using_predicates();\n        let tx = match self.build_strategy {\n            Strategy::Complete => self.resolve_fuel_tx(&provider).await?,\n            Strategy::NoSignatures => {\n                self.set_witness_indexes();\n                self.unresolved_signers = Default::default();\n                self.resolve_fuel_tx(&provider).await?\n            }\n        };\n        Ok(UpgradeTransaction {\n            is_using_predicates,\n            tx,\n        })\n    }\n\n    async fn resolve_fuel_tx(self, provider: impl DryRunner) -> Result<Upgrade> {\n        let chain_id = provider.consensus_parameters().await?.chain_id();\n        let num_witnesses = self.num_witnesses()?;\n        let policies = self.generate_fuel_policies()?;\n        let is_using_predicates = self.is_using_predicates();\n\n        let mut tx = FuelTransaction::upgrade(\n            self.purpose,\n            policies,\n            resolve_fuel_inputs(self.inputs, num_witnesses, &self.unresolved_witness_indexes)?,\n            self.outputs,\n            self.witnesses,\n        );\n\n        if let Some(max_fee) = self.tx_policies.max_fee() {\n            tx.policies_mut().set(PolicyType::MaxFee, Some(max_fee));\n        } else {\n            Self::set_max_fee_policy(\n                &mut tx,\n                &provider,\n                self.gas_price_estimation_block_horizon,\n                is_using_predicates,\n                self.max_fee_estimation_tolerance,\n            )\n            .await?;\n        }\n\n        let missing_witnesses =\n            generate_missing_witnesses(tx.id(&chain_id), &self.unresolved_signers).await?;\n        tx.witnesses_mut().extend(missing_witnesses);\n\n        Ok(tx)\n    }\n\n    pub fn with_purpose(mut self, upgrade_purpose: UpgradePurpose) -> Self {\n        self.purpose = upgrade_purpose;\n        self\n    }\n\n    pub fn with_max_fee_estimation_tolerance(mut self, max_fee_estimation_tolerance: f32) -> Self {\n        self.max_fee_estimation_tolerance = max_fee_estimation_tolerance;\n        self\n    }\n\n    pub fn prepare_state_transition_upgrade(root: Bytes32, tx_policies: TxPolicies) -> Self {\n        Self::default()\n            .with_tx_policies(tx_policies)\n            .with_purpose(UpgradePurpose::StateTransition { root })\n    }\n\n    pub fn prepare_consensus_parameters_upgrade(\n        consensus_parameters: &ConsensusParameters,\n        tx_policies: TxPolicies,\n    ) -> Self {\n        let serialized_consensus_parameters = postcard::to_allocvec(consensus_parameters)\n            .expect(\"Impossible to fail unless there is not enough memory\");\n        let checksum = Hasher::hash(&serialized_consensus_parameters);\n        let witness_index = 0;\n        let outputs = vec![];\n        let witnesses = vec![serialized_consensus_parameters.into()];\n\n        Self::default()\n            .with_tx_policies(tx_policies)\n            .with_purpose(UpgradePurpose::ConsensusParameters {\n                witness_index,\n                checksum,\n            })\n            .with_outputs(outputs)\n            .with_witnesses(witnesses)\n    }\n}\n\n/// Resolve SDK Inputs to fuel_tx Inputs. This function will calculate the right\n/// data offsets for predicates and set witness indexes for signed coins.\nfn resolve_fuel_inputs(\n    inputs: Vec<Input>,\n    num_witnesses: u16,\n    unresolved_witness_indexes: &UnresolvedWitnessIndexes,\n) -> Result<Vec<FuelInput>> {\n    inputs\n        .into_iter()\n        .map(|input| match input {\n            Input::ResourceSigned { resource } => {\n                resolve_signed_resource(resource, num_witnesses, unresolved_witness_indexes)\n            }\n            Input::ResourcePredicate {\n                resource,\n                code,\n                data,\n            } => resolve_predicate_resource(resource, code, data),\n            Input::Contract {\n                utxo_id,\n                balance_root,\n                state_root,\n                tx_pointer,\n                contract_id,\n            } => Ok(FuelInput::contract(\n                utxo_id,\n                balance_root,\n                state_root,\n                tx_pointer,\n                contract_id,\n            )),\n        })\n        .collect()\n}\n\nfn resolve_signed_resource(\n    resource: CoinType,\n    num_witnesses: u16,\n    unresolved_witness_indexes: &UnresolvedWitnessIndexes,\n) -> Result<FuelInput> {\n    match resource {\n        CoinType::Coin(coin) => {\n            let owner = &coin.owner;\n\n            unresolved_witness_indexes\n                .owner_to_idx_offset\n                .get(owner)\n                .ok_or(error_transaction!(\n                    Builder,\n                    \"signature missing for coin with owner: `{owner:?}`\"\n                ))\n                .map(|witness_idx_offset| {\n                    create_coin_input(coin, num_witnesses + *witness_idx_offset as u16)\n                })\n        }\n        CoinType::Message(message) => {\n            let recipient = &message.recipient;\n\n            unresolved_witness_indexes\n                .owner_to_idx_offset\n                .get(recipient)\n                .ok_or(error_transaction!(\n                    Builder,\n                    \"signature missing for message with recipient: `{recipient:?}`\"\n                ))\n                .map(|witness_idx_offset| {\n                    create_coin_message_input(message, num_witnesses + *witness_idx_offset as u16)\n                })\n        }\n        CoinType::Unknown => Err(error_transaction!(\n            Builder,\n            \"can not resolve `CoinType::Unknown`\"\n        )),\n    }\n}\n\nfn resolve_predicate_resource(\n    resource: CoinType,\n    code: Vec<u8>,\n    data: Vec<u8>,\n) -> Result<FuelInput> {\n    match resource {\n        CoinType::Coin(coin) => Ok(create_coin_predicate(coin.asset_id, coin, code, data)),\n        CoinType::Message(message) => Ok(create_coin_message_predicate(message, code, data)),\n        CoinType::Unknown => Err(error_transaction!(\n            Builder,\n            \"can not resolve `CoinType::Unknown`\"\n        )),\n    }\n}\n\npub fn create_coin_input(coin: Coin, witness_index: u16) -> FuelInput {\n    FuelInput::coin_signed(\n        coin.utxo_id,\n        coin.owner,\n        coin.amount,\n        coin.asset_id,\n        TxPointer::default(),\n        witness_index,\n    )\n}\n\npub fn create_coin_message_input(message: Message, witness_index: u16) -> FuelInput {\n    if message.data.is_empty() {\n        FuelInput::message_coin_signed(\n            message.sender,\n            message.recipient,\n            message.amount,\n            message.nonce,\n            witness_index,\n        )\n    } else {\n        FuelInput::message_data_signed(\n            message.sender,\n            message.recipient,\n            message.amount,\n            message.nonce,\n            witness_index,\n            message.data,\n        )\n    }\n}\n\npub fn create_coin_predicate(\n    asset_id: AssetId,\n    coin: Coin,\n    code: Vec<u8>,\n    predicate_data: Vec<u8>,\n) -> FuelInput {\n    FuelInput::coin_predicate(\n        coin.utxo_id,\n        coin.owner,\n        coin.amount,\n        asset_id,\n        TxPointer::default(),\n        0u64,\n        code,\n        predicate_data,\n    )\n}\n\npub fn create_coin_message_predicate(\n    message: Message,\n    code: Vec<u8>,\n    predicate_data: Vec<u8>,\n) -> FuelInput {\n    if message.data.is_empty() {\n        FuelInput::message_coin_predicate(\n            message.sender,\n            message.recipient,\n            message.amount,\n            message.nonce,\n            0u64,\n            code,\n            predicate_data,\n        )\n    } else {\n        FuelInput::message_data_predicate(\n            message.sender,\n            message.recipient,\n            message.amount,\n            message.nonce,\n            0u64,\n            message.data,\n            code,\n            predicate_data,\n        )\n    }\n}\n\nasync fn generate_missing_witnesses(\n    id: Bytes32,\n    unresolved_signatures: &[Arc<dyn Signer + Send + Sync>],\n) -> Result<Vec<Witness>> {\n    let mut witnesses = Vec::with_capacity(unresolved_signatures.len());\n    for signer in unresolved_signatures {\n        let message = CryptoMessage::from_bytes(*id);\n        let signature = signer.sign(message).await?;\n\n        witnesses.push(signature.as_ref().into());\n    }\n\n    Ok(witnesses)\n}\n\n#[cfg(test)]\nmod tests {\n    use std::iter::repeat_with;\n\n    use fuel_crypto::Signature;\n    use fuel_tx::{ConsensusParameters, UtxoId, input::coin::CoinSigned};\n\n    use super::*;\n    use crate::types::{DryRun, message::MessageStatus};\n\n    #[test]\n    fn storage_slots_are_sorted_when_set() {\n        let unsorted_storage_slots = [2, 1].map(given_a_storage_slot).to_vec();\n        let sorted_storage_slots = [1, 2].map(given_a_storage_slot).to_vec();\n\n        let builder =\n            CreateTransactionBuilder::default().with_storage_slots(unsorted_storage_slots);\n\n        assert_eq!(builder.storage_slots, sorted_storage_slots);\n    }\n\n    fn given_a_storage_slot(key: u8) -> StorageSlot {\n        let mut bytes_32 = Bytes32::zeroed();\n        bytes_32[0] = key;\n\n        StorageSlot::new(bytes_32, Default::default())\n    }\n\n    #[test]\n    fn create_message_coin_signed_if_data_is_empty() {\n        assert!(matches!(\n            create_coin_message_input(given_a_message(vec![]), 0),\n            FuelInput::MessageCoinSigned(_)\n        ));\n    }\n\n    #[test]\n    fn create_message_data_signed_if_data_is_not_empty() {\n        assert!(matches!(\n            create_coin_message_input(given_a_message(vec![42]), 0),\n            FuelInput::MessageDataSigned(_)\n        ));\n    }\n\n    #[test]\n    fn create_message_coin_predicate_if_data_is_empty() {\n        assert!(matches!(\n            create_coin_message_predicate(given_a_message(vec![]), vec![], vec![]),\n            FuelInput::MessageCoinPredicate(_)\n        ));\n    }\n\n    #[test]\n    fn create_message_data_predicate_if_data_is_not_empty() {\n        assert!(matches!(\n            create_coin_message_predicate(given_a_message(vec![42]), vec![], vec![]),\n            FuelInput::MessageDataPredicate(_)\n        ));\n    }\n\n    fn given_a_message(data: Vec<u8>) -> Message {\n        Message {\n            sender: Address::default(),\n            recipient: Address::default(),\n            nonce: 0.into(),\n            amount: 0,\n            data,\n            da_height: 0,\n            status: MessageStatus::Unspent,\n        }\n    }\n\n    fn given_a_coin(tx_id: [u8; 32], owner: [u8; 32], amount: u64) -> Coin {\n        Coin {\n            utxo_id: UtxoId::new(tx_id.into(), 0),\n            owner: Address::from(owner),\n            amount,\n            ..Default::default()\n        }\n    }\n\n    fn given_inputs(num_inputs: u8) -> Vec<Input> {\n        (0..num_inputs)\n            .map(|i| {\n                let coin = given_a_coin([i; 32], [num_inputs + i; 32], 1000);\n                Input::resource_signed(CoinType::Coin(coin))\n            })\n            .collect()\n    }\n\n    fn given_witnesses(num_witnesses: usize) -> Vec<Witness> {\n        repeat_with(Witness::default).take(num_witnesses).collect()\n    }\n\n    struct MockDryRunner {\n        c_param: ConsensusParameters,\n    }\n\n    impl Default for MockDryRunner {\n        fn default() -> Self {\n            Self {\n                c_param: ConsensusParameters::standard(),\n            }\n        }\n    }\n\n    #[cfg_attr(target_arch = \"wasm32\", async_trait(?Send))]\n    #[cfg_attr(not(target_arch = \"wasm32\"), async_trait)]\n    impl DryRunner for MockDryRunner {\n        async fn dry_run(&self, _: FuelTransaction) -> Result<DryRun> {\n            Ok(DryRun {\n                succeeded: true,\n                script_gas: 0,\n                variable_outputs: 0,\n            })\n        }\n\n        async fn consensus_parameters(&self) -> Result<ConsensusParameters> {\n            Ok(self.c_param.clone())\n        }\n\n        async fn estimate_gas_price(&self, _block_horizon: u32) -> Result<u64> {\n            Ok(0)\n        }\n\n        async fn estimate_predicates(\n            &self,\n            tx: &FuelTransaction,\n            _: Option<u32>,\n        ) -> Result<FuelTransaction> {\n            Ok(tx.clone())\n        }\n    }\n\n    #[tokio::test]\n    async fn create_tx_builder_witness_indexes_set_correctly() -> Result<()> {\n        // given\n        let num_witnesses = 2;\n        let num_inputs = 3;\n\n        let tb = CreateTransactionBuilder::default()\n            .with_witnesses(given_witnesses(num_witnesses))\n            .with_inputs(given_inputs(num_inputs))\n            .enable_burn(true);\n\n        // when\n        let tx = tb\n            .with_build_strategy(Strategy::NoSignatures)\n            .build(&MockDryRunner::default())\n            .await?;\n\n        // then\n        let indexes: Vec<usize> = tx\n            .inputs()\n            .iter()\n            .filter_map(|input| match input {\n                FuelInput::CoinSigned(CoinSigned { witness_index, .. }) => {\n                    Some(*witness_index as usize)\n                }\n                _ => None,\n            })\n            .collect();\n\n        let expected_indexes: Vec<_> =\n            (num_witnesses..(num_witnesses + num_inputs as usize)).collect();\n\n        assert_eq!(indexes, expected_indexes);\n\n        Ok(())\n    }\n\n    #[tokio::test]\n    async fn script_tx_builder_witness_indexes_set_correctly() -> Result<()> {\n        // given\n        let num_witnesses = 6;\n        let num_inputs = 4;\n\n        let tb = ScriptTransactionBuilder::default()\n            .with_witnesses(given_witnesses(num_witnesses))\n            .with_inputs(given_inputs(num_inputs))\n            .enable_burn(true);\n\n        // when\n        let tx = tb\n            .with_build_strategy(ScriptBuildStrategy::NoSignatures)\n            .build(&MockDryRunner::default())\n            .await?;\n\n        // then\n        let indexes: Vec<usize> = tx\n            .inputs()\n            .iter()\n            .filter_map(|input| match input {\n                FuelInput::CoinSigned(CoinSigned { witness_index, .. }) => {\n                    Some(*witness_index as usize)\n                }\n                _ => None,\n            })\n            .collect();\n\n        let expected_indexes: Vec<_> =\n            (num_witnesses..(num_witnesses + num_inputs as usize)).collect();\n\n        assert_eq!(indexes, expected_indexes);\n\n        Ok(())\n    }\n\n    #[tokio::test]\n    async fn build_w_enable_burn() -> Result<()> {\n        let coin = CoinType::Coin(given_a_coin([1; 32], [2; 32], 1000));\n        test_enable_burn(Input::resource_signed(coin)).await\n    }\n\n    #[tokio::test]\n    async fn build_w_enable_burn_predicates() -> Result<()> {\n        let predicate_coin = CoinType::Coin(given_a_coin([1; 32], [2; 32], 1000));\n\n        test_enable_burn(Input::resource_predicate(\n            predicate_coin,\n            op::ret(1).to_bytes().to_vec(),\n            vec![],\n        ))\n        .await\n    }\n\n    #[tokio::test]\n    async fn build_w_enable_burn_messages() -> Result<()> {\n        let message = CoinType::Message(given_a_message(vec![1, 2, 3]));\n\n        test_enable_burn(Input::resource_signed(message)).await\n    }\n\n    #[tokio::test]\n    async fn build_w_enable_burn_predicates_message() -> Result<()> {\n        let message_predicate = CoinType::Message(given_a_message(vec![1, 2, 3]));\n\n        test_enable_burn(Input::resource_predicate(\n            message_predicate,\n            op::ret(1).to_bytes().to_vec(),\n            vec![],\n        ))\n        .await\n    }\n\n    async fn test_enable_burn(input: Input) -> Result<()> {\n        // Test failure case without enable_burn\n        let tb = ScriptTransactionBuilder::default().with_inputs(vec![input.clone()]);\n        let err = tb\n            .with_build_strategy(ScriptBuildStrategy::NoSignatures)\n            .build(&MockDryRunner::default())\n            .await\n            .expect_err(\"should fail because of missing change outputs\");\n\n        assert!(err.to_string().contains(\"no change outputs\"));\n\n        // Test success case with enable_burn\n        let tb = ScriptTransactionBuilder::default().with_inputs(vec![input]);\n        let _tx = tb\n            .with_build_strategy(ScriptBuildStrategy::NoSignatures)\n            .enable_burn(true)\n            .build(&MockDryRunner::default())\n            .await?;\n\n        Ok(())\n    }\n\n    #[derive(Clone, Debug, Default)]\n    struct MockSigner {\n        address: Address,\n    }\n\n    #[cfg_attr(target_arch = \"wasm32\", async_trait(?Send))]\n    #[cfg_attr(not(target_arch = \"wasm32\"), async_trait)]\n    #[async_trait]\n    impl Signer for MockSigner {\n        async fn sign(&self, _message: fuel_crypto::Message) -> Result<Signature> {\n            Ok(Signature::default())\n        }\n        fn address(&self) -> Address {\n            self.address\n        }\n    }\n\n    #[tokio::test]\n    #[should_panic(expected = \"already added `Signer` with address:\")]\n    async fn add_signer_called_multiple_times() {\n        let mut tb = ScriptTransactionBuilder::default();\n        let signer = MockSigner::default();\n\n        tb.add_signer(signer.clone()).unwrap();\n        tb.add_signer(signer.clone()).unwrap();\n    }\n}\n"
  },
  {
    "path": "packages/fuels-core/src/types/tx_response.rs",
    "content": "use fuel_tx::TxId;\n\nuse super::tx_status::Success;\n\n#[derive(Clone, Debug)]\npub struct TxResponse {\n    pub tx_status: Success,\n    pub tx_id: TxId,\n}\n"
  },
  {
    "path": "packages/fuels-core/src/types/tx_status.rs",
    "content": "use fuel_abi_types::error_codes::{\n    FAILED_ASSERT_EQ_SIGNAL, FAILED_ASSERT_NE_SIGNAL, FAILED_ASSERT_SIGNAL, FAILED_REQUIRE_SIGNAL,\n    FAILED_SEND_MESSAGE_SIGNAL, FAILED_TRANSFER_TO_ADDRESS_SIGNAL, REVERT_WITH_LOG_SIGNAL,\n};\n#[cfg(feature = \"std\")]\nuse fuel_core_client::client::types::TransactionStatus as ClientTransactionStatus;\n#[cfg(feature = \"std\")]\nuse fuel_core_types::services::executor::{TransactionExecutionResult, TransactionExecutionStatus};\nuse fuel_tx::Receipt;\n#[cfg(feature = \"std\")]\nuse fuel_vm::state::ProgramState;\n#[cfg(feature = \"std\")]\nuse std::sync::Arc;\n\n#[cfg(not(feature = \"std\"))]\nuse alloc::sync::Arc;\n\nuse crate::{\n    codec::LogDecoder,\n    types::errors::{Error, Result, transaction::Reason},\n};\n\n#[derive(Debug, Clone)]\npub struct Success {\n    pub receipts: Arc<Vec<Receipt>>,\n    pub total_fee: u64,\n    pub total_gas: u64,\n}\n\n#[derive(Debug, Clone)]\npub struct SqueezedOut {\n    pub reason: String,\n}\n\n#[derive(Debug, Clone)]\npub struct Failure {\n    pub reason: String,\n    pub receipts: Arc<Vec<Receipt>>,\n    pub revert_id: Option<u64>,\n    pub total_fee: u64,\n    pub total_gas: u64,\n}\n\n#[derive(Debug, Clone)]\npub enum TxStatus {\n    Success(Success),\n    PreconfirmationSuccess(Success),\n    Submitted,\n    SqueezedOut(SqueezedOut),\n    Failure(Failure),\n    PreconfirmationFailure(Failure),\n}\n\nimpl TxStatus {\n    pub fn check(&self, log_decoder: Option<&LogDecoder>) -> Result<()> {\n        match self {\n            Self::SqueezedOut(SqueezedOut { reason }) => {\n                Err(Error::Transaction(Reason::SqueezedOut(reason.clone())))\n            }\n            Self::Failure(Failure {\n                receipts,\n                reason,\n                revert_id,\n                ..\n            }) => Err(Self::map_revert_error(\n                receipts.clone(),\n                reason,\n                *revert_id,\n                log_decoder,\n            )),\n            _ => Ok(()),\n        }\n    }\n\n    pub fn take_success_checked(self, log_decoder: Option<&LogDecoder>) -> Result<Success> {\n        match self {\n            Self::SqueezedOut(SqueezedOut { reason }) => {\n                Err(Error::Transaction(Reason::SqueezedOut(reason.clone())))\n            }\n            Self::Failure(Failure {\n                receipts,\n                reason,\n                revert_id,\n                ..\n            })\n            | Self::PreconfirmationFailure(Failure {\n                receipts,\n                reason,\n                revert_id,\n                ..\n            }) => Err(Self::map_revert_error(\n                receipts,\n                &reason,\n                revert_id,\n                log_decoder,\n            )),\n            Self::Submitted => Err(Error::Transaction(Reason::Other(\n                \"transactions was not yet included\".to_owned(),\n            ))),\n            Self::Success(success) | Self::PreconfirmationSuccess(success) => Ok(success),\n        }\n    }\n\n    pub fn total_gas(&self) -> u64 {\n        match self {\n            TxStatus::Success(Success { total_gas, .. })\n            | TxStatus::Failure(Failure { total_gas, .. }) => *total_gas,\n            _ => 0,\n        }\n    }\n\n    pub fn total_fee(&self) -> u64 {\n        match self {\n            TxStatus::Success(Success { total_fee, .. })\n            | TxStatus::Failure(Failure { total_fee, .. }) => *total_fee,\n            _ => 0,\n        }\n    }\n\n    fn map_revert_error(\n        receipts: Arc<Vec<Receipt>>,\n        reason: &str,\n        revert_id: Option<u64>,\n        log_decoder: Option<&LogDecoder>,\n    ) -> Error {\n        if let (Some(revert_id), Some(log_decoder)) = (revert_id, log_decoder)\n            && let Some(error_detail) = log_decoder.get_error_codes(&revert_id)\n        {\n            let error_message = if error_detail.log_id.is_some() {\n                log_decoder\n                    .decode_last_log(&receipts)\n                    .unwrap_or_else(|err| {\n                        format!(\"failed to decode log from require revert: {err}\")\n                    })\n            } else {\n                error_detail.msg.clone().expect(\"is there\")\n            };\n\n            let reason = format!(\n                \"panicked at: `{}` - `{}:{}:{}` with message `{}`\",\n                error_detail.pkg,\n                error_detail.file,\n                error_detail.line,\n                error_detail.column,\n                error_message\n            );\n\n            return Error::Transaction(Reason::Failure {\n                reason,\n                revert_id: Some(revert_id),\n                receipts,\n            });\n        }\n\n        let reason = match (revert_id, log_decoder) {\n            (Some(FAILED_REQUIRE_SIGNAL), Some(log_decoder)) => log_decoder\n                .decode_last_log(&receipts)\n                .unwrap_or_else(|err| format!(\"failed to decode log from require revert: {err}\")),\n            (Some(REVERT_WITH_LOG_SIGNAL), Some(log_decoder)) => log_decoder\n                .decode_last_log(&receipts)\n                .unwrap_or_else(|err| format!(\"failed to decode log from revert_with_log: {err}\")),\n            (Some(FAILED_ASSERT_EQ_SIGNAL), Some(log_decoder)) => {\n                match log_decoder.decode_last_two_logs(&receipts) {\n                    Ok((lhs, rhs)) => format!(\n                        \"assertion failed: `(left == right)`\\n left: `{lhs:?}`\\n right: `{rhs:?}`\"\n                    ),\n                    Err(err) => {\n                        format!(\"failed to decode log from assert_eq revert: {err}\")\n                    }\n                }\n            }\n            (Some(FAILED_ASSERT_NE_SIGNAL), Some(log_decoder)) => {\n                match log_decoder.decode_last_two_logs(&receipts) {\n                    Ok((lhs, rhs)) => format!(\n                        \"assertion failed: `(left != right)`\\n left: `{lhs:?}`\\n right: `{rhs:?}`\"\n                    ),\n                    Err(err) => {\n                        format!(\"failed to decode log from assert_eq revert: {err}\")\n                    }\n                }\n            }\n            (Some(FAILED_ASSERT_SIGNAL), _) => \"assertion failed\".into(),\n            (Some(FAILED_SEND_MESSAGE_SIGNAL), _) => \"failed to send message\".into(),\n            (Some(FAILED_TRANSFER_TO_ADDRESS_SIGNAL), _) => \"failed transfer to address\".into(),\n            _ => reason.to_string(),\n        };\n\n        Error::Transaction(Reason::Failure {\n            reason,\n            revert_id,\n            receipts,\n        })\n    }\n\n    pub fn take_receipts_checked(\n        self,\n        log_decoder: Option<&LogDecoder>,\n    ) -> Result<Arc<Vec<Receipt>>> {\n        self.check(log_decoder)?;\n        Ok(self.take_receipts())\n    }\n\n    pub fn take_receipts(self) -> Arc<Vec<Receipt>> {\n        match self {\n            TxStatus::Success(Success { receipts, .. })\n            | TxStatus::Failure(Failure { receipts, .. }) => receipts,\n            _ => Default::default(),\n        }\n    }\n\n    pub fn is_final(&self) -> bool {\n        matches!(\n            self,\n            TxStatus::Success(_) | TxStatus::Failure(_) | TxStatus::SqueezedOut(_)\n        )\n    }\n}\n\n#[cfg(feature = \"std\")]\nimpl From<ClientTransactionStatus> for TxStatus {\n    fn from(client_status: ClientTransactionStatus) -> Self {\n        match client_status {\n            ClientTransactionStatus::Submitted { .. } => TxStatus::Submitted {},\n            ClientTransactionStatus::Success {\n                receipts,\n                total_gas,\n                total_fee,\n                ..\n            } => TxStatus::Success(Success {\n                receipts: receipts.into(),\n                total_gas,\n                total_fee,\n            }),\n            ClientTransactionStatus::PreconfirmationSuccess {\n                receipts,\n                total_gas,\n                total_fee,\n                ..\n            } => TxStatus::PreconfirmationSuccess(Success {\n                receipts: receipts.unwrap_or_default().into(),\n                total_gas,\n                total_fee,\n            }),\n            ClientTransactionStatus::Failure {\n                reason,\n                program_state,\n                receipts,\n                total_gas,\n                total_fee,\n                ..\n            } => {\n                let revert_id = program_state.and_then(|state| match state {\n                    ProgramState::Revert(revert_id) => Some(revert_id),\n                    _ => None,\n                });\n\n                TxStatus::Failure(Failure {\n                    receipts: receipts.into(),\n                    reason,\n                    revert_id,\n                    total_gas,\n                    total_fee,\n                })\n            }\n            ClientTransactionStatus::PreconfirmationFailure {\n                reason,\n                receipts,\n                total_gas,\n                total_fee,\n                ..\n            } => TxStatus::Failure(Failure {\n                receipts: receipts.unwrap_or_default().into(),\n                reason,\n                revert_id: None,\n                total_gas,\n                total_fee,\n            }),\n            ClientTransactionStatus::SqueezedOut { reason } => {\n                TxStatus::SqueezedOut(SqueezedOut { reason })\n            }\n        }\n    }\n}\n\n#[cfg(feature = \"std\")]\nimpl From<TransactionExecutionStatus> for TxStatus {\n    fn from(value: TransactionExecutionStatus) -> Self {\n        match value.result {\n            TransactionExecutionResult::Success {\n                receipts,\n                total_gas,\n                total_fee,\n                ..\n            } => Self::Success(Success {\n                receipts,\n                total_gas,\n                total_fee,\n            }),\n            TransactionExecutionResult::Failed {\n                result,\n                receipts,\n                total_gas,\n                total_fee,\n                ..\n            } => {\n                let revert_id = result.and_then(|result| match result {\n                    ProgramState::Revert(revert_id) => Some(revert_id),\n                    _ => None,\n                });\n                let reason = TransactionExecutionResult::reason(&receipts, &result);\n\n                Self::Failure(Failure {\n                    receipts,\n                    reason,\n                    revert_id,\n                    total_gas,\n                    total_fee,\n                })\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "packages/fuels-core/src/types/wrappers/block.rs",
    "content": "#![cfg(feature = \"std\")]\n\nuse chrono::{DateTime, Utc};\nuse fuel_core_client::client::types::{\n    block::{Block as ClientBlock, Header as ClientHeader},\n    primitives::Bytes32,\n};\n\n#[derive(Debug, Clone)]\npub struct Header {\n    pub id: Bytes32,\n    pub da_height: u64,\n    pub transactions_count: u16,\n    pub message_receipt_count: u32,\n    pub transactions_root: Bytes32,\n    pub message_outbox_root: Bytes32,\n    pub event_inbox_root: Bytes32,\n    pub consensus_parameters_version: u32,\n    pub state_transition_bytecode_version: u32,\n    pub height: u32,\n    pub prev_root: Bytes32,\n    pub time: Option<DateTime<Utc>>,\n    pub application_hash: Bytes32,\n}\n\nimpl From<ClientHeader> for Header {\n    fn from(client_header: ClientHeader) -> Self {\n        let time = DateTime::from_timestamp(client_header.time.to_unix(), 0);\n\n        Self {\n            id: client_header.id,\n            da_height: client_header.da_height,\n            transactions_count: client_header.transactions_count,\n            message_receipt_count: client_header.message_receipt_count,\n            transactions_root: client_header.transactions_root,\n            message_outbox_root: client_header.message_outbox_root,\n            event_inbox_root: client_header.event_inbox_root,\n            consensus_parameters_version: client_header.consensus_parameters_version,\n            state_transition_bytecode_version: client_header.state_transition_bytecode_version,\n            height: client_header.height,\n            prev_root: client_header.prev_root,\n            time,\n            application_hash: client_header.application_hash,\n        }\n    }\n}\n\n#[derive(Debug, Clone)]\npub struct Block {\n    pub id: Bytes32,\n    pub header: Header,\n    pub transactions: Vec<Bytes32>,\n}\n\nimpl From<ClientBlock> for Block {\n    fn from(client_block: ClientBlock) -> Self {\n        Self {\n            id: client_block.id,\n            header: client_block.header.into(),\n            transactions: client_block.transactions,\n        }\n    }\n}\n"
  },
  {
    "path": "packages/fuels-core/src/types/wrappers/chain_info.rs",
    "content": "#![cfg(feature = \"std\")]\n\nuse fuel_core_client::client::types::chain_info::ChainInfo as ClientChainInfo;\nuse fuel_tx::ConsensusParameters;\n\nuse crate::types::block::Block;\n\n#[derive(Debug)]\npub struct ChainInfo {\n    pub da_height: u64,\n    pub name: String,\n    pub latest_block: Block,\n    pub consensus_parameters: ConsensusParameters,\n}\n\nimpl From<ClientChainInfo> for ChainInfo {\n    fn from(client_chain_info: ClientChainInfo) -> Self {\n        Self {\n            da_height: client_chain_info.da_height,\n            name: client_chain_info.name,\n            latest_block: client_chain_info.latest_block.into(),\n            consensus_parameters: client_chain_info.consensus_parameters,\n        }\n    }\n}\n"
  },
  {
    "path": "packages/fuels-core/src/types/wrappers/coin.rs",
    "content": "#![cfg(feature = \"std\")]\n\nuse fuel_core_chain_config::CoinConfig;\nuse fuel_core_client::client::types::{\n    coins::Coin as ClientCoin,\n    primitives::{AssetId, UtxoId},\n};\n\nuse crate::types::Address;\n\n#[derive(Debug, Clone, Default, PartialEq, Eq, Hash)]\npub struct Coin {\n    pub amount: u64,\n    pub asset_id: AssetId,\n    pub utxo_id: UtxoId,\n    pub owner: Address,\n}\n\nimpl From<ClientCoin> for Coin {\n    fn from(coin: ClientCoin) -> Self {\n        Self {\n            amount: coin.amount,\n            asset_id: coin.asset_id,\n            utxo_id: coin.utxo_id,\n            owner: coin.owner,\n        }\n    }\n}\n\nimpl From<Coin> for CoinConfig {\n    fn from(coin: Coin) -> CoinConfig {\n        Self {\n            tx_id: *coin.utxo_id.tx_id(),\n            output_index: coin.utxo_id.output_index(),\n            owner: fuel_core_chain_config::Owner::Address(coin.owner),\n            amount: coin.amount,\n            asset_id: coin.asset_id,\n            ..Default::default()\n        }\n    }\n}\n"
  },
  {
    "path": "packages/fuels-core/src/types/wrappers/coin_type.rs",
    "content": "#![cfg(feature = \"std\")]\n\nuse fuel_core_client::client::types::CoinType as ClientCoinType;\n\nuse crate::types::{Address, AssetId, coin::Coin, coin_type_id::CoinTypeId, message::Message};\n\n#[derive(Debug, Clone, PartialEq, Eq, Hash)]\npub enum CoinType {\n    Coin(Coin),\n    Message(Message),\n    Unknown,\n}\n\nimpl From<ClientCoinType> for CoinType {\n    fn from(client_resource: ClientCoinType) -> Self {\n        match client_resource {\n            ClientCoinType::Coin(coin) => CoinType::Coin(coin.into()),\n            ClientCoinType::MessageCoin(message) => CoinType::Message(message.into()),\n            ClientCoinType::Unknown => CoinType::Unknown,\n        }\n    }\n}\n\nimpl CoinType {\n    pub fn id(&self) -> Option<CoinTypeId> {\n        match self {\n            CoinType::Coin(coin) => Some(CoinTypeId::UtxoId(coin.utxo_id)),\n            CoinType::Message(message) => Some(CoinTypeId::Nonce(message.nonce)),\n            CoinType::Unknown => None,\n        }\n    }\n\n    pub fn amount(&self) -> u64 {\n        match self {\n            CoinType::Coin(coin) => coin.amount,\n            CoinType::Message(message) => message.amount,\n            CoinType::Unknown => 0,\n        }\n    }\n\n    pub fn coin_asset_id(&self) -> Option<AssetId> {\n        match self {\n            CoinType::Coin(coin) => Some(coin.asset_id),\n            CoinType::Message(_) => None,\n            CoinType::Unknown => None,\n        }\n    }\n\n    pub fn asset_id(&self, base_asset_id: AssetId) -> Option<AssetId> {\n        match self {\n            CoinType::Coin(coin) => Some(coin.asset_id),\n            CoinType::Message(_) => Some(base_asset_id),\n            CoinType::Unknown => None,\n        }\n    }\n\n    pub fn owner(&self) -> Option<&Address> {\n        match self {\n            CoinType::Coin(coin) => Some(&coin.owner),\n            CoinType::Message(message) => Some(&message.recipient),\n            CoinType::Unknown => None,\n        }\n    }\n}\n"
  },
  {
    "path": "packages/fuels-core/src/types/wrappers/coin_type_id.rs",
    "content": "use fuel_tx::UtxoId;\nuse fuel_types::Nonce;\n\n#[derive(Debug, Clone, PartialEq, Eq, Hash)]\npub enum CoinTypeId {\n    UtxoId(UtxoId),\n    Nonce(Nonce),\n}\n"
  },
  {
    "path": "packages/fuels-core/src/types/wrappers/input.rs",
    "content": "#![cfg(feature = \"std\")]\n\nuse std::hash::Hash;\n\nuse fuel_tx::{TxPointer, UtxoId};\nuse fuel_types::{Bytes32, ContractId};\n\nuse crate::types::coin_type::CoinType;\n\n#[derive(Debug, Clone, PartialEq, Eq, Hash)]\npub enum Input {\n    ResourceSigned {\n        resource: CoinType,\n    },\n    ResourcePredicate {\n        resource: CoinType,\n        code: Vec<u8>,\n        data: Vec<u8>,\n    },\n    Contract {\n        utxo_id: UtxoId,\n        balance_root: Bytes32,\n        state_root: Bytes32,\n        tx_pointer: TxPointer,\n        contract_id: ContractId,\n    },\n}\n\nimpl Input {\n    pub const fn resource_signed(resource: CoinType) -> Self {\n        Self::ResourceSigned { resource }\n    }\n\n    pub const fn resource_predicate(resource: CoinType, code: Vec<u8>, data: Vec<u8>) -> Self {\n        Self::ResourcePredicate {\n            resource,\n            code,\n            data,\n        }\n    }\n\n    pub fn amount(&self) -> Option<u64> {\n        match self {\n            Self::ResourceSigned { resource, .. } | Self::ResourcePredicate { resource, .. } => {\n                Some(resource.amount())\n            }\n            _ => None,\n        }\n    }\n\n    pub fn contains_data(&self) -> bool {\n        match self {\n            Self::ResourceSigned {\n                resource: CoinType::Message(msg),\n                ..\n            }\n            | Self::ResourcePredicate {\n                resource: CoinType::Message(msg),\n                ..\n            } => !msg.data.is_empty(),\n            _ => false,\n        }\n    }\n\n    pub const fn contract(\n        utxo_id: UtxoId,\n        balance_root: Bytes32,\n        state_root: Bytes32,\n        tx_pointer: TxPointer,\n        contract_id: ContractId,\n    ) -> Self {\n        Self::Contract {\n            utxo_id,\n            balance_root,\n            state_root,\n            tx_pointer,\n            contract_id,\n        }\n    }\n}\n"
  },
  {
    "path": "packages/fuels-core/src/types/wrappers/message.rs",
    "content": "#![cfg(feature = \"std\")]\n\nuse crate::types::{Address, MessageId, Nonce};\nuse fuel_core_chain_config::MessageConfig;\nuse fuel_core_client::client::types::{\n    coins::MessageCoin as ClientMessageCoin, message::Message as ClientMessage,\n};\n\n#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]\npub enum MessageStatus {\n    #[default]\n    Unspent,\n    Spent,\n}\n\n#[derive(Debug, Clone, PartialEq, Eq, Hash)]\npub struct Message {\n    pub amount: u64,\n    pub sender: Address,\n    pub recipient: Address,\n    pub nonce: Nonce,\n    pub data: Vec<u8>,\n    pub da_height: u64,\n    pub status: MessageStatus,\n}\n\nimpl Message {\n    pub fn message_id(&self) -> MessageId {\n        fuel_tx::Input::compute_message_id(\n            &self.sender,\n            &self.recipient,\n            &self.nonce,\n            self.amount,\n            &self.data,\n        )\n    }\n}\n\nimpl From<ClientMessage> for Message {\n    fn from(message: ClientMessage) -> Self {\n        Self {\n            amount: message.amount,\n            sender: message.sender,\n            recipient: message.recipient,\n            nonce: message.nonce,\n            data: message.data,\n            da_height: message.da_height,\n            status: MessageStatus::Unspent,\n        }\n    }\n}\n\nimpl From<ClientMessageCoin> for Message {\n    fn from(message: ClientMessageCoin) -> Self {\n        Self {\n            amount: message.amount,\n            sender: message.sender,\n            recipient: message.recipient,\n            nonce: message.nonce,\n            data: Default::default(),\n            da_height: message.da_height,\n            status: MessageStatus::Unspent,\n        }\n    }\n}\n\nimpl From<Message> for MessageConfig {\n    fn from(message: Message) -> MessageConfig {\n        MessageConfig {\n            sender: message.sender,\n            recipient: message.recipient,\n            nonce: message.nonce,\n            amount: message.amount,\n            data: message.data,\n            da_height: message.da_height.into(),\n        }\n    }\n}\n"
  },
  {
    "path": "packages/fuels-core/src/types/wrappers/message_proof.rs",
    "content": "#![cfg(feature = \"std\")]\n\nuse fuel_core_client::client::types::{\n    MerkleProof as ClientMerkleProof, MessageProof as ClientMessageProof, primitives::Nonce,\n};\n\nuse crate::types::{Address, Bytes32, block::Header};\n\n#[derive(Debug)]\npub struct MerkleProof {\n    /// The proof set of the message proof.\n    pub proof_set: Vec<Bytes32>,\n    /// The index that was used to produce this proof.\n    pub proof_index: u64,\n}\n\nimpl From<ClientMerkleProof> for MerkleProof {\n    fn from(client_merkle_proof: ClientMerkleProof) -> Self {\n        Self {\n            proof_set: client_merkle_proof.proof_set,\n            proof_index: client_merkle_proof.proof_index,\n        }\n    }\n}\n\n#[derive(Debug)]\npub struct MessageProof {\n    /// Proof that message is contained within the provided block header.\n    pub message_proof: MerkleProof,\n    /// Proof that the provided block header is contained within the blockchain history.\n    pub block_proof: MerkleProof,\n    /// The previous fuel block header that contains the message. Message block height <\n    /// commit block height.\n    pub message_block_header: Header,\n    /// The consensus header associated with the finalized commit being used\n    /// as the root of the block proof.\n    pub commit_block_header: Header,\n    pub sender: Address,\n    pub recipient: Address,\n    pub nonce: Nonce,\n    pub amount: u64,\n    pub data: Vec<u8>,\n}\n\nimpl From<ClientMessageProof> for MessageProof {\n    fn from(client_message_proof: ClientMessageProof) -> Self {\n        Self {\n            message_proof: client_message_proof.message_proof.into(),\n            block_proof: client_message_proof.block_proof.into(),\n            message_block_header: client_message_proof.message_block_header.into(),\n            commit_block_header: client_message_proof.commit_block_header.into(),\n            sender: client_message_proof.sender,\n            recipient: client_message_proof.recipient,\n            nonce: client_message_proof.nonce,\n            amount: client_message_proof.amount,\n            data: client_message_proof.data,\n        }\n    }\n}\n"
  },
  {
    "path": "packages/fuels-core/src/types/wrappers/node_info.rs",
    "content": "#![cfg(feature = \"std\")]\n\nuse fuel_core_client::client::types::node_info::NodeInfo as ClientNodeInfo;\n\n#[derive(Debug, Clone)]\npub struct NodeInfo {\n    pub utxo_validation: bool,\n    pub vm_backtrace: bool,\n    pub max_tx: u64,\n    pub max_depth: u64,\n    pub node_version: String,\n}\n\nimpl From<ClientNodeInfo> for NodeInfo {\n    fn from(client_node_info: ClientNodeInfo) -> Self {\n        Self {\n            utxo_validation: client_node_info.utxo_validation,\n            vm_backtrace: client_node_info.vm_backtrace,\n            max_tx: client_node_info.max_tx,\n            max_depth: client_node_info.max_depth,\n            node_version: client_node_info.node_version,\n        }\n    }\n}\n"
  },
  {
    "path": "packages/fuels-core/src/types/wrappers/transaction.rs",
    "content": "use std::{collections::HashMap, fmt::Debug};\n\nuse async_trait::async_trait;\nuse fuel_crypto::{Message, Signature};\nuse fuel_tx::{\n    Blob, Bytes32, Cacheable, Chargeable, ConsensusParameters, Create, FormatValidityChecks, Input,\n    Mint, Output, Salt as FuelSalt, Script, StorageSlot, Transaction as FuelTransaction,\n    TransactionFee, UniqueIdentifier, Upgrade, Upload, Witness,\n    field::{\n        Inputs, MintAmount, MintAssetId, Outputs, Policies as PoliciesField, Script as ScriptField,\n        ScriptData, ScriptGasLimit, WitnessLimit, Witnesses,\n    },\n    input::{\n        coin::{CoinPredicate, CoinSigned},\n        message::{\n            MessageCoinPredicate, MessageCoinSigned, MessageDataPredicate, MessageDataSigned,\n        },\n    },\n    policies::PolicyType,\n};\nuse fuel_types::{AssetId, ChainId, bytes::padded_len_usize};\nuse itertools::Itertools;\n\nuse crate::{\n    traits::Signer,\n    types::{\n        Address, DryRunner,\n        errors::{Error, Result, error, error_transaction},\n    },\n    utils::{calculate_witnesses_size, sealed},\n};\n\n#[derive(Default, Debug, Clone)]\npub struct Transactions {\n    fuel_transactions: Vec<FuelTransaction>,\n}\n\nimpl Transactions {\n    pub fn new() -> Self {\n        Self::default()\n    }\n\n    pub fn insert(mut self, tx: impl Into<FuelTransaction>) -> Self {\n        self.fuel_transactions.push(tx.into());\n\n        self\n    }\n\n    pub fn as_slice(&self) -> &[FuelTransaction] {\n        &self.fuel_transactions\n    }\n}\n\n#[derive(Default, Debug, Clone, PartialEq, Eq)]\npub struct MintTransaction {\n    tx: Box<Mint>,\n}\n\nimpl From<MintTransaction> for FuelTransaction {\n    fn from(mint: MintTransaction) -> Self {\n        (*mint.tx).into()\n    }\n}\n\nimpl From<MintTransaction> for Mint {\n    fn from(tx: MintTransaction) -> Self {\n        *tx.tx\n    }\n}\n\nimpl From<Mint> for MintTransaction {\n    fn from(tx: Mint) -> Self {\n        Self { tx: Box::new(tx) }\n    }\n}\n\nimpl MintTransaction {\n    pub fn check_without_signatures(\n        &self,\n        block_height: u32,\n        consensus_parameters: &ConsensusParameters,\n    ) -> Result<()> {\n        Ok(self\n            .tx\n            .check_without_signatures(block_height.into(), consensus_parameters)?)\n    }\n    #[must_use]\n    pub fn id(&self, chain_id: ChainId) -> Bytes32 {\n        self.tx.id(&chain_id)\n    }\n\n    #[must_use]\n    pub fn mint_asset_id(&self) -> &AssetId {\n        self.tx.mint_asset_id()\n    }\n\n    #[must_use]\n    pub fn mint_amount(&self) -> u64 {\n        *self.tx.mint_amount()\n    }\n}\n\n#[derive(Default, Debug, Copy, Clone)]\n// ANCHOR: tx_policies_struct\npub struct TxPolicies {\n    tip: Option<u64>,\n    witness_limit: Option<u64>,\n    maturity: Option<u64>,\n    expiration: Option<u64>,\n    max_fee: Option<u64>,\n    script_gas_limit: Option<u64>,\n    owner: Option<u64>,\n}\n// ANCHOR_END: tx_policies_struct\n\nimpl TxPolicies {\n    pub fn new(\n        tip: Option<u64>,\n        witness_limit: Option<u64>,\n        maturity: Option<u64>,\n        expiration: Option<u64>,\n        max_fee: Option<u64>,\n        script_gas_limit: Option<u64>,\n        owner: Option<u64>,\n    ) -> Self {\n        Self {\n            tip,\n            witness_limit,\n            maturity,\n            expiration,\n            max_fee,\n            script_gas_limit,\n            owner,\n        }\n    }\n\n    pub fn with_tip(mut self, tip: u64) -> Self {\n        self.tip = Some(tip);\n        self\n    }\n\n    pub fn tip(&self) -> Option<u64> {\n        self.tip\n    }\n\n    pub fn with_witness_limit(mut self, witness_limit: u64) -> Self {\n        self.witness_limit = Some(witness_limit);\n        self\n    }\n\n    pub fn witness_limit(&self) -> Option<u64> {\n        self.witness_limit\n    }\n\n    pub fn with_maturity(mut self, maturity: u64) -> Self {\n        self.maturity = Some(maturity);\n        self\n    }\n\n    pub fn maturity(&self) -> Option<u64> {\n        self.maturity\n    }\n\n    pub fn with_expiration(mut self, expiration: u64) -> Self {\n        self.expiration = Some(expiration);\n        self\n    }\n\n    pub fn expiration(&self) -> Option<u64> {\n        self.expiration\n    }\n\n    pub fn with_max_fee(mut self, max_fee: u64) -> Self {\n        self.max_fee = Some(max_fee);\n        self\n    }\n\n    pub fn max_fee(&self) -> Option<u64> {\n        self.max_fee\n    }\n\n    pub fn with_script_gas_limit(mut self, script_gas_limit: u64) -> Self {\n        self.script_gas_limit = Some(script_gas_limit);\n        self\n    }\n\n    pub fn script_gas_limit(&self) -> Option<u64> {\n        self.script_gas_limit\n    }\n\n    pub fn with_owner(mut self, owner: u64) -> Self {\n        self.owner = Some(owner);\n        self\n    }\n\n    pub fn owner(&self) -> Option<u64> {\n        self.owner\n    }\n}\n\nuse fuel_tx::field::{BytecodeWitnessIndex, Salt, StorageSlots};\n\nuse crate::types::coin_type_id::CoinTypeId;\n\n#[derive(Debug, Clone)]\npub enum TransactionType {\n    Script(ScriptTransaction),\n    Create(CreateTransaction),\n    Mint(MintTransaction),\n    Upload(UploadTransaction),\n    Upgrade(UpgradeTransaction),\n    Blob(BlobTransaction),\n    Unknown,\n}\n\n#[cfg_attr(target_arch = \"wasm32\", async_trait(?Send))]\n#[cfg_attr(not(target_arch = \"wasm32\"), async_trait)]\npub trait EstimablePredicates: sealed::Sealed {\n    /// If a transaction contains predicates, we have to estimate them\n    /// before sending the transaction to the node. The estimation will check\n    /// all predicates and set the `predicate_gas_used` to the actual consumed gas.\n    async fn estimate_predicates(\n        &mut self,\n        provider: impl DryRunner,\n        latest_chain_executor_version: Option<u32>,\n    ) -> Result<()>;\n}\n\npub trait ValidatablePredicates: sealed::Sealed {\n    /// If a transaction contains predicates, we can verify that these predicates validate, ie\n    /// that they return `true`\n    fn validate_predicates(\n        self,\n        consensus_parameters: &ConsensusParameters,\n        block_height: u32,\n    ) -> Result<()>;\n}\n\n#[cfg_attr(target_arch = \"wasm32\", async_trait(?Send))]\n#[cfg_attr(not(target_arch = \"wasm32\"), async_trait)]\npub trait Transaction:\n    TryFrom<FuelTransaction, Error = Error>\n    + Into<FuelTransaction>\n    + EstimablePredicates\n    + ValidatablePredicates\n    + Clone\n    + Debug\n    + sealed::Sealed\n{\n    fn fee_checked_from_tx(\n        &self,\n        consensus_parameters: &ConsensusParameters,\n        gas_price: u64,\n    ) -> Option<TransactionFee>;\n\n    fn max_gas(&self, consensus_parameters: &ConsensusParameters) -> u64;\n\n    /// Performs all stateless transaction validity checks. This includes the validity\n    /// of fields according to rules in the specification and validity of signatures.\n    /// <https://github.com/FuelLabs/fuel-specs/blob/master/src/tx-format/transaction.md>\n    fn check(&self, block_height: u32, consensus_parameters: &ConsensusParameters) -> Result<()>;\n\n    fn id(&self, chain_id: ChainId) -> Bytes32;\n\n    fn maturity(&self) -> Option<u64>;\n\n    fn expiration(&self) -> Option<u64>;\n\n    fn owner(&self) -> Option<u64>;\n\n    fn metered_bytes_size(&self) -> usize;\n\n    fn inputs(&self) -> &Vec<Input>;\n\n    fn outputs(&self) -> &Vec<Output>;\n\n    fn witnesses(&self) -> &Vec<Witness>;\n\n    fn max_fee(&self) -> Option<u64>;\n\n    fn size(&self) -> usize;\n\n    fn witness_limit(&self) -> Option<u64>;\n\n    fn tip(&self) -> Option<u64>;\n\n    fn is_using_predicates(&self) -> bool;\n\n    /// Precompute transaction metadata. The metadata is required for\n    /// `check_without_signatures` validation.\n    fn precompute(&mut self, chain_id: &ChainId) -> Result<()>;\n\n    /// Append witness and return the corresponding witness index\n    fn append_witness(&mut self, witness: Witness) -> Result<usize>;\n\n    fn used_coins(&self, base_asset_id: &AssetId) -> HashMap<(Address, AssetId), Vec<CoinTypeId>>;\n\n    async fn sign_with(\n        &mut self,\n        signer: &(impl Signer + Send + Sync),\n        chain_id: ChainId,\n    ) -> Result<Signature>;\n}\n\nimpl TryFrom<TransactionType> for FuelTransaction {\n    type Error = Error;\n    fn try_from(value: TransactionType) -> Result<Self> {\n        match value {\n            TransactionType::Script(tx) => Ok(tx.into()),\n            TransactionType::Create(tx) => Ok(tx.into()),\n            TransactionType::Mint(tx) => Ok(tx.into()),\n            TransactionType::Upload(tx) => Ok(tx.into()),\n            TransactionType::Upgrade(tx) => Ok(tx.into()),\n            TransactionType::Blob(tx) => Ok(tx.into()),\n            TransactionType::Unknown => Err(error_transaction!(Other, \"`Unknown` transaction\")),\n        }\n    }\n}\n\nfn extract_coin_type_id(input: &Input) -> Option<CoinTypeId> {\n    if let Some(utxo_id) = input.utxo_id() {\n        return Some(CoinTypeId::UtxoId(*utxo_id));\n    } else if let Some(nonce) = input.nonce() {\n        return Some(CoinTypeId::Nonce(*nonce));\n    }\n\n    None\n}\n\npub fn extract_owner_or_recipient(input: &Input) -> Option<Address> {\n    match input {\n        Input::CoinSigned(CoinSigned { owner, .. })\n        | Input::CoinPredicate(CoinPredicate { owner, .. }) => Some(*owner),\n        Input::MessageCoinSigned(MessageCoinSigned { recipient, .. })\n        | Input::MessageCoinPredicate(MessageCoinPredicate { recipient, .. })\n        | Input::MessageDataSigned(MessageDataSigned { recipient, .. })\n        | Input::MessageDataPredicate(MessageDataPredicate { recipient, .. }) => Some(*recipient),\n        Input::Contract(_) => None,\n    }\n}\n\nmacro_rules! impl_tx_wrapper {\n    ($wrapper: ident, $wrapped: ident) => {\n        #[derive(Debug, Clone)]\n        pub struct $wrapper {\n            pub(crate) tx: $wrapped,\n            pub(crate) is_using_predicates: bool,\n        }\n\n        impl From<$wrapper> for $wrapped {\n            fn from(tx: $wrapper) -> Self {\n                tx.tx\n            }\n        }\n\n        impl From<$wrapper> for FuelTransaction {\n            fn from(tx: $wrapper) -> Self {\n                tx.tx.into()\n            }\n        }\n\n        impl TryFrom<FuelTransaction> for $wrapper {\n            type Error = Error;\n\n            fn try_from(tx: FuelTransaction) -> Result<Self> {\n                match tx {\n                    FuelTransaction::$wrapped(tx) => Ok(tx.into()),\n                    _ => Err(error_transaction!(\n                        Other,\n                        \"couldn't convert Transaction into a wrapper of type $wrapper\"\n                    )),\n                }\n            }\n        }\n\n        impl From<$wrapped> for $wrapper {\n            fn from(tx: $wrapped) -> Self {\n                let is_using_predicates = tx.inputs().iter().any(|input| {\n                    matches!(\n                        input,\n                        Input::CoinPredicate { .. }\n                            | Input::MessageCoinPredicate { .. }\n                            | Input::MessageDataPredicate { .. }\n                    )\n                });\n\n                $wrapper {\n                    tx,\n                    is_using_predicates,\n                }\n            }\n        }\n\n        impl ValidatablePredicates for $wrapper {\n            fn validate_predicates(\n                self,\n                _consensus_parameters: &ConsensusParameters,\n                _block_height: u32,\n            ) -> Result<()> {\n                // Can no longer validate predicates locally due to the need for blob storage\n\n                Ok(())\n            }\n        }\n\n        impl sealed::Sealed for $wrapper {}\n\n        #[cfg_attr(target_arch = \"wasm32\", async_trait(?Send))]\n        #[cfg_attr(not(target_arch = \"wasm32\"), async_trait)]\n        impl Transaction for $wrapper {\n            fn max_gas(&self, consensus_parameters: &ConsensusParameters) -> u64 {\n                self.tx.max_gas(\n                    consensus_parameters.gas_costs(),\n                    consensus_parameters.fee_params(),\n                )\n            }\n\n            fn fee_checked_from_tx(\n                &self,\n                consensus_parameters: &ConsensusParameters,\n                gas_price: u64,\n            ) -> Option<TransactionFee> {\n                TransactionFee::checked_from_tx(\n                    &consensus_parameters.gas_costs(),\n                    consensus_parameters.fee_params(),\n                    &self.tx,\n                    gas_price,\n                )\n            }\n\n            fn check(\n                &self,\n                block_height: u32,\n                consensus_parameters: &ConsensusParameters,\n            ) -> Result<()> {\n                Ok(self.tx.check(block_height.into(), consensus_parameters)?)\n            }\n\n            fn id(&self, chain_id: ChainId) -> Bytes32 {\n                self.tx.id(&chain_id)\n            }\n\n            fn maturity(&self) -> Option<u64> {\n                self.tx.policies().get(PolicyType::Maturity)\n            }\n\n            fn expiration(&self) -> Option<u64> {\n                self.tx.policies().get(PolicyType::Expiration)\n            }\n\n            fn owner(&self) -> Option<u64> {\n                self.tx.policies().get(PolicyType::Owner)\n            }\n\n            fn metered_bytes_size(&self) -> usize {\n                self.tx.metered_bytes_size()\n            }\n\n            fn inputs(&self) -> &Vec<Input> {\n                self.tx.inputs()\n            }\n\n            fn outputs(&self) -> &Vec<Output> {\n                self.tx.outputs()\n            }\n\n            fn witnesses(&self) -> &Vec<Witness> {\n                self.tx.witnesses()\n            }\n\n            fn is_using_predicates(&self) -> bool {\n                self.is_using_predicates\n            }\n\n            fn precompute(&mut self, chain_id: &ChainId) -> Result<()> {\n                Ok(self.tx.precompute(chain_id)?)\n            }\n\n            fn max_fee(&self) -> Option<u64> {\n                self.tx.policies().get(PolicyType::MaxFee)\n            }\n\n            fn size(&self) -> usize {\n                use fuel_types::canonical::Serialize;\n                self.tx.size()\n            }\n\n            fn witness_limit(&self) -> Option<u64> {\n                self.tx.policies().get(PolicyType::WitnessLimit)\n            }\n\n            fn tip(&self) -> Option<u64> {\n                self.tx.policies().get(PolicyType::Tip)\n            }\n\n            fn append_witness(&mut self, witness: Witness) -> Result<usize> {\n                let witness_size = calculate_witnesses_size(\n                    self.tx.witnesses().iter().chain(std::iter::once(&witness)),\n                );\n                let new_witnesses_size = padded_len_usize(witness_size)\n                    .ok_or_else(|| error!(Other, \"witness size overflow: {witness_size}\"))?\n                    as u64;\n\n                if new_witnesses_size > self.tx.witness_limit() {\n                    Err(error_transaction!(\n                        Validation,\n                        \"Witness limit exceeded. Consider setting the limit manually with \\\n                        a transaction builder. The new limit should be: `{new_witnesses_size}`\"\n                    ))\n                } else {\n                    let idx = self.tx.witnesses().len();\n                    self.tx.witnesses_mut().push(witness);\n\n                    Ok(idx)\n                }\n            }\n\n            fn used_coins(\n                &self,\n                base_asset_id: &AssetId,\n            ) -> HashMap<(Address, AssetId), Vec<CoinTypeId>> {\n                self.inputs()\n                    .iter()\n                    .filter_map(|input| match input {\n                        Input::Contract { .. } => None,\n                        _ => {\n                            // Not a contract, it's safe to expect.\n                            let owner = extract_owner_or_recipient(input).expect(\"has owner\");\n                            let asset_id = input\n                                .asset_id(base_asset_id)\n                                .expect(\"has `asset_id`\")\n                                .to_owned();\n\n                            let id = extract_coin_type_id(input).unwrap();\n                            Some(((owner, asset_id), id))\n                        }\n                    })\n                    .into_group_map()\n            }\n\n            async fn sign_with(\n                &mut self,\n                signer: &(impl Signer + Send + Sync),\n                chain_id: ChainId,\n            ) -> Result<Signature> {\n                let tx_id = self.id(chain_id);\n                let message = Message::from_bytes(*tx_id);\n                let signature = signer.sign(message).await?;\n\n                self.append_witness(signature.as_ref().into())?;\n\n                Ok(signature)\n            }\n        }\n    };\n}\n\nimpl_tx_wrapper!(ScriptTransaction, Script);\nimpl_tx_wrapper!(CreateTransaction, Create);\nimpl_tx_wrapper!(UploadTransaction, Upload);\nimpl_tx_wrapper!(UpgradeTransaction, Upgrade);\nimpl_tx_wrapper!(BlobTransaction, Blob);\n\n#[cfg_attr(target_arch = \"wasm32\", async_trait(?Send))]\n#[cfg_attr(not(target_arch = \"wasm32\"), async_trait)]\nimpl EstimablePredicates for UploadTransaction {\n    async fn estimate_predicates(\n        &mut self,\n        provider: impl DryRunner,\n        latest_chain_executor_version: Option<u32>,\n    ) -> Result<()> {\n        let tx = provider\n            .estimate_predicates(&self.tx.clone().into(), latest_chain_executor_version)\n            .await?;\n\n        tx.as_upload().expect(\"is upload\").clone_into(&mut self.tx);\n\n        Ok(())\n    }\n}\n\n#[cfg_attr(target_arch = \"wasm32\", async_trait(?Send))]\n#[cfg_attr(not(target_arch = \"wasm32\"), async_trait)]\nimpl EstimablePredicates for UpgradeTransaction {\n    async fn estimate_predicates(\n        &mut self,\n        provider: impl DryRunner,\n        latest_chain_executor_version: Option<u32>,\n    ) -> Result<()> {\n        let tx = provider\n            .estimate_predicates(&self.tx.clone().into(), latest_chain_executor_version)\n            .await?;\n\n        tx.as_upgrade()\n            .expect(\"is upgrade\")\n            .clone_into(&mut self.tx);\n\n        Ok(())\n    }\n}\n\n#[cfg_attr(target_arch = \"wasm32\", async_trait(?Send))]\n#[cfg_attr(not(target_arch = \"wasm32\"), async_trait)]\nimpl EstimablePredicates for CreateTransaction {\n    async fn estimate_predicates(\n        &mut self,\n        provider: impl DryRunner,\n        latest_chain_executor_version: Option<u32>,\n    ) -> Result<()> {\n        let tx = provider\n            .estimate_predicates(&self.tx.clone().into(), latest_chain_executor_version)\n            .await?;\n\n        tx.as_create().expect(\"is create\").clone_into(&mut self.tx);\n\n        Ok(())\n    }\n}\n\nimpl CreateTransaction {\n    pub fn salt(&self) -> &FuelSalt {\n        self.tx.salt()\n    }\n\n    pub fn bytecode_witness_index(&self) -> u16 {\n        *self.tx.bytecode_witness_index()\n    }\n\n    pub fn storage_slots(&self) -> &Vec<StorageSlot> {\n        self.tx.storage_slots()\n    }\n}\n\n#[cfg_attr(target_arch = \"wasm32\", async_trait(?Send))]\n#[cfg_attr(not(target_arch = \"wasm32\"), async_trait)]\nimpl EstimablePredicates for ScriptTransaction {\n    async fn estimate_predicates(\n        &mut self,\n        provider: impl DryRunner,\n        latest_chain_executor_version: Option<u32>,\n    ) -> Result<()> {\n        let tx = provider\n            .estimate_predicates(&self.tx.clone().into(), latest_chain_executor_version)\n            .await?;\n\n        tx.as_script().expect(\"is script\").clone_into(&mut self.tx);\n\n        Ok(())\n    }\n}\n\n#[cfg_attr(target_arch = \"wasm32\", async_trait(?Send))]\n#[cfg_attr(not(target_arch = \"wasm32\"), async_trait)]\nimpl EstimablePredicates for BlobTransaction {\n    async fn estimate_predicates(\n        &mut self,\n        provider: impl DryRunner,\n        latest_chain_executor_version: Option<u32>,\n    ) -> Result<()> {\n        let tx = provider\n            .estimate_predicates(&self.tx.clone().into(), latest_chain_executor_version)\n            .await?;\n\n        tx.as_blob().expect(\"is blob\").clone_into(&mut self.tx);\n\n        Ok(())\n    }\n}\n\nimpl ScriptTransaction {\n    pub fn script(&self) -> &Vec<u8> {\n        self.tx.script()\n    }\n\n    pub fn script_data(&self) -> &Vec<u8> {\n        self.tx.script_data()\n    }\n\n    pub fn gas_limit(&self) -> u64 {\n        *self.tx.script_gas_limit()\n    }\n\n    pub fn with_gas_limit(mut self, gas_limit: u64) -> Self {\n        *self.tx.script_gas_limit_mut() = gas_limit;\n        self\n    }\n}\n\n#[cfg(test)]\nmod test {\n\n    use fuel_tx::policies::Policies;\n\n    use super::*;\n\n    #[test]\n    fn append_witnesses_returns_error_when_limit_exceeded() {\n        let mut tx = ScriptTransaction {\n            tx: FuelTransaction::script(\n                0,\n                vec![],\n                vec![],\n                Policies::default(),\n                vec![],\n                vec![],\n                vec![],\n            ),\n            is_using_predicates: false,\n        };\n\n        let witness = vec![0, 1, 2].into();\n        let err = tx.append_witness(witness).expect_err(\"should error\");\n\n        let expected_err_str = \"transaction validation: Witness limit exceeded. \\\n                                Consider setting the limit manually with a transaction builder. \\\n                                The new limit should be: `16`\";\n\n        assert_eq!(&err.to_string(), expected_err_str);\n    }\n}\n"
  },
  {
    "path": "packages/fuels-core/src/types/wrappers/transaction_response.rs",
    "content": "#![cfg(feature = \"std\")]\n\nuse chrono::{DateTime, Utc};\nuse fuel_core_client::client::types::{\n    TransactionResponse as ClientTransactionResponse, TransactionStatus as ClientTransactionStatus,\n    TransactionType as ClientTxType,\n};\nuse fuel_tx::Transaction;\nuse fuel_types::BlockHeight;\n\nuse crate::types::{transaction::TransactionType, tx_status::TxStatus};\n\n#[derive(Debug, Clone)]\npub struct TransactionResponse {\n    pub transaction: TransactionType,\n    pub status: TxStatus,\n    pub block_height: Option<BlockHeight>,\n    pub time: Option<DateTime<Utc>>,\n}\n\nimpl From<ClientTransactionResponse> for TransactionResponse {\n    fn from(client_response: ClientTransactionResponse) -> Self {\n        let block_height = match &client_response.status {\n            ClientTransactionStatus::Submitted { .. }\n            | ClientTransactionStatus::SqueezedOut { .. }\n            | ClientTransactionStatus::PreconfirmationSuccess { .. }\n            | ClientTransactionStatus::PreconfirmationFailure { .. } => None,\n            ClientTransactionStatus::Success { block_height, .. }\n            | ClientTransactionStatus::Failure { block_height, .. } => Some(*block_height),\n        };\n\n        let time = match &client_response.status {\n            ClientTransactionStatus::Submitted { .. }\n            | ClientTransactionStatus::SqueezedOut { .. }\n            | ClientTransactionStatus::PreconfirmationSuccess { .. }\n            | ClientTransactionStatus::PreconfirmationFailure { .. } => None,\n            ClientTransactionStatus::Success { time, .. }\n            | ClientTransactionStatus::Failure { time, .. } => {\n                DateTime::from_timestamp(time.to_unix(), 0)\n            }\n        };\n\n        let transaction = match client_response.transaction {\n            ClientTxType::Known(Transaction::Script(tx)) => TransactionType::Script(tx.into()),\n            ClientTxType::Known(Transaction::Create(tx)) => TransactionType::Create(tx.into()),\n            ClientTxType::Known(Transaction::Mint(tx)) => TransactionType::Mint(tx.into()),\n            ClientTxType::Known(Transaction::Upgrade(tx)) => TransactionType::Upgrade(tx.into()),\n            ClientTxType::Known(Transaction::Upload(tx)) => TransactionType::Upload(tx.into()),\n            ClientTxType::Known(Transaction::Blob(tx)) => TransactionType::Blob(tx.into()),\n            ClientTxType::Unknown => TransactionType::Unknown,\n        };\n\n        Self {\n            transaction,\n            status: client_response.status.into(),\n            block_height,\n            time,\n        }\n    }\n}\n"
  },
  {
    "path": "packages/fuels-core/src/types/wrappers.rs",
    "content": "pub mod block;\npub mod chain_info;\npub mod coin;\npub mod coin_type;\npub mod coin_type_id;\npub mod input;\npub mod message;\npub mod message_proof;\npub mod node_info;\npub mod transaction;\npub mod transaction_response;\npub mod output {\n    pub use fuel_tx::Output;\n}\n#[cfg(feature = \"std\")]\npub mod gas_price {\n    pub use fuel_core_client::client::types::gas_price::{EstimateGasPrice, LatestGasPrice};\n}\n"
  },
  {
    "path": "packages/fuels-core/src/types.rs",
    "content": "use fuel_types::bytes::padded_len;\npub use fuel_types::{\n    Address, AssetId, BlockHeight, Bytes4, Bytes8, Bytes32, Bytes64, ChainId, ContractId,\n    MessageId, Nonce, Salt, SubAssetId, Word,\n};\n\npub use crate::types::{core::*, method_descriptor::*, token::*, wrappers::*};\nuse crate::{error, types::errors::Result};\n\nmod core;\nmod dry_runner;\npub mod errors;\npub mod param_types;\nmod token;\npub mod transaction_builders;\npub mod tx_response;\npub mod tx_status;\nmod wrappers;\npub use dry_runner::*;\npub mod checksum_address;\npub mod method_descriptor;\n\npub type ByteArray = [u8; 8];\npub type Selector = Vec<u8>;\n\n/// Converts a u16 to a right aligned array of 8 bytes.\npub fn pad_u16(value: u16) -> ByteArray {\n    let mut padded = ByteArray::default();\n    padded[6..].copy_from_slice(&value.to_be_bytes());\n    padded\n}\n\n/// Converts a u32 to a right aligned array of 8 bytes.\npub fn pad_u32(value: u32) -> ByteArray {\n    let mut padded = [0u8; 8];\n    padded[4..].copy_from_slice(&value.to_be_bytes());\n    padded\n}\n\npub fn pad_string(s: &str) -> Result<Vec<u8>> {\n    let padded_len =\n        padded_len(s.as_bytes()).ok_or_else(|| error!(Codec, \"string is too long to be padded\"))?;\n    let pad = padded_len - s.len();\n\n    let mut padded = s.as_bytes().to_owned();\n\n    padded.extend_from_slice(&vec![0; pad]);\n\n    Ok(padded)\n}\n"
  },
  {
    "path": "packages/fuels-core/src/utils/constants.rs",
    "content": "use fuel_tx::Word;\n\npub const ENUM_DISCRIMINANT_BYTE_WIDTH: usize = 8;\npub const WORD_SIZE: usize = core::mem::size_of::<Word>();\n\n// ANCHOR: default_call_parameters\npub const DEFAULT_CALL_PARAMS_AMOUNT: u64 = 0;\n// ANCHOR_END: default_call_parameters\n\npub const DEFAULT_GAS_ESTIMATION_TOLERANCE: f64 = 0.2;\npub const DEFAULT_GAS_ESTIMATION_BLOCK_HORIZON: u32 = 5;\n\n// The size of a signature inside a transaction `Witness`\npub const WITNESS_STATIC_SIZE: usize = 8;\nconst SIGNATURE_SIZE: usize = 64;\npub const SIGNATURE_WITNESS_SIZE: usize = WITNESS_STATIC_SIZE + SIGNATURE_SIZE;\n"
  },
  {
    "path": "packages/fuels-core/src/utils/offsets.rs",
    "content": "use fuel_asm::Instruction;\nuse fuel_tx::{ConsensusParameters, field::Script};\nuse fuel_types::bytes::padded_len_usize;\n\nuse crate::{error, types::errors::Result};\n\n/// Gets the base offset for a script or a predicate. The offset depends on the `max_inputs`\n/// field of the `ConsensusParameters` and the static offset.\npub fn base_offset_script(consensus_parameters: &ConsensusParameters) -> usize {\n    consensus_parameters.tx_params().tx_offset() + fuel_tx::Script::script_offset_static()\n}\n\n/// Calculates the length of the script based on the number of contract calls it\n/// has to make and returns the offset at which the script data begins\npub fn call_script_data_offset(\n    consensus_parameters: &ConsensusParameters,\n    calls_instructions_len: usize,\n) -> Result<usize> {\n    // Instruction::SIZE is a placeholder for the RET instruction which is added later for returning\n    // from the script. This doesn't happen in the predicate.\n    let opcode_len = Instruction::SIZE;\n\n    let padded_len = padded_len_usize(calls_instructions_len + opcode_len).ok_or_else(|| {\n        error!(\n            Other,\n            \"call script data len overflow: {calls_instructions_len}\"\n        )\n    })?;\n    Ok(base_offset_script(consensus_parameters) + padded_len)\n}\n"
  },
  {
    "path": "packages/fuels-core/src/utils.rs",
    "content": "pub mod constants;\npub mod offsets;\n\nuse constants::{WITNESS_STATIC_SIZE, WORD_SIZE};\nuse fuel_tx::Witness;\n\nuse crate::{error, types::errors::Result};\n\npub fn checked_round_up_to_word_alignment(bytes_len: usize) -> Result<usize> {\n    let lhs = bytes_len.checked_add(WORD_SIZE - 1).ok_or_else(|| {\n        error!(\n            Codec,\n            \"addition overflow while rounding up {bytes_len} bytes to word alignment\"\n        )\n    })?;\n    let rhs = lhs.checked_rem(WORD_SIZE).ok_or_else(|| {\n        error!(\n            Codec,\n            \"remainder overflow while rounding up {bytes_len} bytes to word alignment\"\n        )\n    })?;\n    lhs.checked_sub(rhs).ok_or_else(|| {\n        error!(\n            Codec,\n            \"subtraction overflow while rounding up {bytes_len} bytes to word alignment\"\n        )\n    })\n}\npub(crate) fn calculate_witnesses_size<'a, I: IntoIterator<Item = &'a Witness>>(\n    witnesses: I,\n) -> usize {\n    witnesses\n        .into_iter()\n        .map(|w| w.as_ref().len() + WITNESS_STATIC_SIZE)\n        .sum()\n}\n\npub(crate) mod sealed {\n    pub trait Sealed {}\n}\n\n#[cfg(test)]\npub(crate) fn to_named<'a, I: IntoIterator<Item = &'a crate::types::param_types::ParamType>>(\n    param_types: I,\n) -> Vec<(String, crate::types::param_types::ParamType)> {\n    param_types\n        .into_iter()\n        .map(|pt| (\"\".to_string(), pt.clone()))\n        .collect()\n}\n"
  },
  {
    "path": "packages/fuels-macros/.gitignore",
    "content": "# This folder is generated whenever a UI test fails, so we don't want to track its content.\nwip/*\n"
  },
  {
    "path": "packages/fuels-macros/Cargo.toml",
    "content": "[package]\nname = \"fuels-macros\"\nversion = { workspace = true }\nauthors = { workspace = true }\nedition = { workspace = true }\nhomepage = { workspace = true }\nlicense = { workspace = true }\nrepository = { workspace = true }\nrust-version = { workspace = true }\ndescription = \"Fuel Rust SDK macros to generate types from ABI.\"\n\n[lib]\nproc-macro = true\n\n[dependencies]\nfuels-code-gen = { workspace = true }\nitertools = { workspace = true }\nproc-macro2 = { workspace = true }\nquote = { workspace = true }\nsyn = { workspace = true, features = [\"extra-traits\"] }\n\n[dev-dependencies]\ntrybuild = { workspace = true }\n\n"
  },
  {
    "path": "packages/fuels-macros/src/abigen/parsing.rs",
    "content": "use fuels_code_gen::{Abi, AbigenTarget, ProgramType};\nuse syn::{\n    LitStr, Result,\n    parse::{Parse, ParseStream},\n};\n\nuse crate::parse_utils::{Command, UniqueNameValues};\n\nimpl From<MacroAbigenTargets> for Vec<AbigenTarget> {\n    fn from(targets: MacroAbigenTargets) -> Self {\n        targets.targets.into_iter().map(Into::into).collect()\n    }\n}\n\nimpl From<MacroAbigenTarget> for AbigenTarget {\n    fn from(macro_target: MacroAbigenTarget) -> Self {\n        AbigenTarget::new(\n            macro_target.name,\n            macro_target.source,\n            macro_target.program_type,\n        )\n    }\n}\n\n// Although identical to `AbigenTarget` from fuels-core, due to the orphan rule\n// we cannot implement Parse for the latter.\n#[derive(Debug)]\npub(crate) struct MacroAbigenTarget {\n    pub(crate) name: String,\n    pub(crate) source: Abi,\n    pub program_type: ProgramType,\n}\n\npub(crate) struct MacroAbigenTargets {\n    targets: Vec<MacroAbigenTarget>,\n}\n\nimpl Parse for MacroAbigenTargets {\n    fn parse(input: ParseStream) -> Result<Self> {\n        let targets = Command::parse_multiple(input)?\n            .into_iter()\n            .map(MacroAbigenTarget::new)\n            .collect::<Result<_>>()?;\n\n        Ok(Self { targets })\n    }\n}\n\nimpl MacroAbigenTarget {\n    pub fn new(command: Command) -> Result<Self> {\n        let program_type = command.name.try_into()?;\n\n        let name_values = UniqueNameValues::new(command.contents)?;\n        name_values.validate_has_no_other_names(&[\"name\", \"abi\"])?;\n\n        let name = name_values.get_as_lit_str(\"name\")?.value();\n        let abi_lit_str = name_values.get_as_lit_str(\"abi\")?;\n        let source = Self::parse_inline_or_load_abi(abi_lit_str)?;\n\n        Ok(Self {\n            name,\n            source,\n            program_type,\n        })\n    }\n\n    fn parse_inline_or_load_abi(abi_lit_str: &LitStr) -> Result<Abi> {\n        let abi_string = abi_lit_str.value();\n        let abi_str = abi_string.trim();\n\n        if abi_str.starts_with('{') || abi_str.starts_with('[') || abi_str.starts_with('\\n') {\n            abi_str.parse()\n        } else {\n            Abi::load_from(abi_str)\n        }\n        .map_err(|e| syn::Error::new(abi_lit_str.span(), e.to_string()))\n    }\n}\n"
  },
  {
    "path": "packages/fuels-macros/src/abigen.rs",
    "content": "pub(crate) use parsing::MacroAbigenTargets;\n\nmod parsing;\n"
  },
  {
    "path": "packages/fuels-macros/src/derive/parameterize.rs",
    "content": "use proc_macro2::{Ident, TokenStream};\nuse quote::quote;\nuse syn::{Data, DataEnum, DataStruct, DeriveInput, Error, Generics, Result};\n\nuse crate::{\n    derive::utils::{find_attr, get_path_from_attr_or, std_lib_path},\n    parse_utils::{Members, validate_and_extract_generic_types},\n};\n\npub fn generate_parameterize_impl(input: DeriveInput) -> Result<TokenStream> {\n    let fuels_types_path =\n        get_path_from_attr_or(\"FuelsTypesPath\", &input.attrs, quote! {::fuels::types})?;\n    let fuels_core_path =\n        get_path_from_attr_or(\"FuelsCorePath\", &input.attrs, quote! {::fuels::core})?;\n    let no_std = find_attr(\"NoStd\", &input.attrs).is_some();\n\n    match input.data {\n        Data::Struct(struct_contents) => parameterize_for_struct(\n            input.ident,\n            input.generics,\n            struct_contents,\n            fuels_types_path,\n            fuels_core_path,\n            no_std,\n        ),\n        Data::Enum(enum_contents) => parameterize_for_enum(\n            input.ident,\n            input.generics,\n            enum_contents,\n            fuels_types_path,\n            fuels_core_path,\n            no_std,\n        ),\n        _ => Err(Error::new_spanned(input, \"union type is not supported\")),\n    }\n}\n\nfn parameterize_for_struct(\n    name: Ident,\n    generics: Generics,\n    contents: DataStruct,\n    fuels_types_path: TokenStream,\n    fuels_core_path: TokenStream,\n    no_std: bool,\n) -> Result<TokenStream> {\n    let (impl_gen, type_gen, where_clause) = generics.split_for_impl();\n    let name_stringified = name.to_string();\n    let members = Members::from_struct(contents, fuels_core_path.clone())?;\n    let field_names = members.names_as_strings();\n    let param_type_calls = members.param_type_calls();\n    let generic_param_types = parameterize_generic_params(&generics, &fuels_core_path)?;\n\n    let std_lib = std_lib_path(no_std);\n\n    Ok(quote! {\n        impl #impl_gen #fuels_core_path::traits::Parameterize for #name #type_gen #where_clause {\n            fn param_type() -> #fuels_types_path::param_types::ParamType {\n                #fuels_types_path::param_types::ParamType::Struct{\n                    name: #std_lib::string::String::from(#name_stringified),\n                    fields: #std_lib::vec![#((#field_names, #param_type_calls)),*],\n                    generics: #std_lib::vec![#(#generic_param_types),*],\n                }\n            }\n        }\n    })\n}\n\nfn parameterize_generic_params(\n    generics: &Generics,\n    fuels_core_path: &TokenStream,\n) -> Result<Vec<TokenStream>> {\n    let parameterize_calls = validate_and_extract_generic_types(generics)?\n        .into_iter()\n        .map(|type_param| {\n            let ident = &type_param.ident;\n            quote! {<#ident as #fuels_core_path::traits::Parameterize>::param_type()}\n        })\n        .collect();\n\n    Ok(parameterize_calls)\n}\n\nfn parameterize_for_enum(\n    name: Ident,\n    generics: Generics,\n    contents: DataEnum,\n    fuels_types_path: TokenStream,\n    fuels_core_path: TokenStream,\n    no_std: bool,\n) -> Result<TokenStream> {\n    let (impl_gen, type_gen, where_clause) = generics.split_for_impl();\n    let enum_name_str = name.to_string();\n    let members = Members::from_enum(contents, fuels_core_path.clone())?;\n\n    let variant_names = members.names_as_strings();\n    let variant_param_types = members.param_type_calls();\n    let generic_param_types = parameterize_generic_params(&generics, &fuels_core_path)?;\n\n    let std_lib = std_lib_path(no_std);\n\n    Ok(quote! {\n        impl #impl_gen #fuels_core_path::traits::Parameterize for #name #type_gen #where_clause {\n            fn param_type() -> #fuels_types_path::param_types::ParamType {\n                let variants = #std_lib::vec![#((#variant_names, #variant_param_types)),*];\n                let enum_variants = #fuels_types_path::param_types::EnumVariants::new(variants)\n                    .unwrap_or_else(|_| ::std::panic!(\n                            \"{} has no variants which isn't allowed\",\n                            #enum_name_str\n                        )\n                    );\n\n                #fuels_types_path::param_types::ParamType::Enum {\n                    name: #std_lib::string::String::from(#enum_name_str),\n                    enum_variants,\n                    generics: #std_lib::vec![#(#generic_param_types),*]\n                }\n            }\n        }\n    })\n}\n"
  },
  {
    "path": "packages/fuels-macros/src/derive/tokenizable.rs",
    "content": "use itertools::Itertools;\nuse proc_macro2::{Ident, TokenStream};\nuse quote::quote;\nuse syn::{Data, DataEnum, DataStruct, DeriveInput, Error, Generics, Result};\n\nuse crate::{\n    derive::{\n        utils,\n        utils::{find_attr, get_path_from_attr_or, std_lib_path},\n    },\n    parse_utils::{Members, validate_and_extract_generic_types},\n};\n\npub fn generate_tokenizable_impl(input: DeriveInput) -> Result<TokenStream> {\n    let fuels_types_path =\n        get_path_from_attr_or(\"FuelsTypesPath\", &input.attrs, quote! {::fuels::types})?;\n    let fuels_core_path =\n        get_path_from_attr_or(\"FuelsCorePath\", &input.attrs, quote! {::fuels::core})?;\n    let no_std = find_attr(\"NoStd\", &input.attrs).is_some();\n\n    match input.data {\n        Data::Struct(struct_contents) => tokenizable_for_struct(\n            input.ident,\n            input.generics,\n            struct_contents,\n            fuels_types_path,\n            fuels_core_path,\n            no_std,\n        ),\n        Data::Enum(enum_contents) => tokenizable_for_enum(\n            input.ident,\n            input.generics,\n            enum_contents,\n            fuels_types_path,\n            fuels_core_path,\n            no_std,\n        ),\n        _ => Err(Error::new_spanned(input, \"Union type is not supported\")),\n    }\n}\n\nfn tokenizable_for_struct(\n    name: Ident,\n    generics: Generics,\n    contents: DataStruct,\n    fuels_types_path: TokenStream,\n    fuels_core_path: TokenStream,\n    no_std: bool,\n) -> Result<TokenStream> {\n    validate_and_extract_generic_types(&generics)?;\n    let (impl_gen, type_gen, where_clause) = generics.split_for_impl();\n    let struct_name_str = name.to_string();\n    let members = Members::from_struct(contents, fuels_core_path.clone())?;\n    let field_names = members.names().collect::<Vec<_>>();\n    let ignored_field_names = members.ignored_names().collect_vec();\n\n    let std_lib = std_lib_path(no_std);\n\n    Ok(quote! {\n        impl #impl_gen #fuels_core_path::traits::Tokenizable for #name #type_gen #where_clause {\n            fn into_token(self) -> #fuels_types_path::Token {\n                let tokens = #std_lib::vec![#(#fuels_core_path::traits::Tokenizable::into_token(self.#field_names)),*];\n                #fuels_types_path::Token::Struct(tokens)\n            }\n\n            fn from_token(token: #fuels_types_path::Token)  -> #fuels_types_path::errors::Result<Self> {\n                match token {\n                    #fuels_types_path::Token::Struct(tokens) => {\n                        let mut tokens_iter = tokens.into_iter();\n                        let mut next_token = move || { tokens_iter\n                            .next()\n                            .ok_or_else(|| {\n                                #fuels_types_path::errors::Error::Codec(\n                                    #std_lib::format!(\n                                        \"ran out of tokens before `{}` has finished construction\",\n                                        #struct_name_str\n                                        )\n                                    )\n                                }\n                            )\n                        };\n                        ::core::result::Result::Ok(Self {\n                            #(\n                                #field_names: #fuels_core_path::traits::Tokenizable::from_token(next_token()?)?,\n                             )*\n                            #(#ignored_field_names: ::core::default::Default::default(),)*\n\n                        })\n                    },\n                    other => ::core::result::Result::Err(\n                        #fuels_types_path::errors::Error::Codec(\n                            #std_lib::format!(\n                                \"error while constructing `{}`. Expected token of type `Token::Struct`, \\\n                                got `{:?}`\",\n                                #struct_name_str,\n                                other\n                            )\n                        )\n                    ),\n                }\n            }\n        }\n    })\n}\n\nfn tokenizable_for_enum(\n    name: Ident,\n    generics: Generics,\n    contents: DataEnum,\n    fuels_types_path: TokenStream,\n    fuels_core_path: TokenStream,\n    no_std: bool,\n) -> Result<TokenStream> {\n    validate_and_extract_generic_types(&generics)?;\n    let (impl_gen, type_gen, where_clause) = generics.split_for_impl();\n    let name_stringified = name.to_string();\n    let variants = utils::extract_variants(contents.variants, fuels_core_path.clone())?;\n    let discriminant_and_token = variants.variant_into_discriminant_and_token();\n    let constructed_variant = variants.variant_from_discriminant_and_token(no_std);\n\n    let std_lib = std_lib_path(no_std);\n\n    Ok(quote! {\n        impl #impl_gen #fuels_core_path::traits::Tokenizable for #name #type_gen #where_clause {\n            fn into_token(self) -> #fuels_types_path::Token {\n                let (discriminant, token) = #discriminant_and_token;\n\n                let enum_variants = match <Self as #fuels_core_path::traits::Parameterize>::param_type() {\n                    #fuels_types_path::param_types::ParamType::Enum{enum_variants, ..} => enum_variants,\n                    other => ::std::panic!(\n                        \"calling {}::param_type() must return a `ParamType::Enum` but instead it returned: `{:?}`\",\n                        #name_stringified,\n                        other\n                    )\n                };\n\n                #fuels_types_path::Token::Enum(#std_lib::boxed::Box::new((discriminant, token, enum_variants)))\n            }\n\n            fn from_token(token: #fuels_types_path::Token) -> #fuels_types_path::errors::Result<Self>\n            where\n                Self: Sized,\n            {\n                match token {\n                    #fuels_types_path::Token::Enum(selector) => {\n                        let (discriminant, variant_token, _) = *selector;\n                        #constructed_variant\n                    }\n                    _ => ::core::result::Result::Err(\n                            #std_lib::format!(\"token `{}` is not of the type `Token::Enum`\", token)\n                        ),\n                }.map_err(|e| {\n                    #fuels_types_path::errors::Error::Codec(\n                        #std_lib::format!(\n                            \"error while instantiating `{}` from token `{}`\",\n                            #name_stringified,\n                            e\n                        )\n                    )\n                })\n            }\n        }\n    })\n}\n"
  },
  {
    "path": "packages/fuels-macros/src/derive/try_from.rs",
    "content": "use proc_macro2::TokenStream;\nuse quote::quote;\nuse syn::{Data, DeriveInput, Error, Result};\n\nuse crate::derive::utils::{find_attr, get_path_from_attr_or, std_lib_path};\n\npub fn generate_try_from_impl(input: DeriveInput) -> Result<TokenStream> {\n    let fuels_types_path =\n        get_path_from_attr_or(\"FuelsTypesPath\", &input.attrs, quote! {::fuels::types})?;\n    let fuels_core_path =\n        get_path_from_attr_or(\"FuelsCorePath\", &input.attrs, quote! {::fuels::core})?;\n    let no_std = find_attr(\"NoStd\", &input.attrs).is_some();\n\n    match input.data {\n        Data::Enum(_) | Data::Struct(_) => {\n            impl_try_from(input, fuels_types_path, fuels_core_path, no_std)\n        }\n        Data::Union(union) => Err(Error::new_spanned(\n            union.union_token,\n            \"unions are not supported\",\n        )),\n    }\n}\n\nfn impl_try_from(\n    input: DeriveInput,\n    fuels_types_path: TokenStream,\n    fuels_core_path: TokenStream,\n    no_std: bool,\n) -> Result<TokenStream> {\n    let name = &input.ident;\n    let (impl_gen, type_gen, where_clause) = input.generics.split_for_impl();\n\n    let std_lib = std_lib_path(no_std);\n    Ok(quote! {\n        impl #impl_gen TryFrom<&[u8]> for #name #type_gen #where_clause {\n            type Error = #fuels_types_path::errors::Error;\n\n            fn try_from(bytes: &[u8]) -> #fuels_types_path::errors::Result<Self> {\n                #fuels_core_path::codec::try_from_bytes(bytes, ::std::default::Default::default())\n            }\n        }\n\n        impl #impl_gen TryFrom<&#std_lib::vec::Vec<u8>> for #name #type_gen #where_clause {\n            type Error = #fuels_types_path::errors::Error;\n\n            fn try_from(bytes: &#std_lib::vec::Vec<u8>) -> #fuels_types_path::errors::Result<Self> {\n                ::core::convert::TryInto::try_into(bytes.as_slice())\n            }\n        }\n\n        impl #impl_gen TryFrom<#std_lib::vec::Vec<u8>> for #name #type_gen #where_clause {\n            type Error = #fuels_types_path::errors::Error;\n\n            fn try_from(bytes: #std_lib::vec::Vec<u8>) -> #fuels_types_path::errors::Result<Self> {\n                ::core::convert::TryInto::try_into(bytes.as_slice())\n            }\n        }\n    })\n}\n"
  },
  {
    "path": "packages/fuels-macros/src/derive/utils.rs",
    "content": "use fuels_code_gen::utils::TypePath;\nuse proc_macro2::{Ident, TokenStream};\nuse quote::{ToTokens, quote};\nuse syn::{Attribute, Error, Expr, ExprLit, Fields, Lit, Meta, Result, Variant};\n\nuse crate::parse_utils::has_ignore_attr;\n\npub(crate) fn get_path_from_attr_or(\n    attr_name: &str,\n    attrs: &[Attribute],\n    default: TokenStream,\n) -> Result<TokenStream> {\n    let Some(attr) = find_attr(attr_name, attrs) else {\n        return Ok(default);\n    };\n\n    let Meta::NameValue(name_value) = &attr.meta else {\n        return Err(Error::new_spanned(\n            attr.meta.path(),\n            \"expected name='value'\",\n        ));\n    };\n\n    let Expr::Lit(ExprLit {\n        lit: Lit::Str(lit_str),\n        ..\n    }) = &name_value.value\n    else {\n        return Err(Error::new_spanned(\n            &name_value.value,\n            \"expected string literal\",\n        ));\n    };\n\n    TypePath::new(lit_str.value())\n        .map_err(|_| Error::new_spanned(lit_str.value(), \"invalid path\"))\n        .map(|type_path| type_path.to_token_stream())\n}\n\npub(crate) fn find_attr<'a>(name: &str, attrs: &'a [Attribute]) -> Option<&'a Attribute> {\n    attrs.iter().find(|attr| {\n        attr.path()\n            .get_ident()\n            .map(|ident| ident == name)\n            .unwrap_or(false)\n    })\n}\n\npub(crate) struct VariantInfo {\n    name: Ident,\n    is_unit: bool,\n}\n\npub(crate) enum ExtractedVariant {\n    Normal {\n        info: VariantInfo,\n        discriminant: u64,\n    },\n    Ignored {\n        info: VariantInfo,\n    },\n}\n\npub(crate) fn extract_variants(\n    contents: impl IntoIterator<Item = Variant>,\n    fuels_core_path: TokenStream,\n) -> Result<ExtractedVariants> {\n    let variants = contents\n        .into_iter()\n        .enumerate()\n        .map(|(discriminant, variant)| -> Result<_> {\n            let is_unit = matches!(variant.fields, Fields::Unit);\n            if has_ignore_attr(&variant.attrs) {\n                Ok(ExtractedVariant::Ignored {\n                    info: VariantInfo {\n                        name: variant.ident,\n                        is_unit,\n                    },\n                })\n            } else {\n                validate_variant_type(&variant)?;\n\n                let discriminant = discriminant.try_into().map_err(|_| {\n                    Error::new_spanned(&variant.ident, \"enums cannot have more than 256 variants\")\n                })?;\n\n                Ok(ExtractedVariant::Normal {\n                    info: VariantInfo {\n                        name: variant.ident,\n                        is_unit,\n                    },\n                    discriminant,\n                })\n            }\n        })\n        .collect::<Result<_>>()?;\n\n    Ok(ExtractedVariants {\n        variants,\n        fuels_core_path,\n    })\n}\n\npub(crate) struct ExtractedVariants {\n    fuels_core_path: TokenStream,\n    variants: Vec<ExtractedVariant>,\n}\n\nimpl ExtractedVariants {\n    pub(crate) fn variant_into_discriminant_and_token(&self) -> TokenStream {\n        let match_branches = self.variants.iter().map(|variant|\n            match variant {\n                ExtractedVariant::Normal { info: VariantInfo{ name, is_unit }, discriminant } => {\n                    let fuels_core_path = &self.fuels_core_path;\n                    if *is_unit {\n                            quote! { Self::#name => (#discriminant, #fuels_core_path::traits::Tokenizable::into_token(())) }\n                    } else {\n                            quote! { Self::#name(inner) => (#discriminant, #fuels_core_path::traits::Tokenizable::into_token(inner))}\n                    }\n                },\n                ExtractedVariant::Ignored { info: VariantInfo{ name, is_unit } } => {\n                    let panic_expression = {\n                        let name_stringified = name.to_string();\n                        quote! {::core::panic!(\"variant `{}` should never be constructed\", #name_stringified)}\n                    };\n                    if *is_unit {\n                        quote! { Self::#name => #panic_expression }\n                    } else {\n                        quote! { Self::#name(..) => #panic_expression }\n                    }\n                }\n            }\n        );\n\n        quote! {\n            match self {\n                #(#match_branches),*\n            }\n        }\n    }\n    pub(crate) fn variant_from_discriminant_and_token(&self, no_std: bool) -> TokenStream {\n        let match_discriminant = self\n            .variants\n            .iter()\n            .filter_map(|variant| match variant {\n                ExtractedVariant::Normal { info, discriminant } => Some((info, discriminant)),\n                _ => None,\n            })\n            .map(|(VariantInfo { name, is_unit }, discriminant)| {\n                let fuels_core_path = &self.fuels_core_path;\n\n                let variant_value = if *is_unit {\n                    quote! {}\n                } else {\n                    quote! { (#fuels_core_path::traits::Tokenizable::from_token(variant_token)?) }\n                };\n\n                quote! { #discriminant => ::core::result::Result::Ok(Self::#name #variant_value)}\n            });\n\n        let std_lib = std_lib_path(no_std);\n        quote! {\n            match discriminant {\n                #(#match_discriminant,)*\n                _ => ::core::result::Result::Err(#std_lib::format!(\n                    \"discriminant {} doesn't point to any of the enums variants\", discriminant\n                )),\n            }\n        }\n    }\n}\n\nfn validate_variant_type(variant: &Variant) -> Result<()> {\n    match &variant.fields {\n        Fields::Named(named_fields) => {\n            return Err(Error::new_spanned(\n                named_fields.clone(),\n                \"struct like enum variants are not supported\".to_string(),\n            ));\n        }\n        Fields::Unnamed(unnamed_fields) => {\n            let fields = &unnamed_fields.unnamed;\n\n            if fields.len() != 1 {\n                return Err(Error::new_spanned(\n                    unnamed_fields.clone(),\n                    \"tuple-like enum variants must contain exactly one element\".to_string(),\n                ));\n            }\n        }\n        _ => {}\n    }\n\n    Ok(())\n}\n\npub(crate) fn std_lib_path(no_std: bool) -> TokenStream {\n    if no_std {\n        quote! {::alloc}\n    } else {\n        quote! {::std}\n    }\n}\n"
  },
  {
    "path": "packages/fuels-macros/src/derive.rs",
    "content": "pub mod parameterize;\npub mod tokenizable;\npub mod try_from;\nmod utils;\n"
  },
  {
    "path": "packages/fuels-macros/src/lib.rs",
    "content": "use fuels_code_gen::Abigen;\nuse proc_macro::TokenStream;\nuse syn::{DeriveInput, parse_macro_input};\n\nuse crate::{\n    abigen::MacroAbigenTargets,\n    derive::{\n        parameterize::generate_parameterize_impl, tokenizable::generate_tokenizable_impl,\n        try_from::generate_try_from_impl,\n    },\n    setup_program_test::{TestProgramCommands, generate_setup_program_test_code},\n};\n\nmod abigen;\nmod derive;\nmod parse_utils;\nmod setup_program_test;\n\n/// Used to generate bindings for Contracts, Scripts and Predicates. Accepts\n/// input in the form of `ProgramType(name=\"MyBindings\", abi=ABI_SOURCE)...`\n///\n/// `ProgramType` is either `Contract`, `Script` or `Predicate`.\n///\n/// `ABI_SOURCE` is a string literal representing either a path to the JSON ABI\n/// file or the contents of the JSON ABI file itself.\n///\n///```text\n/// abigen!(Contract(\n///         name = \"MyContract\",\n///         abi = \"packages/fuels/tests/contracts/token_ops/out/release/token_ops-abi.json\"\n///     ));\n///```\n///\n/// More details can be found in the [`Fuel Rust SDK Book`](https://fuellabs.github.io/fuels-rs/latest)\n#[proc_macro]\npub fn abigen(input: TokenStream) -> TokenStream {\n    let targets = parse_macro_input!(input as MacroAbigenTargets);\n\n    Abigen::generate(targets.into(), false)\n        .expect(\"abigen generation failed\")\n        .into()\n}\n\n#[proc_macro]\npub fn wasm_abigen(input: TokenStream) -> TokenStream {\n    let targets = parse_macro_input!(input as MacroAbigenTargets);\n\n    Abigen::generate(targets.into(), true)\n        .expect(\"abigen generation failed\")\n        .into()\n}\n\n/// Used to reduce boilerplate in integration tests.\n///\n/// More details can be found in the [`Fuel Rust SDK Book`](https://fuellabs.github.io/fuels-rs/latest)\n#[proc_macro]\npub fn setup_program_test(input: TokenStream) -> TokenStream {\n    let test_program_commands = parse_macro_input!(input as TestProgramCommands);\n\n    generate_setup_program_test_code(test_program_commands)\n        .unwrap_or_else(|e| e.to_compile_error())\n        .into()\n}\n\n#[proc_macro_derive(Parameterize, attributes(FuelsTypesPath, FuelsCorePath, NoStd, Ignore))]\npub fn parameterize(stream: TokenStream) -> TokenStream {\n    let input = parse_macro_input!(stream as DeriveInput);\n\n    generate_parameterize_impl(input)\n        .unwrap_or_else(|e| e.to_compile_error())\n        .into()\n}\n\n#[proc_macro_derive(Tokenizable, attributes(FuelsTypesPath, FuelsCorePath, NoStd, Ignore))]\npub fn tokenizable(stream: TokenStream) -> TokenStream {\n    let input = parse_macro_input!(stream as DeriveInput);\n\n    generate_tokenizable_impl(input)\n        .unwrap_or_else(|e| e.to_compile_error())\n        .into()\n}\n\n#[proc_macro_derive(TryFrom, attributes(FuelsTypesPath, FuelsCorePath, NoStd))]\npub fn try_from(stream: TokenStream) -> TokenStream {\n    let input = parse_macro_input!(stream as DeriveInput);\n\n    generate_try_from_impl(input)\n        .unwrap_or_else(|e| e.to_compile_error())\n        .into()\n}\n"
  },
  {
    "path": "packages/fuels-macros/src/parse_utils/command.rs",
    "content": "use proc_macro2::{Ident, TokenStream};\nuse syn::{\n    Error, Meta,\n    Meta::List,\n    parse::{ParseStream, Parser},\n    punctuated::Punctuated,\n    token::Comma,\n};\n\n#[derive(Debug)]\npub struct Command {\n    pub name: Ident,\n    pub contents: TokenStream,\n}\n\nimpl Command {\n    pub fn parse_multiple(input: ParseStream) -> syn::Result<Vec<Command>> {\n        input\n            .call(Punctuated::<Meta, Comma>::parse_terminated)?\n            .into_iter()\n            .map(Command::new)\n            .collect()\n    }\n\n    pub fn new(meta: Meta) -> syn::Result<Self> {\n        if let List(meta_list) = meta {\n            let name = meta_list.path.get_ident().cloned().ok_or_else(|| {\n                Error::new_spanned(\n                    &meta_list.path,\n                    \"command name cannot be a Path -- i.e. contain ':'\",\n                )\n            })?;\n\n            Ok(Self {\n                name,\n                contents: meta_list.tokens,\n            })\n        } else {\n            Err(Error::new_spanned(\n                meta,\n                \"expected a command name literal -- e.g. `Something(...)`\",\n            ))\n        }\n    }\n\n    pub fn parse_nested_metas(self) -> syn::Result<Punctuated<Meta, Comma>> {\n        Punctuated::<Meta, Comma>::parse_terminated.parse2(self.contents)\n    }\n\n    #[cfg(test)]\n    pub(crate) fn parse_multiple_from_token_stream(\n        stream: proc_macro2::TokenStream,\n    ) -> syn::Result<Vec<Self>> {\n        syn::parse::Parser::parse2(Command::parse_multiple, stream)\n    }\n\n    #[cfg(test)]\n    pub(crate) fn parse_single_from_token_stream(\n        stream: proc_macro2::TokenStream,\n    ) -> syn::Result<Self> {\n        syn::parse::Parser::parse2(Command::parse_multiple, stream.clone())?\n            .pop()\n            .ok_or_else(|| Error::new_spanned(stream, \"expected to have at least one command!\"))\n    }\n}\n#[cfg(test)]\nmod tests {\n    use quote::quote;\n\n    use crate::parse_utils::command::Command;\n\n    #[test]\n    fn command_name_is_properly_extracted() -> syn::Result<()> {\n        // given\n        let macro_contents = quote! {SomeCommand(), OtherCommand()};\n\n        // when\n        let commands = Command::parse_multiple_from_token_stream(macro_contents)?;\n\n        // then\n        let command_names = commands\n            .into_iter()\n            .map(|command| command.name.to_string())\n            .collect::<Vec<_>>();\n\n        assert_eq!(command_names, vec![\"SomeCommand\", \"OtherCommand\"]);\n\n        Ok(())\n    }\n}\n"
  },
  {
    "path": "packages/fuels-macros/src/parse_utils/unique_lit_strs.rs",
    "content": "use std::vec::IntoIter;\n\nuse proc_macro2::{Span, TokenStream};\nuse syn::{LitStr, Result, parse::Parser, punctuated::Punctuated, spanned::Spanned, token::Comma};\n\nuse crate::parse_utils::validate_no_duplicates;\n\n#[derive(Debug)]\npub struct UniqueLitStrs {\n    span: Span,\n    lit_strs: Vec<LitStr>,\n}\n\nimpl UniqueLitStrs {\n    pub fn new(tokens: TokenStream) -> Result<Self> {\n        let parsed_lit_strs = Punctuated::<LitStr, Comma>::parse_terminated.parse2(tokens)?;\n        let span = parsed_lit_strs.span();\n        let lit_strs: Vec<_> = parsed_lit_strs.into_iter().collect();\n\n        validate_no_duplicates(&lit_strs, |ls| ls.value())?;\n\n        Ok(Self { span, lit_strs })\n    }\n\n    #[allow(dead_code)]\n    pub fn iter(&self) -> impl Iterator<Item = &LitStr> {\n        self.lit_strs.iter()\n    }\n\n    #[allow(dead_code)]\n    pub fn span(&self) -> Span {\n        self.span\n    }\n}\n\nimpl IntoIterator for UniqueLitStrs {\n    type Item = LitStr;\n    type IntoIter = IntoIter<Self::Item>;\n\n    fn into_iter(self) -> Self::IntoIter {\n        self.lit_strs.into_iter()\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use proc_macro2::TokenStream;\n    use quote::quote;\n\n    use super::*;\n    use crate::parse_utils::Command;\n\n    #[test]\n    fn correctly_reads_lit_strs() -> Result<()> {\n        // given\n        let stream = quote! {SomeCommand(\"lit1\", \"lit2\")};\n\n        // when\n        let unique_lit_strs = parse_unique_lit_strs(stream)?;\n\n        // then\n        let stringified = unique_lit_strs\n            .iter()\n            .map(|lit_str| lit_str.value())\n            .collect::<Vec<_>>();\n\n        assert_eq!(stringified, vec![\"lit1\", \"lit2\"]);\n\n        Ok(())\n    }\n\n    #[test]\n    fn doesnt_allow_duplicates() {\n        // given\n        let stream = quote! {SomeCommand(\"lit1\", \"lit2\", \"lit1\")};\n\n        // when\n        let err = parse_unique_lit_strs(stream).expect_err(\"should have failed\");\n\n        // then\n        let messages = err.into_iter().map(|e| e.to_string()).collect::<Vec<_>>();\n        assert_eq!(messages, vec![\"original defined here:\", \"duplicate!\"]);\n    }\n\n    #[test]\n    fn only_strings_allowed() {\n        let stream = quote! {SomeCommand(\"lit1\", \"lit2\", true)};\n\n        let err = parse_unique_lit_strs(stream).expect_err(\"should have failed\");\n\n        assert_eq!(err.to_string(), \"expected string literal\");\n    }\n\n    fn parse_unique_lit_strs(stream: TokenStream) -> Result<UniqueLitStrs> {\n        let command = Command::parse_single_from_token_stream(stream)?;\n\n        UniqueLitStrs::new(command.contents)\n    }\n}\n"
  },
  {
    "path": "packages/fuels-macros/src/parse_utils/unique_name_values.rs",
    "content": "use std::collections::HashMap;\n\nuse fuels_code_gen::utils::ident;\nuse itertools::Itertools;\nuse proc_macro2::{Ident, Span, TokenStream};\nuse syn::{\n    Error, Expr, Lit, LitStr, MetaNameValue, parse::Parser, punctuated::Punctuated,\n    spanned::Spanned,\n};\n\nuse crate::parse_utils::{ErrorsExt, validate_no_duplicates};\n\n#[derive(Debug)]\npub struct UniqueNameValues {\n    span: Span,\n    name_values: HashMap<Ident, Lit>,\n}\n\nimpl UniqueNameValues {\n    pub fn new(tokens: TokenStream) -> syn::Result<Self> {\n        let name_value_metas = Punctuated::<MetaNameValue, syn::token::Comma>::parse_terminated\n            .parse2(tokens)\n            .map_err(|e| Error::new(e.span(), \"expected name='value'\"))?;\n        let span = name_value_metas.span();\n        let name_values = Self::extract_name_values(name_value_metas.into_iter())?;\n\n        let names = name_values.iter().map(|(name, _)| name).collect::<Vec<_>>();\n        validate_no_duplicates(&names, |&&name| name.clone())?;\n\n        Ok(Self {\n            span,\n            name_values: name_values.into_iter().collect(),\n        })\n    }\n\n    pub fn try_get(&self, name: &str) -> Option<&Lit> {\n        self.name_values.get(&ident(name))\n    }\n\n    pub fn validate_has_no_other_names(&self, allowed_names: &[&str]) -> syn::Result<()> {\n        let expected_names = allowed_names\n            .iter()\n            .map(|name| format!(\"'{name}'\"))\n            .join(\", \");\n\n        self.name_values\n            .keys()\n            .filter(|name| !allowed_names.contains(&name.to_string().as_str()))\n            .map(|name| {\n                Error::new_spanned(\n                    name.clone(),\n                    format!(\"attribute '{name}' not recognized. Expected one of: {expected_names}\"),\n                )\n            })\n            .validate_no_errors()\n    }\n\n    pub fn get_as_lit_str(&self, name: &str) -> syn::Result<&LitStr> {\n        let value = self\n            .try_get(name)\n            .ok_or_else(|| Error::new(self.span, format!(\"missing attribute '{name}'\")))?;\n\n        if let Lit::Str(lit_str) = value {\n            Ok(lit_str)\n        } else {\n            Err(Error::new_spanned(\n                value.clone(),\n                format!(\"expected the attribute '{name}' to have a string value\"),\n            ))\n        }\n    }\n\n    fn extract_name_values<T: Iterator<Item = MetaNameValue>>(\n        name_value_metas: T,\n    ) -> syn::Result<Vec<(Ident, Lit)>> {\n        let (name_values, name_value_errors): (Vec<_>, Vec<Error>) = name_value_metas\n            .into_iter()\n            .map(|nv| {\n                let ident = nv.path.get_ident().cloned().ok_or_else(|| {\n                    Error::new_spanned(\n                        nv.path,\n                        \"attribute name cannot be a `Path` -- i.e. must not contain ':'\",\n                    )\n                })?;\n\n                let Expr::Lit(expr_lit) = nv.value else {\n                    return Err(Error::new_spanned(nv.value, \"expected literal\"));\n                };\n\n                Ok((ident, expr_lit.lit))\n            })\n            .partition_result();\n\n        name_value_errors.into_iter().validate_no_errors()?;\n\n        Ok(name_values)\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use proc_macro2::TokenStream;\n    use quote::quote;\n    use syn::LitBool;\n\n    use super::*;\n    use crate::parse_utils::command::Command;\n\n    #[test]\n    fn name_values_correctly_parsed() -> syn::Result<()> {\n        // given\n        let name_values = extract_name_values(quote! {SomeCommand(attr1=\"value1\", attr2=true)})?;\n\n        // when\n        let attr_values = [\"attr1\", \"attr2\"].map(|attr| {\n            name_values\n                .try_get(attr)\n                .unwrap_or_else(|| panic!(\"attribute {attr} should have existed\"))\n                .clone()\n        });\n\n        // then\n        let expected_values = [\n            Lit::Str(LitStr::new(\"value1\", Span::call_site())),\n            Lit::Bool(LitBool::new(true, Span::call_site())),\n        ];\n\n        assert_eq!(attr_values, expected_values);\n\n        Ok(())\n    }\n\n    #[test]\n    fn duplicates_cause_errors() {\n        // given\n        let tokens = quote! {SomeCommand(duplicate=1, something=2, duplicate=3)};\n\n        // when\n        let err = extract_name_values(tokens).expect_err(\"should have failed\");\n\n        // then\n        let messages = err.into_iter().map(|e| e.to_string()).collect::<Vec<_>>();\n        assert_eq!(messages, vec![\"original defined here:\", \"duplicate!\"]);\n    }\n\n    #[test]\n    fn attr_names_cannot_be_paths() {\n        let tokens = quote! {SomeCommand(something::duplicate=1)};\n\n        let err = extract_name_values(tokens).expect_err(\"should have failed\");\n\n        assert_eq!(\n            err.to_string(),\n            \"attribute name cannot be a `Path` -- i.e. must not contain ':'\"\n        );\n    }\n\n    #[test]\n    fn only_name_value_is_accepted() {\n        let tokens = quote! {SomeCommand(name=\"value\", \"something_else\")};\n\n        let err = extract_name_values(tokens).expect_err(\"should have failed\");\n\n        assert_eq!(err.to_string(), \"expected name='value'\");\n    }\n\n    #[test]\n    fn validates_correct_names() -> syn::Result<()> {\n        let tokens = quote! {SomeCommand(name=\"value\", other=\"something_else\")};\n        let name_values = extract_name_values(tokens)?;\n\n        let result = name_values.validate_has_no_other_names(&[\"name\", \"other\", \"another\"]);\n\n        assert!(result.is_ok());\n\n        Ok(())\n    }\n\n    #[test]\n    fn catches_incorrect_names() -> syn::Result<()> {\n        let name_values =\n            extract_name_values(quote! {SomeCommand(name=\"value\", other=\"something_else\")})?;\n\n        let err = name_values\n            .validate_has_no_other_names(&[\"name\", \"other_is_not_allowed\"])\n            .expect_err(\"should have failed\");\n\n        assert_eq!(\n            err.to_string(),\n            \"attribute 'other' not recognized. Expected one of: 'name', 'other_is_not_allowed'\"\n        );\n\n        Ok(())\n    }\n\n    #[test]\n    fn can_get_lit_strs() -> syn::Result<()> {\n        let name_values = extract_name_values(quote! {SomeCommand(name=\"value\")})?;\n\n        let lit_str = name_values.get_as_lit_str(\"name\")?;\n\n        assert_eq!(lit_str.value(), \"value\");\n\n        Ok(())\n    }\n\n    #[test]\n    fn cannot_get_lit_str_if_type_is_wrong() -> syn::Result<()> {\n        let name_values = extract_name_values(quote! {SomeCommand(name=true)})?;\n\n        let err = name_values\n            .get_as_lit_str(\"name\")\n            .expect_err(\"should have failed\");\n\n        assert_eq!(\n            err.to_string(),\n            \"expected the attribute 'name' to have a string value\"\n        );\n\n        Ok(())\n    }\n\n    #[test]\n    fn lit_str_getter_complains_value_is_missing() -> syn::Result<()> {\n        let name_values = extract_name_values(quote! {SomeCommand(name=true)})?;\n\n        let err = name_values\n            .get_as_lit_str(\"missing\")\n            .expect_err(\"should have failed\");\n\n        assert_eq!(err.to_string(), \"missing attribute 'missing'\");\n\n        Ok(())\n    }\n\n    fn extract_name_values(stream: TokenStream) -> syn::Result<UniqueNameValues> {\n        let command = Command::parse_single_from_token_stream(stream)?;\n        UniqueNameValues::new(command.contents)\n    }\n}\n"
  },
  {
    "path": "packages/fuels-macros/src/parse_utils.rs",
    "content": "pub(crate) use command::Command;\nuse itertools::{Itertools, chain};\nuse proc_macro2::{Ident, TokenStream};\nuse quote::{ToTokens, quote};\nuse syn::{\n    Attribute, DataEnum, DataStruct, Error, Fields, GenericParam, Generics, TypeParam, Variant,\n};\npub(crate) use unique_lit_strs::UniqueLitStrs;\npub(crate) use unique_name_values::UniqueNameValues;\n\nmod command;\nmod unique_lit_strs;\nmod unique_name_values;\n\npub(crate) trait ErrorsExt: Iterator<Item = Error> + Sized {\n    fn combine_errors(self) -> Option<Self::Item>;\n    fn validate_no_errors(self) -> Result<(), Self::Item>;\n}\n\nimpl<T> ErrorsExt for T\nwhere\n    T: Iterator<Item = Error> + Sized,\n{\n    fn combine_errors(self) -> Option<Self::Item> {\n        self.reduce(|mut errors, error| {\n            errors.combine(error);\n            errors\n        })\n    }\n\n    fn validate_no_errors(self) -> Result<(), Self::Item> {\n        if let Some(err) = self.combine_errors() {\n            Err(err)\n        } else {\n            Ok(())\n        }\n    }\n}\n\nfn generate_duplicate_error<T>(duplicates: &[&T]) -> Error\nwhere\n    T: ToTokens,\n{\n    let mut iter = duplicates.iter();\n\n    let original_error = iter\n        .next()\n        .map(|first_el| Error::new_spanned(first_el, \"original defined here:\"));\n\n    let the_rest = iter.map(|duplicate| Error::new_spanned(duplicate, \"duplicate!\"));\n\n    chain!(original_error, the_rest)\n        .combine_errors()\n        .expect(\"has to be at least one error!\")\n}\n\nfn group_up_duplicates<T, K, KeyFn>(name_values: &[T], key: KeyFn) -> Vec<Vec<&T>>\nwhere\n    KeyFn: Fn(&&T) -> K,\n    K: Ord,\n{\n    name_values\n        .iter()\n        .sorted_by_key(&key)\n        .group_by(&key)\n        .into_iter()\n        .filter_map(|(_, group)| {\n            let group = group.collect::<Vec<_>>();\n\n            (group.len() > 1).then_some(group)\n        })\n        .collect()\n}\n\nfn validate_no_duplicates<T, K, KeyFn>(elements: &[T], key_fn: KeyFn) -> syn::Result<()>\nwhere\n    KeyFn: Fn(&&T) -> K + Copy,\n    T: ToTokens,\n    K: Ord,\n{\n    group_up_duplicates(elements, key_fn)\n        .into_iter()\n        .map(|duplicates| generate_duplicate_error(&duplicates))\n        .validate_no_errors()\n}\n\npub fn validate_and_extract_generic_types(generics: &Generics) -> syn::Result<Vec<&TypeParam>> {\n    generics\n        .params\n        .iter()\n        .map(|generic_param| match generic_param {\n            GenericParam::Type(generic_type) => Ok(generic_type),\n            GenericParam::Lifetime(lifetime) => {\n                Err(Error::new_spanned(lifetime, \"Lifetimes not supported\"))\n            }\n            GenericParam::Const(const_generic) => Err(Error::new_spanned(\n                const_generic,\n                \"Const generics not supported\",\n            )),\n        })\n        .collect()\n}\n\nenum Member {\n    Normal { name: Ident, ty: TokenStream },\n    Ignored { name: Ident },\n}\n\npub(crate) struct Members {\n    members: Vec<Member>,\n    fuels_core_path: TokenStream,\n}\n\nimpl Members {\n    pub(crate) fn from_struct(\n        fields: DataStruct,\n        fuels_core_path: TokenStream,\n    ) -> syn::Result<Self> {\n        let named_fields = match fields.fields {\n            Fields::Named(named_fields) => Ok(named_fields.named),\n            Fields::Unnamed(fields) => Err(Error::new_spanned(\n                fields.unnamed,\n                \"Tuple-like structs not supported\",\n            )),\n            _ => {\n                panic!(\"This cannot happen in valid Rust code. Fields::Unit only appears in enums\")\n            }\n        }?;\n\n        let members = named_fields\n            .into_iter()\n            .map(|field| {\n                let name = field\n                    .ident\n                    .expect(\"`FieldsNamed` to only contain named fields\");\n                if has_ignore_attr(&field.attrs) {\n                    Member::Ignored { name }\n                } else {\n                    let ty = field.ty.into_token_stream();\n                    Member::Normal { name, ty }\n                }\n            })\n            .collect();\n\n        Ok(Members {\n            members,\n            fuels_core_path,\n        })\n    }\n\n    pub(crate) fn from_enum(data: DataEnum, fuels_core_path: TokenStream) -> syn::Result<Self> {\n        let members = data\n            .variants\n            .into_iter()\n            .map(|variant: Variant| {\n                let name = variant.ident;\n                if has_ignore_attr(&variant.attrs) {\n                    Ok(Member::Ignored { name })\n                } else {\n                    let ty = match variant.fields {\n                        Fields::Unnamed(fields_unnamed) => {\n                            if fields_unnamed.unnamed.len() != 1 {\n                                return Err(Error::new(\n                                    fields_unnamed.paren_token.span.join(),\n                                    \"must have exactly one element\",\n                                ));\n                            }\n                            fields_unnamed.unnamed.into_iter().next()\n                        }\n                        Fields::Unit => None,\n                        Fields::Named(named_fields) => {\n                            return Err(Error::new_spanned(\n                                named_fields,\n                                \"struct-like enum variants are not supported\",\n                            ));\n                        }\n                    }\n                    .map(|field| field.ty.into_token_stream())\n                    .unwrap_or_else(|| quote! {()});\n                    Ok(Member::Normal { name, ty })\n                }\n            })\n            .collect::<Result<Vec<_>, _>>()?;\n\n        Ok(Members {\n            members,\n            fuels_core_path,\n        })\n    }\n\n    pub(crate) fn names(&self) -> impl Iterator<Item = &Ident> + '_ {\n        self.members.iter().filter_map(|member| {\n            if let Member::Normal { name, .. } = member {\n                Some(name)\n            } else {\n                None\n            }\n        })\n    }\n\n    pub(crate) fn names_as_strings(&self) -> impl Iterator<Item = TokenStream> + '_ {\n        self.names().map(|ident| {\n            let name = ident.to_string();\n            quote! {#name.to_string()}\n        })\n    }\n\n    pub(crate) fn ignored_names(&self) -> impl Iterator<Item = &Ident> + '_ {\n        self.members.iter().filter_map(|member| {\n            if let Member::Ignored { name } = member {\n                Some(name)\n            } else {\n                None\n            }\n        })\n    }\n\n    pub(crate) fn param_type_calls(&self) -> impl Iterator<Item = TokenStream> + '_ {\n        let fuels_core_path = self.fuels_core_path.to_token_stream();\n        self.members.iter().filter_map(move |member| match member {\n            Member::Normal { ty, .. } => {\n                Some(quote! { <#ty as #fuels_core_path::traits::Parameterize>::param_type() })\n            }\n            _ => None,\n        })\n    }\n}\n\npub(crate) fn has_ignore_attr(attrs: &[Attribute]) -> bool {\n    attrs.iter().any(|attr| match &attr.meta {\n        syn::Meta::Path(path) => path.get_ident().is_some_and(|ident| ident == \"Ignore\"),\n        _ => false,\n    })\n}\n"
  },
  {
    "path": "packages/fuels-macros/src/setup_program_test/code_gen.rs",
    "content": "use std::{\n    collections::HashMap,\n    path::{Path, PathBuf},\n};\n\nuse fuels_code_gen::{Abi, Abigen, AbigenTarget, ProgramType, utils::ident};\nuse proc_macro2::{Ident, Span, TokenStream};\nuse quote::quote;\nuse syn::LitStr;\n\nuse crate::setup_program_test::parsing::{\n    AbigenCommand, BuildProfile, DeployContractCommand, InitializeWalletCommand, LoadScriptCommand,\n    SetOptionsCommand, TestProgramCommands,\n};\n\npub(crate) fn generate_setup_program_test_code(\n    commands: TestProgramCommands,\n) -> syn::Result<TokenStream> {\n    let TestProgramCommands {\n        set_options,\n        initialize_wallets,\n        generate_bindings,\n        deploy_contract,\n        load_scripts,\n    } = commands;\n\n    let SetOptionsCommand { profile } = set_options.unwrap_or_default();\n    let project_lookup = generate_project_lookup(&generate_bindings, profile)?;\n    let abigen_code = abigen_code(&project_lookup)?;\n    let wallet_code = wallet_initialization_code(initialize_wallets);\n    let deploy_code = contract_deploying_code(&deploy_contract, &project_lookup);\n    let script_code = script_loading_code(&load_scripts, &project_lookup);\n\n    Ok(quote! {\n       #abigen_code\n       #wallet_code\n       #deploy_code\n       #script_code\n    })\n}\n\nfn generate_project_lookup(\n    commands: &AbigenCommand,\n    profile: BuildProfile,\n) -> syn::Result<HashMap<String, Project>> {\n    let pairs = commands\n        .targets\n        .iter()\n        .map(|command| -> syn::Result<_> {\n            let project = Project::new(command.program_type, &command.project, profile.clone())?;\n            Ok((command.name.value(), project))\n        })\n        .collect::<Result<Vec<_>, _>>()?;\n\n    Ok(pairs.into_iter().collect())\n}\n\nfn abigen_code(project_lookup: &HashMap<String, Project>) -> syn::Result<TokenStream> {\n    let targets = parse_abigen_targets(project_lookup)?;\n\n    Ok(Abigen::generate(targets, false).expect(\"abigen generation failed\"))\n}\n\nfn parse_abigen_targets(\n    project_lookup: &HashMap<String, Project>,\n) -> syn::Result<Vec<AbigenTarget>> {\n    project_lookup\n        .iter()\n        .map(|(name, project)| {\n            let source = Abi::load_from(project.abi_path())\n                .map_err(|e| syn::Error::new(project.path_span, e.to_string()))?;\n\n            Ok(AbigenTarget::new(\n                name.clone(),\n                source,\n                project.program_type,\n            ))\n        })\n        .collect()\n}\n\nfn wallet_initialization_code(maybe_command: Option<InitializeWalletCommand>) -> TokenStream {\n    let command = if let Some(command) = maybe_command {\n        command\n    } else {\n        return Default::default();\n    };\n\n    let wallet_names = extract_wallet_names(&command);\n\n    if wallet_names.is_empty() {\n        return Default::default();\n    }\n\n    let num_wallets = wallet_names.len();\n    quote! {\n        let [#(#wallet_names),*]: [_; #num_wallets] = ::fuels::test_helpers::launch_custom_provider_and_get_wallets(\n            ::fuels::test_helpers::WalletsConfig::new(Some(#num_wallets as u64), None, None),\n            None,\n            None,\n        )\n        .await\n        .expect(\"Error while trying to fetch wallets from the custom provider\")\n        .try_into()\n        .expect(\"Should have the exact number of wallets\");\n    }\n}\n\nfn extract_wallet_names(command: &InitializeWalletCommand) -> Vec<Ident> {\n    command\n        .names\n        .iter()\n        .map(|name| ident(&name.value()))\n        .collect()\n}\n\nfn contract_deploying_code(\n    commands: &[DeployContractCommand],\n    project_lookup: &HashMap<String, Project>,\n) -> TokenStream {\n    commands\n        .iter()\n        .map(|command| {\n            let contract_instance_name = ident(&command.name);\n            let contract_struct_name = ident(&command.contract.value());\n            let wallet_name = ident(&command.wallet);\n            let random_salt = command.random_salt;\n\n            let project = project_lookup\n                .get(&command.contract.value())\n                .expect(\"Project should be in lookup\");\n            let bin_path = project.bin_path();\n\n            let salt = if random_salt {\n                quote! {\n                    // Generate random salt for contract deployment.\n                    // These lines must be inside the `quote!` macro, otherwise the salt remains\n                    // identical between macro compilation, causing contract id collision.\n                    ::fuels::test_helpers::generate_random_salt()\n                }\n            } else {\n                quote! { [0; 32] }\n            };\n\n            quote! {\n                let salt: [u8; 32] = #salt;\n\n                let #contract_instance_name = {\n                    let load_config = ::fuels::programs::contract::LoadConfiguration::default().with_salt(salt);\n\n                    let loaded_contract = ::fuels::programs::contract::Contract::load_from(\n                        #bin_path,\n                        load_config\n                    )\n                    .expect(\"Failed to load the contract\");\n\n                    let response = loaded_contract.deploy_if_not_exists(\n                        &#wallet_name,\n                        ::fuels::types::transaction::TxPolicies::default()\n                    )\n                    .await\n                    .expect(\"Failed to deploy the contract\");\n\n                    #contract_struct_name::new(response.contract_id, #wallet_name.clone())\n                };\n            }\n        })\n        .reduce(|mut all_code, code| {\n            all_code.extend(code);\n            all_code\n        })\n        .unwrap_or_default()\n}\n\nfn script_loading_code(\n    commands: &[LoadScriptCommand],\n    project_lookup: &HashMap<String, Project>,\n) -> TokenStream {\n    commands\n        .iter()\n        .map(|command| {\n            let script_instance_name = ident(&command.name);\n            let script_struct_name = ident(&command.script.value());\n            let wallet_name = ident(&command.wallet);\n\n            let project = project_lookup\n                .get(&command.script.value())\n                .expect(\"Project should be in lookup\");\n            let bin_path = project.bin_path();\n\n            quote! {\n                let #script_instance_name = #script_struct_name::new(#wallet_name.clone(), #bin_path);\n            }\n        })\n        .reduce(|mut all_code, code| {\n            all_code.extend(code);\n            all_code\n        })\n        .unwrap_or_default()\n}\n\nstruct Project {\n    program_type: ProgramType,\n    path: PathBuf,\n    path_span: Span,\n    profile: BuildProfile,\n}\n\nimpl Project {\n    fn new(program_type: ProgramType, dir: &LitStr, profile: BuildProfile) -> syn::Result<Self> {\n        let path = Path::new(&dir.value()).canonicalize().map_err(|_| {\n            syn::Error::new_spanned(\n                dir.clone(),\n                \"unable to canonicalize forc project path. Make sure the path is valid!\",\n            )\n        })?;\n\n        Ok(Self {\n            program_type,\n            path,\n            path_span: dir.span(),\n            profile,\n        })\n    }\n\n    fn compile_file_path(&self, suffix: &str, description: &str) -> String {\n        self.path\n            .join(\n                [\n                    format!(\"out/{}/\", &self.profile).as_str(),\n                    self.project_name(),\n                    suffix,\n                ]\n                .concat(),\n            )\n            .to_str()\n            .unwrap_or_else(|| panic!(\"could not join path for {description}\"))\n            .to_string()\n    }\n\n    fn project_name(&self) -> &str {\n        self.path\n            .file_name()\n            .expect(\"failed to get project name\")\n            .to_str()\n            .expect(\"failed to convert project name to string\")\n    }\n\n    fn abi_path(&self) -> String {\n        self.compile_file_path(\"-abi.json\", \"the ABI file\")\n    }\n\n    fn bin_path(&self) -> String {\n        self.compile_file_path(\".bin\", \"the binary file\")\n    }\n}\n"
  },
  {
    "path": "packages/fuels-macros/src/setup_program_test/parsing/command_parser.rs",
    "content": "macro_rules! command_parser {\n    ($($command_name: ident -> $command_struct: ty),+ $(,)?) => {\n        #[derive(Default)]\n        #[allow(non_snake_case)]\n        pub(crate) struct CommandParser {\n            $(pub(crate) $command_name: Vec<$command_struct>),*\n        }\n\n        impl CommandParser {\n            fn available_commands() -> impl Iterator<Item=&'static str> {\n                [$(stringify!($command_name)),*].into_iter()\n            }\n\n            pub(crate) fn parse_and_save(&mut self, command: $crate::parse_utils::Command) -> ::syn::Result<()>{\n                match command.name.to_string().as_str() {\n                    $(stringify!($command_name) => self.$command_name.push(command.try_into()?),)*\n                    _ => {\n                        let msg = Self::available_commands().map(|command| format!(\"'{command}'\")).join(\", \");\n                        return Err(::syn::Error::new(command.name.span(), format!(\"Unrecognized command. Expected one of: {msg}\")));\n                    }\n                };\n                Ok(())\n            }\n        }\n\n        impl Parse for CommandParser {\n            fn parse(input: ::syn::parse::ParseStream) -> Result<Self> {\n                use $crate::parse_utils::ErrorsExt;\n                let mut command_parser = Self::default();\n\n                let mut errors = vec![];\n                for command in $crate::parse_utils::Command::parse_multiple(input)? {\n                    if let Err(error) = command_parser.parse_and_save(command) {\n                        errors.push(error);\n                    }\n                }\n\n                errors.into_iter().validate_no_errors()?;\n                Ok(command_parser)\n            }\n        }\n    }\n}\npub(crate) use command_parser;\n"
  },
  {
    "path": "packages/fuels-macros/src/setup_program_test/parsing/commands/abigen.rs",
    "content": "use std::convert::TryFrom;\n\nuse fuels_code_gen::ProgramType;\nuse proc_macro2::Span;\nuse syn::{Error, LitStr};\n\nuse crate::parse_utils::{Command, UniqueNameValues};\n\n#[derive(Debug, Clone)]\npub(crate) struct TargetInfo {\n    pub(crate) name: LitStr,\n    pub(crate) project: LitStr,\n    pub(crate) program_type: ProgramType,\n}\n\nimpl TryFrom<Command> for TargetInfo {\n    type Error = Error;\n\n    fn try_from(command: Command) -> Result<Self, Self::Error> {\n        let program_type = command.name.try_into()?;\n\n        let name_values = UniqueNameValues::new(command.contents)?;\n        name_values.validate_has_no_other_names(&[\"name\", \"project\"])?;\n\n        let name = name_values.get_as_lit_str(\"name\")?.clone();\n        let project = name_values.get_as_lit_str(\"project\")?.clone();\n\n        Ok(Self {\n            name,\n            project,\n            program_type,\n        })\n    }\n}\n\n#[derive(Debug, Clone)]\npub(crate) struct AbigenCommand {\n    pub(crate) span: Span,\n    pub(crate) targets: Vec<TargetInfo>,\n}\n\nimpl TryFrom<Command> for AbigenCommand {\n    type Error = Error;\n\n    fn try_from(command: Command) -> Result<Self, Self::Error> {\n        let span = command.name.span();\n        let targets = command\n            .parse_nested_metas()?\n            .into_iter()\n            .map(|meta| Command::new(meta).and_then(TargetInfo::try_from))\n            .collect::<Result<Vec<_>, _>>()?;\n\n        Ok(Self { span, targets })\n    }\n}\n"
  },
  {
    "path": "packages/fuels-macros/src/setup_program_test/parsing/commands/deploy_contract.rs",
    "content": "use std::convert::TryFrom;\n\nuse syn::{Error, Lit, LitStr};\n\nuse crate::parse_utils::{Command, UniqueNameValues};\n\n#[derive(Debug, Clone)]\npub struct DeployContractCommand {\n    pub name: String,\n    pub contract: LitStr,\n    pub wallet: String,\n    pub random_salt: bool,\n}\n\nimpl TryFrom<Command> for DeployContractCommand {\n    type Error = Error;\n\n    fn try_from(command: Command) -> Result<Self, Self::Error> {\n        let name_values = UniqueNameValues::new(command.contents)?;\n        name_values.validate_has_no_other_names(&[\"name\", \"contract\", \"wallet\", \"random_salt\"])?;\n\n        let name = name_values.get_as_lit_str(\"name\")?.value();\n        let contract = name_values.get_as_lit_str(\"contract\")?.clone();\n        let wallet = name_values.get_as_lit_str(\"wallet\")?.value();\n        let random_salt = name_values.try_get(\"random_salt\").is_none_or(|opt| {\n            let Lit::Bool(b) = opt else { return true };\n            b.value()\n        });\n\n        Ok(Self {\n            name,\n            contract,\n            wallet,\n            random_salt,\n        })\n    }\n}\n"
  },
  {
    "path": "packages/fuels-macros/src/setup_program_test/parsing/commands/initialize_wallet.rs",
    "content": "use std::convert::TryFrom;\n\nuse proc_macro2::Span;\nuse syn::{Error, LitStr};\n\nuse crate::parse_utils::{Command, UniqueLitStrs};\n\n#[derive(Debug, Clone)]\npub struct InitializeWalletCommand {\n    pub span: Span,\n    pub names: Vec<LitStr>,\n}\n\nimpl TryFrom<Command> for InitializeWalletCommand {\n    type Error = Error;\n\n    fn try_from(command: Command) -> Result<Self, Self::Error> {\n        let wallets = UniqueLitStrs::new(command.contents)?;\n\n        Ok(Self {\n            span: command.name.span(),\n            names: wallets.into_iter().collect(),\n        })\n    }\n}\n"
  },
  {
    "path": "packages/fuels-macros/src/setup_program_test/parsing/commands/load_script.rs",
    "content": "use std::convert::TryFrom;\n\nuse syn::{Error, LitStr};\n\nuse crate::parse_utils::{Command, UniqueNameValues};\n\n#[derive(Debug, Clone)]\npub struct LoadScriptCommand {\n    pub name: String,\n    pub script: LitStr,\n    pub wallet: String,\n}\n\nimpl TryFrom<Command> for LoadScriptCommand {\n    type Error = Error;\n\n    fn try_from(command: Command) -> Result<Self, Self::Error> {\n        let name_values = UniqueNameValues::new(command.contents)?;\n        name_values.validate_has_no_other_names(&[\"name\", \"script\", \"wallet\"])?;\n\n        let name = name_values.get_as_lit_str(\"name\")?.value();\n        let script = name_values.get_as_lit_str(\"script\")?.clone();\n        let wallet = name_values.get_as_lit_str(\"wallet\")?.value();\n\n        Ok(Self {\n            name,\n            script,\n            wallet,\n        })\n    }\n}\n"
  },
  {
    "path": "packages/fuels-macros/src/setup_program_test/parsing/commands/set_options.rs",
    "content": "use std::{convert::TryFrom, fmt, str::FromStr};\n\nuse syn::Error;\n\nuse crate::parse_utils::{Command, UniqueNameValues};\n\n#[derive(Debug, Clone, Default, PartialEq, Eq)]\npub enum BuildProfile {\n    Debug,\n    #[default]\n    Release,\n}\n\nimpl FromStr for BuildProfile {\n    type Err = &'static str;\n\n    fn from_str(s: &str) -> Result<Self, Self::Err> {\n        match s {\n            \"debug\" => Ok(Self::Debug),\n            \"release\" => Ok(Self::Release),\n            _ => Err(r#\"invalid build profile option: must be \"debug\" or \"release\"\"#),\n        }\n    }\n}\n\nimpl fmt::Display for BuildProfile {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        write!(\n            f,\n            \"{}\",\n            match self {\n                BuildProfile::Debug => \"debug\",\n                BuildProfile::Release => \"release\",\n            }\n        )\n    }\n}\n\n#[derive(Debug, Clone, Default)]\npub struct SetOptionsCommand {\n    pub profile: BuildProfile,\n}\n\nimpl TryFrom<Command> for SetOptionsCommand {\n    type Error = Error;\n\n    fn try_from(command: Command) -> Result<Self, Self::Error> {\n        let name_values = UniqueNameValues::new(command.contents)?;\n        name_values.validate_has_no_other_names(&[\"profile\"])?;\n\n        let profile = name_values.get_as_lit_str(\"profile\")?;\n        let profile = profile\n            .value()\n            .as_str()\n            .parse()\n            .map_err(|msg| Error::new(profile.span(), msg))?;\n\n        Ok(Self { profile })\n    }\n}\n"
  },
  {
    "path": "packages/fuels-macros/src/setup_program_test/parsing/commands.rs",
    "content": "pub(crate) use abigen::AbigenCommand;\npub(crate) use deploy_contract::DeployContractCommand;\npub(crate) use initialize_wallet::InitializeWalletCommand;\nuse itertools::Itertools;\npub(crate) use load_script::LoadScriptCommand;\npub(crate) use set_options::{BuildProfile, SetOptionsCommand};\nuse syn::{\n    Result,\n    parse::{Parse, ParseStream},\n};\n\nuse crate::setup_program_test::parsing::{\n    command_parser::command_parser,\n    validations::{\n        extract_the_abigen_command, validate_all_contracts_are_known,\n        validate_all_scripts_are_known, validate_zero_or_one_wallet_command_present,\n    },\n};\n\nmod abigen;\nmod deploy_contract;\nmod initialize_wallet;\nmod load_script;\nmod set_options;\n\n// Contains the result of parsing the input to the `setup_program_test` macro.\n// Contents represent the users wishes with regards to wallet initialization,\n// bindings generation and contract deployment.\npub(crate) struct TestProgramCommands {\n    pub(crate) set_options: Option<SetOptionsCommand>,\n    pub(crate) initialize_wallets: Option<InitializeWalletCommand>,\n    pub(crate) generate_bindings: AbigenCommand,\n    pub(crate) deploy_contract: Vec<DeployContractCommand>,\n    pub(crate) load_scripts: Vec<LoadScriptCommand>,\n}\n\ncommand_parser!(\n    Options -> SetOptionsCommand,\n    Wallets -> InitializeWalletCommand,\n    Abigen -> AbigenCommand,\n    Deploy -> DeployContractCommand,\n    LoadScript -> LoadScriptCommand\n);\n\nimpl Parse for TestProgramCommands {\n    fn parse(input: ParseStream) -> Result<Self> {\n        let span = input.span();\n\n        let mut parsed_commands = CommandParser::parse(input)?;\n\n        let abigen_command = extract_the_abigen_command(span, &parsed_commands.Abigen)?;\n\n        validate_all_contracts_are_known(&abigen_command, &parsed_commands.Deploy)?;\n\n        validate_all_scripts_are_known(&abigen_command, &parsed_commands.LoadScript)?;\n\n        validate_zero_or_one_wallet_command_present(&parsed_commands.Wallets)?;\n\n        Ok(Self {\n            set_options: parsed_commands.Options.pop(),\n            initialize_wallets: parsed_commands.Wallets.pop(),\n            generate_bindings: abigen_command,\n            deploy_contract: parsed_commands.Deploy,\n            load_scripts: parsed_commands.LoadScript,\n        })\n    }\n}\n"
  },
  {
    "path": "packages/fuels-macros/src/setup_program_test/parsing/validations.rs",
    "content": "use std::collections::HashSet;\n\nuse fuels_code_gen::ProgramType;\nuse proc_macro2::Span;\nuse syn::{Error, LitStr, Result};\n\nuse crate::{\n    parse_utils::ErrorsExt,\n    setup_program_test::parsing::{\n        AbigenCommand, DeployContractCommand, InitializeWalletCommand, LoadScriptCommand,\n    },\n};\n\npub(crate) fn extract_the_abigen_command(\n    parent_span: Span,\n    abigen_commands: &[AbigenCommand],\n) -> Result<AbigenCommand> {\n    match abigen_commands {\n        [single_command] => Ok(single_command.clone()),\n        commands => {\n            let err = commands\n                .iter()\n                .map(|command| Error::new(command.span, \"Only one `Abigen` command allowed\"))\n                .combine_errors()\n                .unwrap_or_else(|| Error::new(parent_span, \"Add an `Abigen(..)` command!\"));\n\n            Err(err)\n        }\n    }\n}\n\npub(crate) fn validate_all_contracts_are_known(\n    abigen_command: &AbigenCommand,\n    deploy_commands: &[DeployContractCommand],\n) -> Result<()> {\n    extract_contracts_to_deploy(deploy_commands)\n        .difference(&names_of_program_bindings(\n            abigen_command,\n            ProgramType::Contract,\n        ))\n        .flat_map(|unknown_contract| {\n            [\n                Error::new_spanned(unknown_contract, \"Contract is unknown\"),\n                Error::new(\n                    abigen_command.span,\n                    format!(\n                        \"Consider adding: Contract(name=\\\"{}\\\", project=...)\",\n                        unknown_contract.value()\n                    ),\n                ),\n            ]\n        })\n        .validate_no_errors()\n}\n\npub(crate) fn validate_all_scripts_are_known(\n    abigen_command: &AbigenCommand,\n    load_commands: &[LoadScriptCommand],\n) -> Result<()> {\n    extract_scripts_to_load(load_commands)\n        .difference(&names_of_program_bindings(\n            abigen_command,\n            ProgramType::Script,\n        ))\n        .flat_map(|unknown_contract| {\n            [\n                Error::new_spanned(unknown_contract, \"Script is unknown\"),\n                Error::new(\n                    abigen_command.span,\n                    format!(\n                        \"Consider adding: Script(name=\\\"{}\\\", project=...)\",\n                        unknown_contract.value()\n                    ),\n                ),\n            ]\n        })\n        .validate_no_errors()\n}\n\npub(crate) fn validate_zero_or_one_wallet_command_present(\n    commands: &[InitializeWalletCommand],\n) -> Result<()> {\n    if commands.len() > 1 {\n        commands\n            .iter()\n            .map(|command| Error::new(command.span, \"Only one `Wallets` command allowed\"))\n            .combine_errors()\n            .map(Err)\n            .expect(\"Known to have at least one error\")\n    } else {\n        Ok(())\n    }\n}\n\nfn names_of_program_bindings(\n    commands: &AbigenCommand,\n    program_type: ProgramType,\n) -> HashSet<&LitStr> {\n    commands\n        .targets\n        .iter()\n        .filter_map(|target| (target.program_type == program_type).then_some(&target.name))\n        .collect()\n}\n\nfn extract_contracts_to_deploy(commands: &[DeployContractCommand]) -> HashSet<&LitStr> {\n    commands.iter().map(|c| &c.contract).collect()\n}\n\nfn extract_scripts_to_load(commands: &[LoadScriptCommand]) -> HashSet<&LitStr> {\n    commands.iter().map(|c| &c.script).collect()\n}\n"
  },
  {
    "path": "packages/fuels-macros/src/setup_program_test/parsing.rs",
    "content": "pub(crate) use commands::{\n    AbigenCommand, BuildProfile, DeployContractCommand, InitializeWalletCommand, LoadScriptCommand,\n    SetOptionsCommand, TestProgramCommands,\n};\n\nmod command_parser;\nmod commands;\nmod validations;\n"
  },
  {
    "path": "packages/fuels-macros/src/setup_program_test.rs",
    "content": "pub(crate) use code_gen::generate_setup_program_test_code;\npub(crate) use parsing::TestProgramCommands;\n\nmod code_gen;\nmod parsing;\n"
  },
  {
    "path": "packages/fuels-macros/tests/macro_usage.rs",
    "content": "#[cfg(test)]\nmod tests {\n    #[test]\n    fn ui() {\n        let t = trybuild::TestCases::new();\n        t.compile_fail(\"tests/ui/abigen/*.rs\");\n        t.compile_fail(\"tests/ui/setup_program_test/*.rs\");\n        t.compile_fail(\"tests/ui/derive/*/*.rs\");\n    }\n}\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/abigen/duplicate_attribute.rs",
    "content": "use fuels_macros::abigen;\n\nabigen!(Contract(\n    abi = \"some-abi.json\",\n    abi = \"some-abi2.json\",\n    name = \"SomeName\",\n    abi = \"some-abi3.json\",\n));\n\nfn main() {}\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/abigen/duplicate_attribute.stderr",
    "content": "error: original defined here:\n --> tests/ui/abigen/duplicate_attribute.rs:4:5\n  |\n4 |     abi = \"some-abi.json\",\n  |     ^^^\n\nerror: duplicate!\n --> tests/ui/abigen/duplicate_attribute.rs:5:5\n  |\n5 |     abi = \"some-abi2.json\",\n  |     ^^^\n\nerror: duplicate!\n --> tests/ui/abigen/duplicate_attribute.rs:7:5\n  |\n7 |     abi = \"some-abi3.json\",\n  |     ^^^\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/abigen/invalid_abi_path.rs",
    "content": "use fuels_macros::abigen;\n\nabigen!(Contract(name = \"SomeName\", abi = \"some_abi.json\"));\n\nfn main() {}\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/abigen/invalid_abi_path.stderr",
    "content": "error: failed to read `abi` file with path $WORKSPACE/target/tests/trybuild/fuels-macros/some_abi.json: No such file or directory (os error 2)\n --> tests/ui/abigen/invalid_abi_path.rs:3:43\n  |\n3 | abigen!(Contract(name = \"SomeName\", abi = \"some_abi.json\"));\n  |                                           ^^^^^^^^^^^^^^^\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/abigen/invalid_abi_value.rs",
    "content": "use fuels_macros::abigen;\n\nabigen!(Contract(name = \"SomeName\", abi = true,));\n\nfn main() {}\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/abigen/invalid_abi_value.stderr",
    "content": "error: expected the attribute 'abi' to have a string value\n --> tests/ui/abigen/invalid_abi_value.rs:3:43\n  |\n3 | abigen!(Contract(name = \"SomeName\", abi = true,));\n  |                                           ^^^^\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/abigen/invalid_name_value.rs",
    "content": "use fuels_macros::abigen;\n\nabigen!(Contract(name = true, abi = \"some-abi.json\",));\n\nfn main() {}\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/abigen/invalid_name_value.stderr",
    "content": "error: expected the attribute 'name' to have a string value\n --> tests/ui/abigen/invalid_name_value.rs:3:25\n  |\n3 | abigen!(Contract(name = true, abi = \"some-abi.json\",));\n  |                         ^^^^\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/abigen/invalid_program_type.rs",
    "content": "use fuels_macros::abigen;\n\nabigen!(SomeInvalidProgramType(\n    name = \"SomeName\",\n    abi = \"some-abi.json\"\n));\n\nfn main() {}\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/abigen/invalid_program_type.stderr",
    "content": "error: `SomeInvalidProgramType` is not a valid program type. Expected one of: `Script`, `Contract`, `Predicate`\n --> tests/ui/abigen/invalid_program_type.rs:3:9\n  |\n3 | abigen!(SomeInvalidProgramType(\n  |         ^^^^^^^^^^^^^^^^^^^^^^\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/abigen/malformed_abi.rs",
    "content": "use fuels_macros::abigen;\n\nabigen!(Contract(name = \"SomeName\", abi = r#\"{}\"#));\n\nfn main() {}\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/abigen/malformed_abi.stderr",
    "content": "error: malformed `abi`. Did you use `forc` to create it?:  missing field `programType` at line 1 column 2\n --> tests/ui/abigen/malformed_abi.rs:3:43\n  |\n3 | abigen!(Contract(name = \"SomeName\", abi = r#\"{}\"#));\n  |                                           ^^^^^^^\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/abigen/missing_abi_attribute.rs",
    "content": "use fuels_macros::abigen;\n\nabigen!(Contract(name = \"SomeName\"));\n\nfn main() {}\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/abigen/missing_abi_attribute.stderr",
    "content": "error: missing attribute 'abi'\n --> tests/ui/abigen/missing_abi_attribute.rs:3:18\n  |\n3 | abigen!(Contract(name = \"SomeName\"));\n  |                  ^^^^\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/abigen/missing_name_attr.rs",
    "content": "use fuels_macros::abigen;\n\nabigen!(Contract(abi = \"some-abi.json\"));\n\nfn main() {}\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/abigen/missing_name_attr.stderr",
    "content": "error: missing attribute 'name'\n --> tests/ui/abigen/missing_name_attr.rs:3:18\n  |\n3 | abigen!(Contract(abi = \"some-abi.json\"));\n  |                  ^^^\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/abigen/unrecognized_attribute.rs",
    "content": "use fuels_macros::abigen;\n\nabigen!(Contract(\n    name = \"SomeName\",\n    abi = \"some-abi.json\",\n    unknown = \"something\"\n));\n\nfn main() {}\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/abigen/unrecognized_attribute.stderr",
    "content": "error: attribute 'unknown' not recognized. Expected one of: 'name', 'abi'\n --> tests/ui/abigen/unrecognized_attribute.rs:6:5\n  |\n6 |     unknown = \"something\"\n  |     ^^^^^^^\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/derive/parameterize/attribute_must_be_named_value.rs",
    "content": "use fuels_macros::Parameterize;\n\n#[derive(Parameterize)]\n#[FuelsTypesPath]\nenum SomeEnum {\n    A(u8),\n}\n\n#[derive(Parameterize)]\n#[FuelsTypesPath = true]\nstruct SomeStruct {}\n\nfn main() {}\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/derive/parameterize/attribute_must_be_named_value.stderr",
    "content": "error: expected name='value'\n --> tests/ui/derive/parameterize/attribute_must_be_named_value.rs:4:3\n  |\n4 | #[FuelsTypesPath]\n  |   ^^^^^^^^^^^^^^\n\nerror: expected string literal\n  --> tests/ui/derive/parameterize/attribute_must_be_named_value.rs:10:20\n   |\n10 | #[FuelsTypesPath = true]\n   |                    ^^^^\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/derive/parameterize/only_generic_types_are_supported.rs",
    "content": "use fuels_macros::Parameterize;\n\n#[derive(Parameterize)]\nenum SomeEnum<const T: usize> {\n    A,\n}\n\n#[derive(Parameterize)]\nenum AnotherEnum<'a> {\n    A(&'a u64),\n}\n\n#[derive(Parameterize)]\nstruct SomeStruct<const T: usize> {}\n\n#[derive(Parameterize)]\nstruct AnotherStruct<'a> {\n    a: &'a u64,\n}\n\nfn main() {}\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/derive/parameterize/only_generic_types_are_supported.stderr",
    "content": "error: Const generics not supported\n --> tests/ui/derive/parameterize/only_generic_types_are_supported.rs:4:15\n  |\n4 | enum SomeEnum<const T: usize> {\n  |               ^^^^^^^^^^^^^^\n\nerror: Lifetimes not supported\n --> tests/ui/derive/parameterize/only_generic_types_are_supported.rs:9:18\n  |\n9 | enum AnotherEnum<'a> {\n  |                  ^^\n\nerror: Const generics not supported\n  --> tests/ui/derive/parameterize/only_generic_types_are_supported.rs:14:19\n   |\n14 | struct SomeStruct<const T: usize> {}\n   |                   ^^^^^^^^^^^^^^\n\nerror: Lifetimes not supported\n  --> tests/ui/derive/parameterize/only_generic_types_are_supported.rs:17:22\n   |\n17 | struct AnotherStruct<'a> {\n   |                      ^^\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/derive/parameterize/only_one_variant_element_supported.rs",
    "content": "use fuels_macros::Parameterize;\n\n#[derive(Parameterize)]\nenum SomeEnum {\n    // problem because no elements present\n    B(),\n}\n\n#[derive(Parameterize)]\nenum AnotherEnum {\n    A(u64, u32),\n}\n\nfn main() {}\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/derive/parameterize/only_one_variant_element_supported.stderr",
    "content": "error: must have exactly one element\n --> tests/ui/derive/parameterize/only_one_variant_element_supported.rs:6:6\n  |\n6 |     B(),\n  |      ^^\n\nerror: must have exactly one element\n  --> tests/ui/derive/parameterize/only_one_variant_element_supported.rs:11:6\n   |\n11 |     A(u64, u32),\n   |      ^^^^^^^^^^\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/derive/parameterize/struct_like_enum_variants_not_supported.rs",
    "content": "use fuels_macros::Parameterize;\n\n#[derive(Parameterize)]\nenum SomeEnum {\n    A,\n    B { something: u64 },\n}\n\nfn main() {}\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/derive/parameterize/struct_like_enum_variants_not_supported.stderr",
    "content": "error: struct-like enum variants are not supported\n --> tests/ui/derive/parameterize/struct_like_enum_variants_not_supported.rs:6:7\n  |\n6 |     B { something: u64 },\n  |       ^^^^^^^^^^^^^^^^^^\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/derive/parameterize/tuple_like_structs_not_supported.rs",
    "content": "use fuels_macros::Parameterize;\n\n#[derive(Parameterize)]\nstruct SomeStruct(pub u64, pub String);\n\nfn main() {}\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/derive/parameterize/tuple_like_structs_not_supported.stderr",
    "content": "error: Tuple-like structs not supported\n --> tests/ui/derive/parameterize/tuple_like_structs_not_supported.rs:4:19\n  |\n4 | struct SomeStruct(pub u64, pub String);\n  |                   ^^^^^^^^^^^^^^^^^^^\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/derive/tokenizable/attribute_must_be_named_value.stderr",
    "content": "error: Expected name='value'\n --> tests/ui/derive/tokenizable/attribute_must_be_named_value.rs:4:3\n  |\n4 | #[FuelsTypesPath]\n  |   ^^^^^^^^^^^^^^\n\nerror: Expected string literal\n  --> tests/ui/derive/tokenizable/attribute_must_be_named_value.rs:10:20\n   |\n10 | #[FuelsTypesPath = true]\n   |                    ^^^^\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/derive/tokenizable/only_generic_types_are_supported.rs",
    "content": "use fuels_macros::Tokenizable;\n\n#[derive(Tokenizable)]\nenum SomeEnum<const T: usize> {\n    A,\n}\n\n#[derive(Tokenizable)]\nenum AnotherEnum<'a> {\n    A(&'a u64),\n}\n\n#[derive(Tokenizable)]\nstruct SomeStruct<const T: usize> {}\n\n#[derive(Tokenizable)]\nstruct AnotherStruct<'a> {\n    a: &'a u64,\n}\n\nfn main() {}\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/derive/tokenizable/only_generic_types_are_supported.stderr",
    "content": "error: Const generics not supported\n --> tests/ui/derive/tokenizable/only_generic_types_are_supported.rs:4:15\n  |\n4 | enum SomeEnum<const T: usize> {\n  |               ^^^^^^^^^^^^^^\n\nerror: Lifetimes not supported\n --> tests/ui/derive/tokenizable/only_generic_types_are_supported.rs:9:18\n  |\n9 | enum AnotherEnum<'a> {\n  |                  ^^\n\nerror: Const generics not supported\n  --> tests/ui/derive/tokenizable/only_generic_types_are_supported.rs:14:19\n   |\n14 | struct SomeStruct<const T: usize> {}\n   |                   ^^^^^^^^^^^^^^\n\nerror: Lifetimes not supported\n  --> tests/ui/derive/tokenizable/only_generic_types_are_supported.rs:17:22\n   |\n17 | struct AnotherStruct<'a> {\n   |                      ^^\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/derive/tokenizable/only_one_variant_element_supported.rs",
    "content": "use fuels_macros::Tokenizable;\n\n#[derive(Tokenizable)]\nenum SomeEnum {\n    // problem because no elements present\n    B(),\n}\n\n#[derive(Tokenizable)]\nenum AnotherEnum {\n    A(u64, u32),\n}\n\nfn main() {}\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/derive/tokenizable/only_one_variant_element_supported.stderr",
    "content": "error: tuple-like enum variants must contain exactly one element\n --> tests/ui/derive/tokenizable/only_one_variant_element_supported.rs:6:6\n  |\n6 |     B(),\n  |      ^^\n\nerror: tuple-like enum variants must contain exactly one element\n  --> tests/ui/derive/tokenizable/only_one_variant_element_supported.rs:11:6\n   |\n11 |     A(u64, u32),\n   |      ^^^^^^^^^^\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/derive/tokenizable/struct_like_enum_variants_not_supported.rs",
    "content": "use fuels_macros::Tokenizable;\n\n#[derive(Tokenizable)]\nenum SomeEnum {\n    A,\n    B { something: u64 },\n}\n\nfn main() {}\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/derive/tokenizable/struct_like_enum_variants_not_supported.stderr",
    "content": "error: struct like enum variants are not supported\n --> tests/ui/derive/tokenizable/struct_like_enum_variants_not_supported.rs:6:7\n  |\n6 |     B { something: u64 },\n  |       ^^^^^^^^^^^^^^^^^^\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/derive/tokenizable/tuple_like_structs_not_supported.rs",
    "content": "use fuels_macros::Tokenizable;\n\n#[derive(Tokenizable)]\nstruct SomeStruct(pub u64, pub String);\n\nfn main() {}\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/derive/tokenizable/tuple_like_structs_not_supported.stderr",
    "content": "error: Tuple-like structs not supported\n --> tests/ui/derive/tokenizable/tuple_like_structs_not_supported.rs:4:19\n  |\n4 | struct SomeStruct(pub u64, pub String);\n  |                   ^^^^^^^^^^^^^^^^^^^\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/setup_program_test/abigen_command_is_missing.rs",
    "content": "use fuels_macros::setup_program_test;\n\nsetup_program_test!(Deploy(\n    name = \"some_instance\",\n    contract = \"SomeUnknownContract\",\n    wallet = \"some_wallet\"\n));\n\nfn main() {}\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/setup_program_test/abigen_command_is_missing.stderr",
    "content": "error: Add an `Abigen(..)` command!\n --> tests/ui/setup_program_test/abigen_command_is_missing.rs:3:21\n  |\n3 | setup_program_test!(Deploy(\n  |                     ^^^^^^\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/setup_program_test/duplicate_wallet_command.rs",
    "content": "use fuels_macros::setup_program_test;\n\nsetup_program_test!(\n    Wallets(\"wallet1\"),\n    Wallets(\"wallet2\"),\n    Abigen(Contract(name = \"MyContract\", project = \"some_project\"))\n);\n\nfn main() {}\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/setup_program_test/duplicate_wallet_command.stderr",
    "content": "error: Only one `Wallets` command allowed\n --> tests/ui/setup_program_test/duplicate_wallet_command.rs:4:5\n  |\n4 |     Wallets(\"wallet1\"),\n  |     ^^^^^^^\n\nerror: Only one `Wallets` command allowed\n --> tests/ui/setup_program_test/duplicate_wallet_command.rs:5:5\n  |\n5 |     Wallets(\"wallet2\"),\n  |     ^^^^^^^\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/setup_program_test/duplicate_wallet_names.rs",
    "content": "use fuels_macros::setup_program_test;\n\nsetup_program_test!(\n    Wallets(\"wallet1\", \"wallet1\"),\n    Abigen(Contract(name = \"MyContract\", project = \"some_project\"))\n);\n\nfn main() {}\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/setup_program_test/duplicate_wallet_names.stderr",
    "content": "error: original defined here:\n --> tests/ui/setup_program_test/duplicate_wallet_names.rs:4:13\n  |\n4 |     Wallets(\"wallet1\", \"wallet1\"),\n  |             ^^^^^^^^^\n\nerror: duplicate!\n --> tests/ui/setup_program_test/duplicate_wallet_names.rs:4:24\n  |\n4 |     Wallets(\"wallet1\", \"wallet1\"),\n  |                        ^^^^^^^^^\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/setup_program_test/invalid_path.rs",
    "content": "use fuels_macros::setup_program_test;\n\nsetup_program_test!(Abigen(Contract(\n    name = \"MyContract\",\n    project = \"some_project\"\n)));\n\nfn main() {}\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/setup_program_test/invalid_path.stderr",
    "content": "error: unable to canonicalize forc project path. Make sure the path is valid!\n --> tests/ui/setup_program_test/invalid_path.rs:5:15\n  |\n5 |     project = \"some_project\"\n  |               ^^^^^^^^^^^^^^\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/setup_program_test/invalid_project_path.rs",
    "content": "use fuels_macros::setup_program_test;\n\nsetup_program_test!(Abigen(Contract(name = \"MyContract\", project = \".\")));\n\nfn main() {}\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/setup_program_test/invalid_project_path.stderr",
    "content": "error: failed to read `abi` file with path $WORKSPACE/target/tests/trybuild/fuels-macros/out/release/fuels-macros-abi.json: No such file or directory (os error 2)\n --> tests/ui/setup_program_test/invalid_project_path.rs:3:68\n  |\n3 | setup_program_test!(Abigen(Contract(name = \"MyContract\", project = \".\")));\n  |                                                                    ^^^\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/setup_program_test/unknown_command.rs",
    "content": "use fuels_macros::setup_program_test;\n\nsetup_program_test!(\n    Abigen(Contract(project = \"some_project\", name = \"SomeContract\")),\n    Deploy(\n        name = \"some_instance\",\n        contract = \"SomeContract\",\n        wallet = \"some_wallet\"\n    ),\n    UnknownCommand()\n);\n\nfn main() {}\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/setup_program_test/unknown_command.stderr",
    "content": "error: Unrecognized command. Expected one of: 'Options', 'Wallets', 'Abigen', 'Deploy', 'LoadScript'\n  --> tests/ui/setup_program_test/unknown_command.rs:10:5\n   |\n10 |     UnknownCommand()\n   |     ^^^^^^^^^^^^^^\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/setup_program_test/unknown_contract.rs",
    "content": "use fuels_macros::setup_program_test;\n\nsetup_program_test!(\n    Abigen(Contract(project = \"some_project\", name = \"MismatchedName\")),\n    Deploy(\n        name = \"some_instance\",\n        contract = \"SomeUnknownContract\",\n        wallet = \"some_wallet\"\n    )\n);\n\nfn main() {}\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/setup_program_test/unknown_contract.stderr",
    "content": "error: Contract is unknown\n --> tests/ui/setup_program_test/unknown_contract.rs:7:20\n  |\n7 |         contract = \"SomeUnknownContract\",\n  |                    ^^^^^^^^^^^^^^^^^^^^^\n\nerror: Consider adding: Contract(name=\"SomeUnknownContract\", project=...)\n --> tests/ui/setup_program_test/unknown_contract.rs:4:5\n  |\n4 |     Abigen(Contract(project = \"some_project\", name = \"MismatchedName\")),\n  |     ^^^^^^\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/setup_program_test/unknown_options_key.rs",
    "content": "use fuels_macros::setup_program_test;\n\nsetup_program_test!(Options(unknown = \"debug\"));\n\nfn main() {}\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/setup_program_test/unknown_options_key.stderr",
    "content": "error: attribute 'unknown' not recognized. Expected one of: 'profile'\n --> tests/ui/setup_program_test/unknown_options_key.rs:3:29\n  |\n3 | setup_program_test!(Options(unknown = \"debug\"));\n  |                             ^^^^^^^\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/setup_program_test/unknown_options_value.rs",
    "content": "use fuels_macros::setup_program_test;\n\nsetup_program_test!(Options(profile = \"not_a_profile\"));\n\nfn main() {}\n"
  },
  {
    "path": "packages/fuels-macros/tests/ui/setup_program_test/unknown_options_value.stderr",
    "content": "error: invalid build profile option: must be \"debug\" or \"release\"\n --> tests/ui/setup_program_test/unknown_options_value.rs:3:39\n  |\n3 | setup_program_test!(Options(profile = \"not_a_profile\"));\n  |                                       ^^^^^^^^^^^^^^^\n"
  },
  {
    "path": "packages/fuels-programs/Cargo.toml",
    "content": "[package]\nname = \"fuels-programs\"\nversion = { workspace = true }\nauthors = { workspace = true }\nedition = { workspace = true }\nhomepage = { workspace = true }\nlicense = { workspace = true }\nrepository = { workspace = true }\nrust-version = { workspace = true }\ndescription = \"Fuel Rust SDK contracts.\"\n\n[dependencies]\nasync-trait = { workspace = true, default-features = false }\nfuel-abi-types = { workspace = true }\nfuel-asm = { workspace = true }\nfuel-tx = { workspace = true }\nfuel-types = { workspace = true, features = [\"default\"] }\nfuels-accounts = { workspace = true }\nfuels-core = { workspace = true }\nitertools = { workspace = true }\nrand = { workspace = true }\nserde_json = { workspace = true }\ntokio = { workspace = true }\n\n[dev-dependencies]\ntempfile = \"3.8.1\"\ntest-case = { workspace = true }\n\n[features]\ndefault = [\"std\"]\nstd = [\"fuels-core/std\", \"fuels-accounts/std\"]\nfault-proving = [\"fuels-core/fault-proving\", \"fuels-accounts/fault-proving\"]\n"
  },
  {
    "path": "packages/fuels-programs/src/assembly/contract_call.rs",
    "content": "use fuel_asm::{Instruction, RegId, Word, op};\nuse fuel_tx::{AssetId, ContractId};\nuse fuels_core::{constants::WORD_SIZE, error, types::errors::Result};\n\nuse super::cursor::WasmFriendlyCursor;\n#[derive(Debug)]\n\npub struct ContractCallInstructions {\n    instructions: Vec<Instruction>,\n    gas_fwd: bool,\n}\n\nimpl IntoIterator for ContractCallInstructions {\n    type Item = Instruction;\n    type IntoIter = std::vec::IntoIter<Instruction>;\n    fn into_iter(self) -> Self::IntoIter {\n        self.instructions.into_iter()\n    }\n}\n\nimpl ContractCallInstructions {\n    pub fn new(opcode_params: CallOpcodeParamsOffset) -> Self {\n        Self {\n            gas_fwd: opcode_params.gas_forwarded_offset.is_some(),\n            instructions: Self::generate_instructions(opcode_params),\n        }\n    }\n\n    pub fn into_bytes(self) -> impl Iterator<Item = u8> {\n        self.instructions\n            .into_iter()\n            .flat_map(|instruction| instruction.to_bytes())\n    }\n\n    /// Returns the VM instructions for calling a contract method\n    /// We use the [`Opcode`] to call a contract: [`CALL`](Opcode::CALL)\n    /// pointing at the following registers:\n    ///\n    /// 0x10 Script data offset\n    /// 0x11 Coin amount\n    /// 0x12 Asset ID\n    /// 0x13 Gas forwarded\n    ///\n    /// Note that these are soft rules as we're picking this addresses simply because they\n    /// non-reserved register.\n    fn generate_instructions(offsets: CallOpcodeParamsOffset) -> Vec<Instruction> {\n        let call_data_offset = offsets\n            .call_data_offset\n            .try_into()\n            .expect(\"call_data_offset out of range\");\n        let amount_offset = offsets\n            .amount_offset\n            .try_into()\n            .expect(\"amount_offset out of range\");\n        let asset_id_offset = offsets\n            .asset_id_offset\n            .try_into()\n            .expect(\"asset_id_offset out of range\");\n\n        let mut instructions = [\n            op::movi(0x10, call_data_offset),\n            op::movi(0x11, amount_offset),\n            op::lw(0x11, 0x11, 0),\n            op::movi(0x12, asset_id_offset),\n        ]\n        .to_vec();\n\n        match offsets.gas_forwarded_offset {\n            Some(gas_forwarded_offset) => {\n                let gas_forwarded_offset = gas_forwarded_offset\n                    .try_into()\n                    .expect(\"gas_forwarded_offset out of range\");\n\n                instructions.extend(&[\n                    op::movi(0x13, gas_forwarded_offset),\n                    op::lw(0x13, 0x13, 0),\n                    op::call(0x10, 0x11, 0x12, 0x13),\n                ]);\n            }\n            // if `gas_forwarded` was not set use `REG_CGAS`\n            None => instructions.push(op::call(0x10, 0x11, 0x12, RegId::CGAS)),\n        };\n\n        instructions\n    }\n\n    fn extract_normal_variant(instructions: &[Instruction]) -> Option<&[Instruction]> {\n        let normal_instructions = Self::generate_instructions(CallOpcodeParamsOffset {\n            call_data_offset: 0,\n            amount_offset: 0,\n            asset_id_offset: 0,\n            gas_forwarded_offset: None,\n        });\n        Self::extract_if_match(instructions, &normal_instructions)\n    }\n\n    fn extract_gas_fwd_variant(instructions: &[Instruction]) -> Option<&[Instruction]> {\n        let gas_fwd_instructions = Self::generate_instructions(CallOpcodeParamsOffset {\n            call_data_offset: 0,\n            amount_offset: 0,\n            asset_id_offset: 0,\n            gas_forwarded_offset: Some(0),\n        });\n        Self::extract_if_match(instructions, &gas_fwd_instructions)\n    }\n\n    pub fn extract_from(instructions: &[Instruction]) -> Option<Self> {\n        if let Some(instructions) = Self::extract_normal_variant(instructions) {\n            return Some(Self {\n                instructions: instructions.to_vec(),\n                gas_fwd: false,\n            });\n        }\n\n        Self::extract_gas_fwd_variant(instructions).map(|instructions| Self {\n            instructions: instructions.to_vec(),\n            gas_fwd: true,\n        })\n    }\n\n    pub fn len(&self) -> usize {\n        self.instructions.len()\n    }\n\n    pub fn call_data_offset(&self) -> u32 {\n        let Instruction::MOVI(movi) = self.instructions[0] else {\n            panic!(\"should have validated the first instruction is a MOVI\");\n        };\n\n        movi.imm18().into()\n    }\n\n    pub fn is_gas_fwd_variant(&self) -> bool {\n        self.gas_fwd\n    }\n\n    fn extract_if_match<'a>(\n        unknown: &'a [Instruction],\n        correct: &[Instruction],\n    ) -> Option<&'a [Instruction]> {\n        if unknown.len() < correct.len() {\n            return None;\n        }\n\n        unknown\n            .iter()\n            .zip(correct)\n            .all(|(expected, actual)| expected.opcode() == actual.opcode())\n            .then(|| &unknown[..correct.len()])\n    }\n}\n\n#[derive(Debug, Clone, PartialEq, Eq)]\npub struct ContractCallData {\n    pub amount: u64,\n    pub asset_id: AssetId,\n    pub contract_id: ContractId,\n    pub fn_selector_encoded: Vec<u8>,\n    pub encoded_args: Vec<u8>,\n    pub gas_forwarded: Option<u64>,\n}\n\nimpl ContractCallData {\n    pub fn decode_fn_selector(&self) -> Result<String> {\n        String::from_utf8(self.fn_selector_encoded.clone())\n            .map_err(|e| error!(Codec, \"cannot decode function selector: {}\", e))\n    }\n\n    /// Encodes as script data, consisting of the following items in the given order:\n    /// 1. Amount to be forwarded `(1 * `[`WORD_SIZE`]`)`\n    /// 2. Asset ID to be forwarded ([`AssetId::LEN`])\n    /// 3. Contract ID ([`ContractId::LEN`]);\n    /// 4. Function selector offset `(1 * `[`WORD_SIZE`]`)`\n    /// 5. Calldata offset `(1 * `[`WORD_SIZE`]`)`\n    /// 6. Encoded function selector - method name\n    /// 7. Encoded arguments\n    /// 8. Gas to be forwarded `(1 * `[`WORD_SIZE`]`)` - Optional\n    pub fn encode(&self, memory_offset: usize, buffer: &mut Vec<u8>) -> CallOpcodeParamsOffset {\n        let amount_offset = memory_offset;\n        let asset_id_offset = amount_offset + WORD_SIZE;\n        let call_data_offset = asset_id_offset + AssetId::LEN;\n        let encoded_selector_offset = call_data_offset + ContractId::LEN + 2 * WORD_SIZE;\n        let encoded_args_offset = encoded_selector_offset + self.fn_selector_encoded.len();\n\n        buffer.extend(self.amount.to_be_bytes()); // 1. Amount\n\n        let asset_id = self.asset_id;\n        buffer.extend(asset_id.iter()); // 2. Asset ID\n\n        buffer.extend(self.contract_id.as_ref()); // 3. Contract ID\n\n        buffer.extend((encoded_selector_offset as Word).to_be_bytes()); // 4. Fun. selector offset\n\n        buffer.extend((encoded_args_offset as Word).to_be_bytes()); // 5. Calldata offset\n\n        buffer.extend(&self.fn_selector_encoded); // 6. Encoded function selector\n\n        let encoded_args_len = self.encoded_args.len();\n\n        buffer.extend(&self.encoded_args); // 7. Encoded arguments\n\n        let gas_forwarded_offset = self.gas_forwarded.map(|gf| {\n            buffer.extend((gf as Word).to_be_bytes()); // 8. Gas to be forwarded - Optional\n\n            encoded_args_offset + encoded_args_len\n        });\n\n        CallOpcodeParamsOffset {\n            amount_offset,\n            asset_id_offset,\n            gas_forwarded_offset,\n            call_data_offset,\n        }\n    }\n\n    pub fn decode(data: &[u8], gas_fwd: bool) -> Result<Self> {\n        let mut data = WasmFriendlyCursor::new(data);\n\n        let amount = u64::from_be_bytes(data.consume_fixed(\"amount\")?);\n\n        let asset_id = AssetId::new(data.consume_fixed(\"asset id\")?);\n\n        let contract_id = ContractId::new(data.consume_fixed(\"contract id\")?);\n\n        let _ = data.consume(8, \"function selector offset\")?;\n\n        let _ = data.consume(8, \"encoded args offset\")?;\n\n        let fn_selector = {\n            let fn_selector_len = {\n                let bytes = data.consume_fixed(\"function selector length\")?;\n                u64::from_be_bytes(bytes) as usize\n            };\n            data.consume(fn_selector_len, \"function selector\")?.to_vec()\n        };\n\n        let (encoded_args, gas_forwarded) = if gas_fwd {\n            let encoded_args = data\n                .consume(data.unconsumed().saturating_sub(WORD_SIZE), \"encoded_args\")?\n                .to_vec();\n\n            let gas_fwd = { u64::from_be_bytes(data.consume_fixed(\"forwarded gas\")?) };\n\n            (encoded_args, Some(gas_fwd))\n        } else {\n            (data.consume_all().to_vec(), None)\n        };\n\n        Ok(ContractCallData {\n            amount,\n            asset_id,\n            contract_id,\n            fn_selector_encoded: fn_selector,\n            encoded_args,\n            gas_forwarded,\n        })\n    }\n}\n\n#[derive(Default)]\n/// Specifies offsets of [`Opcode::CALL`][`fuel_asm::Opcode::CALL`] parameters stored in the script\n/// data from which they can be loaded into registers\npub struct CallOpcodeParamsOffset {\n    pub call_data_offset: usize,\n    pub amount_offset: usize,\n    pub asset_id_offset: usize,\n    pub gas_forwarded_offset: Option<usize>,\n}\n\n// Creates a contract that loads the specified blobs into memory and delegates the call to the code contained in the blobs.\npub fn loader_contract_asm(blob_ids: &[[u8; 32]]) -> Result<Vec<u8>> {\n    const BLOB_ID_SIZE: u16 = 32;\n    let get_instructions = |num_of_instructions, num_of_blobs| {\n        // There are 2 main steps:\n        // 1. Load the blob contents into memory\n        // 2. Jump to the beginning of the memory where the blobs were loaded\n        // After that the execution continues normally with the loaded contract reading our\n        // prepared fn selector and jumps to the selected contract method.\n        [\n            // 1. Load the blob contents into memory\n            // Find the start of the hardcoded blob IDs, which are located after the code ends.\n            op::move_(0x10, RegId::PC),\n            // 0x10 to hold the address of the current blob ID.\n            op::addi(0x10, 0x10, num_of_instructions * Instruction::SIZE as u16),\n            // The contract is going to be loaded from the current value of SP onwards, save\n            // the location into 0x16 so we can jump into it later on.\n            op::move_(0x16, RegId::SP),\n            // Loop counter.\n            op::movi(0x13, num_of_blobs),\n            // LOOP starts here.\n            // 0x11 to hold the size of the current blob.\n            op::bsiz(0x11, 0x10),\n            // Push the blob contents onto the stack.\n            op::ldc(0x10, 0, 0x11, 1),\n            // Move on to the next blob.\n            op::addi(0x10, 0x10, BLOB_ID_SIZE),\n            // Decrement the loop counter.\n            op::subi(0x13, 0x13, 1),\n            // Jump backwards (3+1) instructions if the counter has not reached 0.\n            op::jnzb(0x13, RegId::ZERO, 3),\n            // 2. Jump into the memory where the contract is loaded.\n            // What follows is called _jmp_mem by the sway compiler.\n            // Subtract the address contained in IS because jmp will add it back.\n            op::sub(0x16, 0x16, RegId::IS),\n            // jmp will multiply by 4, so we need to divide to cancel that out.\n            op::divi(0x16, 0x16, 4),\n            // Jump to the start of the contract we loaded.\n            op::jmp(0x16),\n        ]\n    };\n\n    let num_of_instructions = u16::try_from(get_instructions(0, 0).len())\n        .expect(\"to never have more than u16::MAX instructions\");\n\n    let num_of_blobs = u32::try_from(blob_ids.len()).map_err(|_| {\n        error!(\n            Other,\n            \"the number of blobs ({}) exceeds the maximum number of blobs supported: {}\",\n            blob_ids.len(),\n            u32::MAX\n        )\n    })?;\n\n    let instruction_bytes = get_instructions(num_of_instructions, num_of_blobs)\n        .into_iter()\n        .flat_map(|instruction| instruction.to_bytes());\n\n    let blob_bytes = blob_ids.iter().flatten().copied();\n\n    Ok(instruction_bytes.chain(blob_bytes).collect())\n}\n"
  },
  {
    "path": "packages/fuels-programs/src/assembly/cursor.rs",
    "content": "use fuels_core::{error, types::errors::Result};\n\npub struct WasmFriendlyCursor<'a> {\n    data: &'a [u8],\n}\n\nimpl<'a> WasmFriendlyCursor<'a> {\n    pub fn new(data: &'a [u8]) -> Self {\n        Self { data }\n    }\n\n    pub fn consume(&mut self, amount: usize, ctx: &'static str) -> Result<&'a [u8]> {\n        if self.data.len() < amount {\n            Err(error!(\n                Other,\n                \"while decoding {ctx}: not enough data, available: {}, requested: {}\",\n                self.data.len(),\n                amount\n            ))\n        } else {\n            let data = &self.data[..amount];\n            self.data = &self.data[amount..];\n            Ok(data)\n        }\n    }\n\n    pub fn consume_fixed<const AMOUNT: usize>(\n        &mut self,\n        ctx: &'static str,\n    ) -> Result<[u8; AMOUNT]> {\n        let data = self\n            .consume(AMOUNT, ctx)?\n            .try_into()\n            .expect(\"should have failed if not enough data\");\n\n        Ok(data)\n    }\n\n    pub fn consume_all(&mut self) -> &'a [u8] {\n        let data = self.data;\n\n        self.data = &[];\n\n        data\n    }\n\n    pub fn unconsumed(&self) -> usize {\n        self.data.len()\n    }\n}\n"
  },
  {
    "path": "packages/fuels-programs/src/assembly/script_and_predicate_loader.rs",
    "content": "//! # Loader Module\n//!\n//! This module provides functionality for loading and processing binaries generated by Sway.\n//! **Important:** All functions within this module assume the binary adheres to the structure\n//! produced by Sway. Using binaries generated by other means (e.g., manually constructed binaries)\n//! may lead to unexpected or incorrect results.\n//!\n//! For more information on Sway, please visit the [Sway GitHub repository](https://github.com/FuelLabs/sway).\n\nuse fuel_asm::{Instruction, RegId, op};\nuse fuels_core::{constants::WORD_SIZE, types::errors::Result};\nuse itertools::Itertools;\n\nuse crate::assembly::cursor::WasmFriendlyCursor;\n\npub struct LoaderCode {\n    blob_id: [u8; 32],\n    code: Vec<u8>,\n    section_offset: usize,\n}\n\nimpl LoaderCode {\n    // std gated because of Blob usage which is in transaction_builders which are currently not\n    // nostd friendly\n    #[cfg(feature = \"std\")]\n    pub fn from_normal_binary(binary: Vec<u8>) -> Result<Self> {\n        let (original_code, split_section) = split_for_loader(&binary)?;\n\n        let blob_id =\n            fuels_core::types::transaction_builders::Blob::from(original_code.to_vec()).id();\n        let (loader_code, section_offset) = Self::generate_loader_code(blob_id, split_section);\n\n        Ok(Self {\n            blob_id,\n            code: loader_code,\n            section_offset,\n        })\n    }\n\n    pub fn from_loader_binary(binary: &[u8]) -> Result<Option<Self>> {\n        if let Some((blob_id, section_offset)) = extract_blob_id_and_section_offset(binary)? {\n            Ok(Some(Self {\n                section_offset,\n                code: binary.to_vec(),\n                blob_id,\n            }))\n        } else {\n            Ok(None)\n        }\n    }\n\n    #[cfg(feature = \"std\")]\n    pub fn extract_blob(binary: &[u8]) -> Result<fuels_core::types::transaction_builders::Blob> {\n        let (code, _) = split_for_loader(binary)?;\n        Ok(code.to_vec().into())\n    }\n\n    pub fn as_bytes(&self) -> &[u8] {\n        &self.code\n    }\n\n    pub fn configurables_section_offset(&self) -> usize {\n        self.section_offset\n    }\n\n    fn generate_loader_code(blob_id: [u8; 32], split_section: &[u8]) -> (Vec<u8>, usize) {\n        if !split_section.is_empty() {\n            generate_loader_w_configurables(blob_id, split_section)\n        } else {\n            generate_loader_wo_configurables(blob_id)\n        }\n    }\n\n    pub fn blob_id(&self) -> [u8; 32] {\n        self.blob_id\n    }\n}\n\nfn extract_blob_id_and_section_offset(binary: &[u8]) -> Result<Option<([u8; 32], usize)>> {\n    let (has_configurables, mut cursor) = if let Some(cursor) =\n        consume_instructions(binary, &loader_instructions_w_configurables())\n    {\n        (true, cursor)\n    } else if let Some(cursor) =\n        consume_instructions(binary, &loader_instructions_no_configurables())\n    {\n        (false, cursor)\n    } else {\n        return Ok(None);\n    };\n\n    let blob_id = cursor.consume_fixed(\"blob id\")?;\n    if has_configurables {\n        let _section_len = cursor.consume(WORD_SIZE, \"section with configurables len\")?;\n    }\n\n    let section_offset = binary\n        .len()\n        .checked_sub(cursor.unconsumed())\n        .expect(\"must be less or eq\");\n\n    Ok(Some((blob_id, section_offset)))\n}\n\nfn consume_instructions<'a>(\n    binary: &'a [u8],\n    expected_instructions: &[Instruction],\n) -> Option<WasmFriendlyCursor<'a>> {\n    let loader_instructions_byte_size = expected_instructions.len() * Instruction::SIZE;\n\n    let mut script_cursor = WasmFriendlyCursor::new(binary);\n    let instruction_bytes = script_cursor\n        .consume(loader_instructions_byte_size, \"loader instructions\")\n        .ok()?;\n\n    let instructions = fuel_asm::from_bytes(instruction_bytes.to_vec())\n        .collect::<std::result::Result<Vec<Instruction>, _>>()\n        .ok()?;\n\n    instructions\n        .iter()\n        .zip(expected_instructions.iter())\n        .all(|(actual, expected)| actual == expected)\n        .then_some(script_cursor)\n}\n\nfn generate_loader_wo_configurables(blob_id: [u8; 32]) -> (Vec<u8>, usize) {\n    let instruction_bytes = loader_instructions_no_configurables()\n        .into_iter()\n        .flat_map(|instruction| instruction.to_bytes());\n\n    let code = instruction_bytes\n        .chain(blob_id.iter().copied())\n        .collect_vec();\n    // there is no data section, so we point the offset to the end of the file\n    let new_section_offset = code.len();\n\n    (code, new_section_offset)\n}\n\nfn generate_loader_w_configurables(\n    blob_id: [u8; 32],\n    section_w_configurables: &[u8],\n) -> (Vec<u8>, usize) {\n    // The final code is going to have this structure:\n    // 1. loader instructions\n    // 2. blob id\n    // 3. length_of_section_containing_configurables\n    // 4. the section with configurables (updated with configurables as needed)\n\n    let instruction_bytes = loader_instructions_w_configurables()\n        .into_iter()\n        .flat_map(|instruction| instruction.to_bytes())\n        .collect_vec();\n\n    let blob_bytes = blob_id.iter().copied().collect_vec();\n\n    let original_section_len_encoded = u64::try_from(section_w_configurables.len())\n        .expect(\"data section to be less than u64::MAX\")\n        .to_be_bytes();\n\n    // The section with configurables is placed after all of the instructions, the BlobId, and the number representing\n    // how big the data section is.\n    let new_section_offset =\n        instruction_bytes.len() + blob_bytes.len() + original_section_len_encoded.len();\n\n    let code = instruction_bytes\n        .into_iter()\n        .chain(blob_bytes)\n        .chain(original_section_len_encoded)\n        .chain(section_w_configurables.to_vec())\n        .collect();\n\n    (code, new_section_offset)\n}\n\nfn loader_instructions_no_configurables() -> [Instruction; 8] {\n    const REG_ADDRESS_OF_DATA_AFTER_CODE: u8 = 0x10;\n    const REG_START_OF_LOADED_CODE: u8 = 0x11;\n    const REG_GENERAL_USE: u8 = 0x12;\n\n    const NUM_OF_INSTRUCTIONS: u16 = 8;\n\n    // There are 2 main steps:\n    // 1. Load the blob content into memory\n    // 2. Jump to the beginning of the memory where the blob was loaded\n    let instructions = [\n        // 1. Load the blob content into memory\n        // Find the start of the hardcoded blob ID, which is located after the loader code ends.\n        op::move_(REG_ADDRESS_OF_DATA_AFTER_CODE, RegId::PC),\n        // hold the address of the blob ID.\n        op::addi(\n            REG_ADDRESS_OF_DATA_AFTER_CODE,\n            REG_ADDRESS_OF_DATA_AFTER_CODE,\n            NUM_OF_INSTRUCTIONS * Instruction::SIZE as u16,\n        ),\n        // The code is going to be loaded from the current value of SP onwards, save\n        // the location into REG_START_OF_LOADED_CODE so we can jump into it at the end.\n        op::move_(REG_START_OF_LOADED_CODE, RegId::SP),\n        // REG_GENERAL_USE to hold the size of the blob.\n        op::bsiz(REG_GENERAL_USE, REG_ADDRESS_OF_DATA_AFTER_CODE),\n        // Push the blob contents onto the stack.\n        op::ldc(REG_ADDRESS_OF_DATA_AFTER_CODE, 0, REG_GENERAL_USE, 1),\n        // Jump into the memory where the contract is loaded.\n        // What follows is called _jmp_mem by the sway compiler.\n        // Subtract the address contained in IS because jmp will add it back.\n        op::sub(\n            REG_START_OF_LOADED_CODE,\n            REG_START_OF_LOADED_CODE,\n            RegId::IS,\n        ),\n        // jmp will multiply by 4, so we need to divide to cancel that out.\n        op::divi(REG_START_OF_LOADED_CODE, REG_START_OF_LOADED_CODE, 4),\n        // Jump to the start of the contract we loaded.\n        op::jmp(REG_START_OF_LOADED_CODE),\n    ];\n\n    debug_assert_eq!(instructions.len(), NUM_OF_INSTRUCTIONS as usize);\n\n    instructions\n}\n\npub fn loader_instructions_w_configurables() -> [Instruction; 12] {\n    const BLOB_ID_SIZE: u16 = 32;\n    const REG_ADDRESS_OF_DATA_AFTER_CODE: u8 = 0x10;\n    const REG_START_OF_LOADED_CODE: u8 = 0x11;\n    const REG_GENERAL_USE: u8 = 0x12;\n\n    // extract the length of the NoDataSectionLoaderInstructions type\n    const NUM_OF_INSTRUCTIONS: u16 = 12;\n\n    // There are 3 main steps:\n    // 1. Load the blob content into memory\n    // 2. Load the data section right after the blob\n    // 3. Jump to the beginning of the memory where the blob was loaded\n    let instructions = [\n        // 1. Load the blob content into memory\n        // Find the start of the hardcoded blob ID, which is located after the loader code ends.\n        op::move_(REG_ADDRESS_OF_DATA_AFTER_CODE, RegId::PC),\n        // hold the address of the blob ID.\n        op::addi(\n            REG_ADDRESS_OF_DATA_AFTER_CODE,\n            REG_ADDRESS_OF_DATA_AFTER_CODE,\n            NUM_OF_INSTRUCTIONS * Instruction::SIZE as u16,\n        ),\n        // The code is going to be loaded from the current value of SP onwards, save\n        // the location into REG_START_OF_LOADED_CODE so we can jump into it at the end.\n        op::move_(REG_START_OF_LOADED_CODE, RegId::SP),\n        // REG_GENERAL_USE to hold the size of the blob.\n        op::bsiz(REG_GENERAL_USE, REG_ADDRESS_OF_DATA_AFTER_CODE),\n        // Push the blob contents onto the stack.\n        op::ldc(REG_ADDRESS_OF_DATA_AFTER_CODE, 0, REG_GENERAL_USE, 1),\n        // Move on to the data section length\n        op::addi(\n            REG_ADDRESS_OF_DATA_AFTER_CODE,\n            REG_ADDRESS_OF_DATA_AFTER_CODE,\n            BLOB_ID_SIZE,\n        ),\n        // load the size of the data section into REG_GENERAL_USE\n        op::lw(REG_GENERAL_USE, REG_ADDRESS_OF_DATA_AFTER_CODE, 0),\n        // after we have read the length of the data section, we move the pointer to the actual\n        // data by skipping WORD_SIZE B.\n        op::addi(\n            REG_ADDRESS_OF_DATA_AFTER_CODE,\n            REG_ADDRESS_OF_DATA_AFTER_CODE,\n            WORD_SIZE as u16,\n        ),\n        // load the data section of the executable\n        op::ldc(REG_ADDRESS_OF_DATA_AFTER_CODE, 0, REG_GENERAL_USE, 2),\n        // Jump into the memory where the contract is loaded.\n        // What follows is called _jmp_mem by the sway compiler.\n        // Subtract the address contained in IS because jmp will add it back.\n        op::sub(\n            REG_START_OF_LOADED_CODE,\n            REG_START_OF_LOADED_CODE,\n            RegId::IS,\n        ),\n        // jmp will multiply by 4, so we need to divide to cancel that out.\n        op::divi(REG_START_OF_LOADED_CODE, REG_START_OF_LOADED_CODE, 4),\n        // Jump to the start of the contract we loaded.\n        op::jmp(REG_START_OF_LOADED_CODE),\n    ];\n\n    debug_assert_eq!(instructions.len(), NUM_OF_INSTRUCTIONS as usize);\n\n    instructions\n}\n\npub fn extract_configurables_offset(binary: &[u8]) -> Result<usize> {\n    if binary.len() < 24 {\n        return Err(fuels_core::error!(\n            Other,\n            \"given binary is too short to contain a configurable offset, len: {}\",\n            binary.len()\n        ));\n    }\n\n    let configurable_offset: [u8; 8] = binary[16..24].try_into().expect(\"checked above\");\n    Ok(u64::from_be_bytes(configurable_offset) as usize)\n}\n\npub fn split_at_configurables_offset(binary: &[u8]) -> Result<(&[u8], &[u8])> {\n    let offset = extract_configurables_offset(binary)?;\n    if binary.len() < offset {\n        return Err(fuels_core::error!(\n            Other,\n            \"configurables section offset is out of bounds, offset: {offset}, binary len: {}\",\n            binary.len()\n        ));\n    }\n\n    Ok(binary.split_at(offset))\n}\n\npub fn extract_data_offset(binary: &[u8]) -> Result<usize> {\n    if binary.len() < 16 {\n        return Err(fuels_core::error!(\n            Other,\n            \"given binary is too short to contain a data offset, len: {}\",\n            binary.len()\n        ));\n    }\n\n    let data_offset: [u8; 8] = binary[8..16].try_into().expect(\"checked above\");\n    Ok(u64::from_be_bytes(data_offset) as usize)\n}\n\npub fn split_at_data_offset(binary: &[u8]) -> Result<(&[u8], &[u8])> {\n    let offset = extract_data_offset(binary)?;\n    if binary.len() < offset {\n        return Err(fuels_core::error!(\n            Other,\n            \"data section offset is out of bounds, offset: {offset}, binary len: {}\",\n            binary.len()\n        ));\n    }\n    Ok(binary.split_at(offset))\n}\n\npub fn split_for_loader(binary: &[u8]) -> Result<(&[u8], &[u8])> {\n    // First determine if it's a legacy binary\n    if has_configurables_section_offset(binary)? {\n        split_at_configurables_offset(binary)\n    } else {\n        split_at_data_offset(binary)\n    }\n}\n\npub fn get_offset_for_section_containing_configurables(binary: &[u8]) -> Result<usize> {\n    if has_configurables_section_offset(binary).unwrap_or(true) {\n        extract_configurables_offset(binary)\n    } else {\n        extract_data_offset(binary)\n    }\n}\n\npub fn has_configurables_section_offset(binary: &[u8]) -> Result<bool> {\n    let slice = binary.get(4..8).ok_or_else(|| {\n        fuels_core::error!(\n            Other,\n            \"binary too short to check JMPF instruction, need at least 8 bytes but got: {}\",\n            binary.len()\n        )\n    })?;\n\n    let instruction_bytes: [u8; 4] = slice\n        .try_into()\n        .map_err(|_| fuels_core::error!(Other, \"Failed to convert slice to [u8; 4]\"))?;\n\n    match Instruction::try_from(instruction_bytes)\n        .map_err(|e| fuels_core::error!(Other, \"Invalid instruction at byte 4: {:?}\", e))?\n    {\n        Instruction::JMPF(offset) => match offset.imm18().to_u32() {\n            0x04 => Ok(true),\n            0x02 => Ok(false),\n            other => Err(fuels_core::error!(\n                Other,\n                \"invalid JMPF offset, expected 0x02 or 0x04, got: {:#04x}\",\n                other\n            )),\n        },\n        inst => Err(fuels_core::error!(\n            Other,\n            \"expected JMPF instruction, got: {:?}\",\n            inst\n        )),\n    }\n}\n"
  },
  {
    "path": "packages/fuels-programs/src/assembly.rs",
    "content": "pub mod contract_call;\npub mod cursor;\npub mod script_and_predicate_loader;\n"
  },
  {
    "path": "packages/fuels-programs/src/calls/call_handler.rs",
    "content": "use crate::{\n    calls::{\n        CallParameters, ContractCall, Execution, ExecutionType, ScriptCall,\n        receipt_parser::ReceiptParser,\n        traits::{ContractDependencyConfigurator, ResponseParser, TransactionTuner},\n        utils::find_ids_of_missing_contracts,\n    },\n    responses::{CallResponse, SubmitResponse},\n};\nuse core::{fmt::Debug, marker::PhantomData};\nuse fuel_tx::ConsensusParameters;\nuse fuels_accounts::{Account, provider::TransactionCost};\nuse fuels_core::{\n    codec::{ABIEncoder, DecoderConfig, EncoderConfig, LogDecoder},\n    traits::{Parameterize, Signer, Tokenizable},\n    types::{\n        Address, AssetId, Bytes32, ContractId, Selector, Token,\n        errors::{Error, Result, error, transaction::Reason},\n        input::Input,\n        output::Output,\n        transaction::{ScriptTransaction, Transaction, TxPolicies},\n        transaction_builders::{\n            BuildableTransaction, ScriptBuildStrategy, ScriptTransactionBuilder,\n            TransactionBuilder, VariableOutputPolicy,\n        },\n        tx_status::TxStatus,\n    },\n};\nuse std::sync::Arc;\n\n// Trait implemented by contract instances so that\n// they can be passed to the `with_contracts` method\npub trait ContractDependency {\n    fn id(&self) -> ContractId;\n    fn log_decoder(&self) -> LogDecoder;\n}\n\n#[derive(Debug, Clone)]\n#[must_use = \"contract calls do nothing unless you `call` them\"]\n/// Helper that handles submitting a call to a client and formatting the response\npub struct CallHandler<A, C, T> {\n    pub account: A,\n    pub call: C,\n    pub tx_policies: TxPolicies,\n    pub log_decoder: LogDecoder,\n    pub datatype: PhantomData<T>,\n    decoder_config: DecoderConfig,\n    // Initially `None`, gets set to the right tx id after the transaction is submitted\n    cached_tx_id: Option<Bytes32>,\n    variable_output_policy: VariableOutputPolicy,\n    unresolved_signers: Vec<Arc<dyn Signer + Send + Sync>>,\n}\n\nimpl<A, C, T> CallHandler<A, C, T> {\n    /// Sets the transaction policies for a given transaction.\n    /// Note that this is a builder method, i.e. use it as a chain:\n    /// ```ignore\n    /// let tx_policies = TxPolicies::default().with_gas_price(100);\n    /// my_contract_instance.my_method(...).with_tx_policies(tx_policies).call()\n    /// ```\n    pub fn with_tx_policies(mut self, tx_policies: TxPolicies) -> Self {\n        self.tx_policies = tx_policies;\n        self\n    }\n\n    pub fn with_decoder_config(mut self, decoder_config: DecoderConfig) -> Self {\n        self.decoder_config = decoder_config;\n        self.log_decoder.set_decoder_config(decoder_config);\n        self\n    }\n\n    /// If this method is not called, the default policy is to not add any variable outputs.\n    ///\n    /// # Parameters\n    /// - `variable_outputs`: The [`VariableOutputPolicy`] to apply for the contract call.\n    ///\n    /// # Returns\n    /// - `Self`: The updated SDK configuration.\n    pub fn with_variable_output_policy(mut self, variable_outputs: VariableOutputPolicy) -> Self {\n        self.variable_output_policy = variable_outputs;\n        self\n    }\n\n    pub fn add_signer(mut self, signer: impl Signer + Send + Sync + 'static) -> Self {\n        self.unresolved_signers.push(Arc::new(signer));\n        self\n    }\n}\n\nimpl<A, C, T> CallHandler<A, C, T>\nwhere\n    A: Account,\n    C: TransactionTuner,\n    T: Tokenizable + Parameterize + Debug,\n{\n    pub async fn transaction_builder(&self) -> Result<ScriptTransactionBuilder> {\n        let consensus_parameters = self.account.try_provider()?.consensus_parameters().await?;\n        let required_asset_amounts = self\n            .call\n            .required_assets(*consensus_parameters.base_asset_id());\n\n        // Find the spendable resources required for those calls\n        let mut asset_inputs = vec![];\n        for &(asset_id, amount) in &required_asset_amounts {\n            let resources = self\n                .account\n                .get_asset_inputs_for_amount(asset_id, amount, None)\n                .await?;\n            asset_inputs.extend(resources);\n        }\n\n        self.transaction_builder_with_parameters(&consensus_parameters, asset_inputs)\n    }\n\n    pub fn transaction_builder_with_parameters(\n        &self,\n        consensus_parameters: &ConsensusParameters,\n        asset_inputs: Vec<Input>,\n    ) -> Result<ScriptTransactionBuilder> {\n        let mut tb = self.call.transaction_builder(\n            self.tx_policies,\n            self.variable_output_policy,\n            consensus_parameters,\n            asset_inputs,\n            &self.account,\n        )?;\n\n        tb.add_signers(&self.unresolved_signers)?;\n\n        Ok(tb)\n    }\n\n    /// Returns the script that executes the contract call\n    pub async fn build_tx(&self) -> Result<ScriptTransaction> {\n        let tb = self.transaction_builder().await?;\n\n        self.call.build_tx(tb, &self.account).await\n    }\n\n    /// Get a call's estimated cost\n    pub async fn estimate_transaction_cost(\n        &self,\n        tolerance: Option<f64>,\n        block_horizon: Option<u32>,\n    ) -> Result<TransactionCost> {\n        let tx = self.build_tx().await?;\n        let provider = self.account.try_provider()?;\n\n        let transaction_cost = provider\n            .estimate_transaction_cost(tx, tolerance, block_horizon)\n            .await?;\n\n        Ok(transaction_cost)\n    }\n}\n\nimpl<A, C, T> CallHandler<A, C, T>\nwhere\n    A: Account,\n    C: ContractDependencyConfigurator + TransactionTuner + ResponseParser,\n    T: Tokenizable + Parameterize + Debug,\n{\n    /// Sets external contracts as dependencies to this contract's call.\n    /// Effectively, this will be used to create [`fuel_tx::Input::Contract`]/[`fuel_tx::Output::Contract`]\n    /// pairs and set them into the transaction. Note that this is a builder\n    /// method, i.e. use it as a chain:\n    ///\n    /// ```ignore\n    /// my_contract_instance.my_method(...).with_contract_ids(&[another_contract_id]).call()\n    /// ```\n    ///\n    /// [`Input::Contract`]: fuel_tx::Input::Contract\n    /// [`Output::Contract`]: fuel_tx::Output::Contract\n    pub fn with_contract_ids(mut self, contract_ids: &[ContractId]) -> Self {\n        self.call = self.call.with_external_contracts(contract_ids.to_vec());\n\n        self\n    }\n\n    /// Sets external contract instances as dependencies to this contract's call.\n    /// Effectively, this will be used to: merge `LogDecoder`s and create\n    /// [`fuel_tx::Input::Contract`]/[`fuel_tx::Output::Contract`] pairs and set them into the transaction.\n    /// Note that this is a builder method, i.e. use it as a chain:\n    ///\n    /// ```ignore\n    /// my_contract_instance.my_method(...).with_contracts(&[another_contract_instance]).call()\n    /// ```\n    pub fn with_contracts(mut self, contracts: &[&dyn ContractDependency]) -> Self {\n        self.call = self\n            .call\n            .with_external_contracts(contracts.iter().map(|c| c.id()).collect());\n        for c in contracts {\n            self.log_decoder.merge(c.log_decoder());\n        }\n\n        self\n    }\n\n    /// Call a contract's method on the node, in a state-modifying manner.\n    pub async fn call(mut self) -> Result<CallResponse<T>> {\n        let tx = self.build_tx().await?;\n        let provider = self.account.try_provider()?;\n\n        let consensus_parameters = provider.consensus_parameters().await?;\n        let chain_id = consensus_parameters.chain_id();\n        self.cached_tx_id = Some(tx.id(chain_id));\n\n        let tx_status = provider.send_transaction_and_await_commit(tx).await?;\n\n        self.get_response(tx_status)\n    }\n\n    pub async fn submit(mut self) -> Result<SubmitResponse<A, C, T>> {\n        let tx = self.build_tx().await?;\n        let provider = self.account.try_provider()?;\n\n        let tx_id = provider.send_transaction(tx.clone()).await?;\n        self.cached_tx_id = Some(tx_id);\n\n        Ok(SubmitResponse::<A, C, T>::new(tx_id, self))\n    }\n\n    /// Call a contract's method on the node, in a simulated manner, meaning the state of the\n    /// blockchain is *not* modified but simulated.\n    pub async fn simulate(\n        &mut self,\n        Execution {\n            execution_type,\n            at_height,\n        }: Execution,\n    ) -> Result<CallResponse<T>> {\n        let provider = self.account.try_provider()?;\n\n        let tx_status = if let ExecutionType::StateReadOnly = execution_type {\n            let tx = self\n                .transaction_builder()\n                .await?\n                .with_build_strategy(ScriptBuildStrategy::StateReadOnly)\n                .build(provider)\n                .await?;\n\n            provider.dry_run_opt(tx, false, Some(0), at_height).await?\n        } else {\n            let tx = self.build_tx().await?;\n            provider.dry_run_opt(tx, true, None, at_height).await?\n        };\n\n        self.get_response(tx_status)\n    }\n\n    /// Create a [`CallResponse`] from `TxStatus`\n    pub fn get_response(&self, tx_status: TxStatus) -> Result<CallResponse<T>> {\n        let success = tx_status.take_success_checked(Some(&self.log_decoder))?;\n\n        let token =\n            self.call\n                .parse_call(&success.receipts, self.decoder_config, &T::param_type())?;\n\n        Ok(CallResponse {\n            value: T::from_token(token)?,\n            log_decoder: self.log_decoder.clone(),\n            tx_id: self.cached_tx_id,\n            tx_status: success,\n        })\n    }\n\n    pub async fn determine_missing_contracts(mut self) -> Result<Self> {\n        match self.simulate(Execution::realistic()).await {\n            Ok(_) => Ok(self),\n\n            Err(Error::Transaction(Reason::Failure { ref receipts, .. })) => {\n                for contract_id in find_ids_of_missing_contracts(receipts) {\n                    self.call.append_external_contract(contract_id);\n                }\n\n                Ok(self)\n            }\n\n            Err(other_error) => Err(other_error),\n        }\n    }\n}\n\nimpl<A, T> CallHandler<A, ContractCall, T>\nwhere\n    A: Account,\n    T: Tokenizable + Parameterize + Debug,\n{\n    pub fn new_contract_call(\n        contract_id: ContractId,\n        account: A,\n        encoded_selector: Selector,\n        args: &[Token],\n        log_decoder: LogDecoder,\n        is_payable: bool,\n        encoder_config: EncoderConfig,\n    ) -> Self {\n        let call = ContractCall {\n            contract_id,\n            encoded_selector,\n            encoded_args: ABIEncoder::new(encoder_config).encode(args),\n            call_parameters: CallParameters::default(),\n            external_contracts: vec![],\n            output_param: T::param_type(),\n            is_payable,\n            custom_assets: Default::default(),\n            inputs: vec![],\n            outputs: vec![],\n        };\n        CallHandler {\n            account,\n            call,\n            tx_policies: TxPolicies::default(),\n            log_decoder,\n            datatype: PhantomData,\n            decoder_config: DecoderConfig::default(),\n            cached_tx_id: None,\n            variable_output_policy: VariableOutputPolicy::default(),\n            unresolved_signers: vec![],\n        }\n    }\n\n    /// Adds a custom `asset_id` with its `amount` and an optional `address` to be used for\n    /// generating outputs to this contract's call.\n    ///\n    /// # Parameters\n    /// - `asset_id`: The unique identifier of the asset being added.\n    /// - `amount`: The amount of the asset being added.\n    /// - `address`: The optional account address that the output amount will be sent to.\n    ///   If not provided, the asset will be sent to the users account address.\n    ///\n    /// Note that this is a builder method, i.e. use it as a chain:\n    ///\n    /// ```ignore\n    /// let asset_id = AssetId::from([3u8; 32]);\n    /// let amount = 5000;\n    /// my_contract_instance.my_method(...).add_custom_asset(asset_id, amount, None).call()\n    /// ```\n    pub fn add_custom_asset(mut self, asset_id: AssetId, amount: u64, to: Option<Address>) -> Self {\n        self.call.add_custom_asset(asset_id, amount, to);\n        self\n    }\n\n    pub fn is_payable(&self) -> bool {\n        self.call.is_payable\n    }\n\n    /// Sets the call parameters for a given contract call.\n    /// Note that this is a builder method, i.e. use it as a chain:\n    ///\n    /// ```ignore\n    /// let params = CallParameters { amount: 1, asset_id: AssetId::zeroed() };\n    /// my_contract_instance.my_method(...).call_params(params).call()\n    /// ```\n    pub fn call_params(mut self, params: CallParameters) -> Result<Self> {\n        if !self.is_payable() && params.amount() > 0 {\n            return Err(error!(Other, \"assets forwarded to non-payable method\"));\n        }\n        self.call.call_parameters = params;\n\n        Ok(self)\n    }\n\n    /// Add custom outputs to the `CallHandler`. These outputs\n    /// will appear at the **start** of the final output list.\n    pub fn with_outputs(mut self, outputs: Vec<Output>) -> Self {\n        self.call = self.call.with_outputs(outputs);\n        self\n    }\n\n    /// Add custom inputs to the `CallHandler`. These inputs\n    /// will appear at the **start** of the final input list.\n    pub fn with_inputs(mut self, inputs: Vec<Input>) -> Self {\n        self.call = self.call.with_inputs(inputs);\n        self\n    }\n}\n\nimpl<A, T> CallHandler<A, ScriptCall, T>\nwhere\n    A: Account,\n    T: Parameterize + Tokenizable + Debug,\n{\n    pub fn new_script_call(\n        script_binary: Vec<u8>,\n        encoded_args: Result<Vec<u8>>,\n        account: A,\n        log_decoder: LogDecoder,\n    ) -> Self {\n        let call = ScriptCall {\n            script_binary,\n            encoded_args,\n            inputs: vec![],\n            outputs: vec![],\n            external_contracts: vec![],\n        };\n\n        Self {\n            account,\n            call,\n            tx_policies: TxPolicies::default(),\n            log_decoder,\n            datatype: PhantomData,\n            decoder_config: DecoderConfig::default(),\n            cached_tx_id: None,\n            variable_output_policy: VariableOutputPolicy::default(),\n            unresolved_signers: vec![],\n        }\n    }\n\n    /// Add custom outputs to the `CallHandler`. These outputs\n    /// will appear at the **start** of the final output list.\n    pub fn with_outputs(mut self, outputs: Vec<Output>) -> Self {\n        self.call = self.call.with_outputs(outputs);\n        self\n    }\n\n    /// Add custom inputs to the `CallHandler`. These inputs\n    /// will appear at the **start** of the final input list.\n    pub fn with_inputs(mut self, inputs: Vec<Input>) -> Self {\n        self.call = self.call.with_inputs(inputs);\n        self\n    }\n}\n\nimpl<A> CallHandler<A, Vec<ContractCall>, ()>\nwhere\n    A: Account,\n{\n    pub fn new_multi_call(account: A) -> Self {\n        Self {\n            account,\n            call: vec![],\n            tx_policies: TxPolicies::default(),\n            log_decoder: LogDecoder::new(Default::default(), Default::default()),\n            datatype: PhantomData,\n            decoder_config: DecoderConfig::default(),\n            cached_tx_id: None,\n            variable_output_policy: VariableOutputPolicy::default(),\n            unresolved_signers: vec![],\n        }\n    }\n\n    fn append_external_contract(mut self, contract_id: ContractId) -> Result<Self> {\n        if self.call.is_empty() {\n            return Err(error!(\n                Other,\n                \"no calls added. Have you used '.add_calls()'?\"\n            ));\n        }\n\n        self.call\n            .iter_mut()\n            .take(1)\n            .for_each(|call| call.append_external_contract(contract_id));\n\n        Ok(self)\n    }\n\n    /// Adds a contract call to be bundled in the transaction.\n    /// Note that if you added custom inputs/outputs that they will follow the\n    /// order in which the calls are added.\n    pub fn add_call(\n        mut self,\n        call_handler: CallHandler<impl Account, ContractCall, impl Tokenizable>,\n    ) -> Self {\n        self.log_decoder.merge(call_handler.log_decoder);\n        self.call.push(call_handler.call);\n        self.unresolved_signers\n            .extend(call_handler.unresolved_signers);\n\n        self\n    }\n\n    /// Call contract methods on the node, in a state-modifying manner.\n    pub async fn call<T: Tokenizable + Debug>(mut self) -> Result<CallResponse<T>> {\n        let tx = self.build_tx().await?;\n\n        let provider = self.account.try_provider()?;\n        let consensus_parameters = provider.consensus_parameters().await?;\n        let chain_id = consensus_parameters.chain_id();\n\n        self.cached_tx_id = Some(tx.id(chain_id));\n\n        let tx_status = provider.send_transaction_and_await_commit(tx).await?;\n\n        self.get_response(tx_status)\n    }\n\n    pub async fn submit(mut self) -> Result<SubmitResponse<A, Vec<ContractCall>, ()>> {\n        let tx = self.build_tx().await?;\n        let provider = self.account.try_provider()?;\n\n        let tx_id = provider.send_transaction(tx).await?;\n        self.cached_tx_id = Some(tx_id);\n\n        Ok(SubmitResponse::<A, Vec<ContractCall>, ()>::new(tx_id, self))\n    }\n\n    /// Call contract methods on the node, in a simulated manner, meaning the state of the\n    /// blockchain is *not* modified but simulated.\n    /// It is the same as the [call] method because the API is more user-friendly this way.\n    ///\n    /// [call]: Self::call\n    pub async fn simulate<T: Tokenizable + Debug>(\n        &mut self,\n        Execution {\n            execution_type,\n            at_height,\n        }: Execution,\n    ) -> Result<CallResponse<T>> {\n        let provider = self.account.try_provider()?;\n\n        let tx_status = if let ExecutionType::StateReadOnly = execution_type {\n            let tx = self\n                .transaction_builder()\n                .await?\n                .with_build_strategy(ScriptBuildStrategy::StateReadOnly)\n                .build(provider)\n                .await?;\n\n            provider.dry_run_opt(tx, false, Some(0), at_height).await?\n        } else {\n            let tx = self.build_tx().await?;\n            provider.dry_run_opt(tx, true, None, at_height).await?\n        };\n\n        self.get_response(tx_status)\n    }\n\n    /// Simulates a call without needing to resolve the generic for the return type\n    async fn simulate_without_decode(&self) -> Result<()> {\n        let provider = self.account.try_provider()?;\n        let tx = self.build_tx().await?;\n\n        provider.dry_run(tx).await?.check(None)?;\n\n        Ok(())\n    }\n\n    /// Create a [`CallResponse`] from `TxStatus`\n    pub fn get_response<T: Tokenizable + Debug>(\n        &self,\n        tx_status: TxStatus,\n    ) -> Result<CallResponse<T>> {\n        let success = tx_status.take_success_checked(Some(&self.log_decoder))?;\n        let mut receipt_parser = ReceiptParser::new(&success.receipts, self.decoder_config);\n\n        let final_tokens = self\n            .call\n            .iter()\n            .map(|call| receipt_parser.parse_call(call.contract_id, &call.output_param))\n            .collect::<Result<Vec<_>>>()?;\n\n        let tokens_as_tuple = Token::Tuple(final_tokens);\n\n        Ok(CallResponse {\n            value: T::from_token(tokens_as_tuple)?,\n            log_decoder: self.log_decoder.clone(),\n            tx_id: self.cached_tx_id,\n            tx_status: success,\n        })\n    }\n\n    /// Simulates the call and attempts to resolve missing contract outputs.\n    /// Forwards the received error if it cannot be fixed.\n    pub async fn determine_missing_contracts(mut self) -> Result<Self> {\n        match self.simulate_without_decode().await {\n            Ok(_) => Ok(self),\n\n            Err(Error::Transaction(Reason::Failure { ref receipts, .. })) => {\n                for contract_id in find_ids_of_missing_contracts(receipts) {\n                    self = self.append_external_contract(contract_id)?;\n                }\n\n                Ok(self)\n            }\n\n            Err(other_error) => Err(other_error),\n        }\n    }\n}\n"
  },
  {
    "path": "packages/fuels-programs/src/calls/contract_call.rs",
    "content": "use std::{collections::HashMap, fmt::Debug};\n\nuse fuels_core::{\n    constants::DEFAULT_CALL_PARAMS_AMOUNT,\n    error,\n    types::{\n        Address, AssetId, ContractId, Selector, errors::Result, input::Input, output::Output,\n        param_types::ParamType,\n    },\n};\n\nuse crate::{assembly::contract_call::ContractCallData, calls::utils::sealed};\n\n#[derive(Debug, Clone)]\n/// Contains all data relevant to a single contract call\npub struct ContractCall {\n    pub contract_id: ContractId,\n    pub encoded_args: Result<Vec<u8>>,\n    pub encoded_selector: Selector,\n    pub call_parameters: CallParameters,\n    pub external_contracts: Vec<ContractId>,\n    pub output_param: ParamType,\n    pub is_payable: bool,\n    pub custom_assets: HashMap<(AssetId, Option<Address>), u64>,\n    pub inputs: Vec<Input>,\n    pub outputs: Vec<Output>,\n}\n\nimpl ContractCall {\n    pub(crate) fn data(&self, base_asset_id: AssetId) -> Result<ContractCallData> {\n        let encoded_args = self\n            .encoded_args\n            .as_ref()\n            .map_err(|e| error!(Codec, \"cannot encode contract call arguments: {e}\"))?\n            .to_owned();\n\n        Ok(ContractCallData {\n            amount: self.call_parameters.amount(),\n            asset_id: self.call_parameters.asset_id().unwrap_or(base_asset_id),\n            contract_id: self.contract_id,\n            fn_selector_encoded: self.encoded_selector.clone(),\n            encoded_args,\n            gas_forwarded: self.call_parameters.gas_forwarded,\n        })\n    }\n\n    pub fn with_contract_id(self, contract_id: ContractId) -> Self {\n        ContractCall {\n            contract_id,\n            ..self\n        }\n    }\n\n    pub fn with_call_parameters(self, call_parameters: CallParameters) -> ContractCall {\n        ContractCall {\n            call_parameters,\n            ..self\n        }\n    }\n\n    pub fn add_custom_asset(&mut self, asset_id: AssetId, amount: u64, to: Option<Address>) {\n        *self.custom_assets.entry((asset_id, to)).or_default() += amount;\n    }\n\n    /// Add custom outputs to the `ContractCall`.\n    pub fn with_outputs(mut self, outputs: Vec<Output>) -> Self {\n        self.outputs = outputs;\n        self\n    }\n\n    /// Add custom inputs to the `ContractCall`.\n    pub fn with_inputs(mut self, inputs: Vec<Input>) -> Self {\n        self.inputs = inputs;\n        self\n    }\n}\n\nimpl sealed::Sealed for ContractCall {}\n\n#[derive(Debug, Clone)]\npub struct CallParameters {\n    amount: u64,\n    asset_id: Option<AssetId>,\n    gas_forwarded: Option<u64>,\n}\n\nimpl CallParameters {\n    pub fn new(amount: u64, asset_id: AssetId, gas_forwarded: u64) -> Self {\n        Self {\n            amount,\n            asset_id: Some(asset_id),\n            gas_forwarded: Some(gas_forwarded),\n        }\n    }\n\n    pub fn with_amount(mut self, amount: u64) -> Self {\n        self.amount = amount;\n        self\n    }\n\n    pub fn amount(&self) -> u64 {\n        self.amount\n    }\n\n    pub fn with_asset_id(mut self, asset_id: AssetId) -> Self {\n        self.asset_id = Some(asset_id);\n        self\n    }\n\n    pub fn asset_id(&self) -> Option<AssetId> {\n        self.asset_id\n    }\n\n    pub fn with_gas_forwarded(mut self, gas_forwarded: u64) -> Self {\n        self.gas_forwarded = Some(gas_forwarded);\n        self\n    }\n\n    pub fn gas_forwarded(&self) -> Option<u64> {\n        self.gas_forwarded\n    }\n}\n\nimpl Default for CallParameters {\n    fn default() -> Self {\n        Self {\n            amount: DEFAULT_CALL_PARAMS_AMOUNT,\n            asset_id: None,\n            gas_forwarded: None,\n        }\n    }\n}\n"
  },
  {
    "path": "packages/fuels-programs/src/calls/receipt_parser.rs",
    "content": "use std::collections::VecDeque;\n\nuse fuel_tx::Receipt;\nuse fuel_types::bytes::Bytes;\nuse fuels_core::{\n    codec::{ABIDecoder, DecoderConfig},\n    types::{\n        ContractId, Token,\n        errors::{Error, Result, error},\n        param_types::ParamType,\n    },\n};\n\npub struct ReceiptParser {\n    receipts: VecDeque<Receipt>,\n    decoder: ABIDecoder,\n}\n\nimpl ReceiptParser {\n    pub fn new(receipts: &[Receipt], decoder_config: DecoderConfig) -> Self {\n        let relevant_receipts = receipts\n            .iter()\n            .filter(|receipt| matches!(receipt, Receipt::ReturnData { .. } | Receipt::Call { .. }))\n            .cloned()\n            .collect();\n\n        Self {\n            receipts: relevant_receipts,\n            decoder: ABIDecoder::new(decoder_config),\n        }\n    }\n\n    /// Based on receipts returned by a script transaction, the contract ID,\n    /// and the output param, parse the values and return them as Token.\n    pub fn parse_call(\n        &mut self,\n        contract_id: ContractId,\n        output_param: &ParamType,\n    ) -> Result<Token> {\n        let data = self\n            .extract_contract_call_data(contract_id)\n            .ok_or_else(|| Self::missing_receipts_error(output_param))?;\n\n        self.decoder.decode(output_param, data.as_slice())\n    }\n\n    pub fn parse_script(self, output_param: &ParamType) -> Result<Token> {\n        let data = self\n            .extract_script_data()\n            .ok_or_else(|| Self::missing_receipts_error(output_param))?;\n\n        self.decoder.decode(output_param, data.as_slice())\n    }\n\n    fn missing_receipts_error(output_param: &ParamType) -> Error {\n        error!(\n            Codec,\n            \"`ReceiptDecoder`: failed to find matching receipts entry for {output_param:?}\"\n        )\n    }\n\n    pub fn extract_contract_call_data(&mut self, target_contract: ContractId) -> Option<Bytes> {\n        // If the script contains nested calls, we need to extract the data of the top-level call\n        let mut nested_calls_stack = vec![];\n\n        while let Some(receipt) = self.receipts.pop_front() {\n            if let Receipt::Call { to, .. } = receipt {\n                nested_calls_stack.push(to);\n            } else if let Receipt::ReturnData {\n                data,\n                id: return_id,\n                ..\n            } = receipt\n            {\n                let call_id = nested_calls_stack.pop();\n\n                // Somethings off if there is a mismatch between the call and return ids\n                debug_assert_eq!(call_id.unwrap(), return_id);\n\n                if nested_calls_stack.is_empty() {\n                    // The top-level call return should match our target contract\n                    debug_assert_eq!(target_contract, return_id);\n\n                    return data.clone();\n                }\n            }\n        }\n\n        None\n    }\n\n    fn extract_script_data(&self) -> Option<Bytes> {\n        self.receipts.iter().find_map(|receipt| match receipt {\n            Receipt::ReturnData {\n                id,\n                data: Some(data),\n                ..\n            } if *id == ContractId::zeroed() => Some(data.clone()),\n            _ => None,\n        })\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use fuel_tx::ScriptExecutionResult;\n    use fuels_core::traits::{Parameterize, Tokenizable};\n\n    use super::*;\n\n    const RECEIPT_DATA: &[u8; 3] = &[8, 8, 3];\n    const DECODED_DATA: &[u8; 3] = &[8, 8, 3];\n\n    fn target_contract() -> ContractId {\n        ContractId::from([1u8; 32])\n    }\n\n    fn get_return_data_receipt(id: ContractId, data: &[u8]) -> Receipt {\n        Receipt::ReturnData {\n            id,\n            ptr: Default::default(),\n            len: Default::default(),\n            digest: Default::default(),\n            data: Some(data.to_vec().into()),\n            pc: Default::default(),\n            is: Default::default(),\n        }\n    }\n\n    fn get_call_receipt(to: ContractId) -> Receipt {\n        Receipt::Call {\n            id: Default::default(),\n            to,\n            amount: Default::default(),\n            asset_id: Default::default(),\n            gas: Default::default(),\n            param1: Default::default(),\n            param2: Default::default(),\n            pc: Default::default(),\n            is: Default::default(),\n        }\n    }\n\n    fn get_relevant_receipts() -> Vec<Receipt> {\n        let id = target_contract();\n        vec![\n            get_call_receipt(id),\n            get_return_data_receipt(id, RECEIPT_DATA),\n        ]\n    }\n\n    #[tokio::test]\n    async fn receipt_parser_filters_receipts() -> Result<()> {\n        let mut receipts = vec![\n            Receipt::Revert {\n                id: Default::default(),\n                ra: Default::default(),\n                pc: Default::default(),\n                is: Default::default(),\n            },\n            Receipt::Log {\n                id: Default::default(),\n                ra: Default::default(),\n                rb: Default::default(),\n                rc: Default::default(),\n                rd: Default::default(),\n                pc: Default::default(),\n                is: Default::default(),\n            },\n            Receipt::LogData {\n                id: Default::default(),\n                ra: Default::default(),\n                rb: Default::default(),\n                ptr: Default::default(),\n                len: Default::default(),\n                digest: Default::default(),\n                data: Default::default(),\n                pc: Default::default(),\n                is: Default::default(),\n            },\n            Receipt::ScriptResult {\n                result: ScriptExecutionResult::Success,\n                gas_used: Default::default(),\n            },\n        ];\n        let relevant_receipts = get_relevant_receipts();\n        receipts.extend(relevant_receipts.clone());\n\n        let parser = ReceiptParser::new(&receipts, Default::default());\n\n        assert_eq!(parser.receipts, relevant_receipts);\n\n        Ok(())\n    }\n\n    #[tokio::test]\n    async fn receipt_parser_empty_receipts() -> Result<()> {\n        let receipts = [];\n        let output_param = ParamType::U8;\n\n        let error = ReceiptParser::new(&receipts, Default::default())\n            .parse_call(target_contract(), &output_param)\n            .expect_err(\"should error\");\n\n        let expected_error = ReceiptParser::missing_receipts_error(&output_param);\n        assert_eq!(error.to_string(), expected_error.to_string());\n\n        Ok(())\n    }\n\n    #[tokio::test]\n    async fn receipt_parser_extract_return_data() -> Result<()> {\n        let receipts = get_relevant_receipts();\n\n        let mut parser = ReceiptParser::new(&receipts, Default::default());\n\n        let token = parser\n            .parse_call(target_contract(), &<[u8; 3]>::param_type())\n            .expect(\"parsing should succeed\");\n\n        assert_eq!(&<[u8; 3]>::from_token(token)?, DECODED_DATA);\n\n        Ok(())\n    }\n\n    #[tokio::test]\n    async fn receipt_parser_extracts_top_level_call_receipts() -> Result<()> {\n        const CORRECT_DATA_1: [u8; 3] = [1, 2, 3];\n        const CORRECT_DATA_2: [u8; 3] = [5, 6, 7];\n\n        let contract_top_lvl = target_contract();\n        let contract_nested = ContractId::from([9u8; 32]);\n\n        let receipts = vec![\n            get_call_receipt(contract_top_lvl),\n            get_call_receipt(contract_nested),\n            get_return_data_receipt(contract_nested, &[9, 9, 9]),\n            get_return_data_receipt(contract_top_lvl, &CORRECT_DATA_1),\n            get_call_receipt(contract_top_lvl),\n            get_call_receipt(contract_nested),\n            get_return_data_receipt(contract_nested, &[7, 7, 7]),\n            get_return_data_receipt(contract_top_lvl, &CORRECT_DATA_2),\n        ];\n\n        let mut parser = ReceiptParser::new(&receipts, Default::default());\n\n        let token_1 = parser\n            .parse_call(contract_top_lvl, &<[u8; 3]>::param_type())\n            .expect(\"parsing should succeed\");\n        let token_2 = parser\n            .parse_call(contract_top_lvl, &<[u8; 3]>::param_type())\n            .expect(\"parsing should succeed\");\n\n        assert_eq!(&<[u8; 3]>::from_token(token_1)?, &CORRECT_DATA_1);\n        assert_eq!(&<[u8; 3]>::from_token(token_2)?, &CORRECT_DATA_2);\n\n        Ok(())\n    }\n}\n"
  },
  {
    "path": "packages/fuels-programs/src/calls/script_call.rs",
    "content": "use std::{collections::HashSet, fmt::Debug};\n\nuse fuels_core::types::{\n    ContractId,\n    errors::{Result, error},\n    input::Input,\n    output::Output,\n};\nuse itertools::chain;\n\nuse crate::calls::utils::{generate_contract_inputs, generate_contract_outputs, sealed};\n\n#[derive(Debug, Clone)]\n/// Contains all data relevant to a single script call\npub struct ScriptCall {\n    pub script_binary: Vec<u8>,\n    pub encoded_args: Result<Vec<u8>>,\n    pub inputs: Vec<Input>,\n    pub outputs: Vec<Output>,\n    pub external_contracts: Vec<ContractId>,\n}\n\nimpl ScriptCall {\n    /// Add custom outputs to the `ScriptCall`.\n    pub fn with_outputs(mut self, outputs: Vec<Output>) -> Self {\n        self.outputs = outputs;\n        self\n    }\n\n    /// Add custom inputs to the `ScriptCall`.\n    pub fn with_inputs(mut self, inputs: Vec<Input>) -> Self {\n        self.inputs = inputs;\n        self\n    }\n\n    pub(crate) fn prepare_inputs_outputs(&self) -> Result<(Vec<Input>, Vec<Output>)> {\n        let contract_ids: HashSet<ContractId> = self.external_contracts.iter().copied().collect();\n        let num_of_contracts = contract_ids.len();\n\n        let inputs = chain!(\n            self.inputs.clone(),\n            generate_contract_inputs(contract_ids, self.outputs.len())\n        )\n        .collect();\n\n        // Note the contract_outputs are placed after the custom outputs and\n        // the contract_inputs are referencing them via `output_index`. The\n        // node will, upon receiving our request, use `output_index` to index\n        // the `inputs` array we've sent over.\n        let outputs = chain!(\n            self.outputs.clone(),\n            generate_contract_outputs(num_of_contracts, self.inputs.len()),\n        )\n        .collect();\n\n        Ok((inputs, outputs))\n    }\n\n    pub(crate) fn compute_script_data(&self) -> Result<Vec<u8>> {\n        self.encoded_args\n            .as_ref()\n            .map(|b| b.to_owned())\n            .map_err(|e| error!(Codec, \"cannot encode script call arguments: {e}\"))\n    }\n}\n\nimpl sealed::Sealed for ScriptCall {}\n"
  },
  {
    "path": "packages/fuels-programs/src/calls/traits/contract_dep_configurator.rs",
    "content": "use fuels_core::types::ContractId;\n\nuse crate::calls::{ContractCall, ScriptCall, utils::sealed};\n\npub trait ContractDependencyConfigurator: sealed::Sealed {\n    fn append_external_contract(&mut self, contract_id: ContractId);\n    fn with_external_contracts(self, external_contracts: Vec<ContractId>) -> Self;\n}\n\nimpl ContractDependencyConfigurator for ContractCall {\n    fn append_external_contract(&mut self, contract_id: ContractId) {\n        self.external_contracts.push(contract_id)\n    }\n\n    fn with_external_contracts(self, external_contracts: Vec<ContractId>) -> Self {\n        ContractCall {\n            external_contracts,\n            ..self\n        }\n    }\n}\n\nimpl ContractDependencyConfigurator for ScriptCall {\n    fn append_external_contract(&mut self, contract_id: ContractId) {\n        self.external_contracts.push(contract_id)\n    }\n\n    fn with_external_contracts(self, external_contracts: Vec<ContractId>) -> Self {\n        ScriptCall {\n            external_contracts,\n            ..self\n        }\n    }\n}\n"
  },
  {
    "path": "packages/fuels-programs/src/calls/traits/response_parser.rs",
    "content": "use fuel_tx::Receipt;\nuse fuels_core::{\n    codec::DecoderConfig,\n    types::{Token, errors::Result, param_types::ParamType},\n};\n\nuse crate::calls::{ContractCall, ScriptCall, receipt_parser::ReceiptParser, utils::sealed};\n\npub trait ResponseParser: sealed::Sealed {\n    fn parse_call(\n        &self,\n        receipts: &[Receipt],\n        decoder_config: DecoderConfig,\n        param_type: &ParamType,\n    ) -> Result<Token>;\n}\n\nimpl ResponseParser for ContractCall {\n    fn parse_call(\n        &self,\n        receipts: &[Receipt],\n        decoder_config: DecoderConfig,\n        param_type: &ParamType,\n    ) -> Result<Token> {\n        ReceiptParser::new(receipts, decoder_config).parse_call(self.contract_id, param_type)\n    }\n}\n\nimpl ResponseParser for ScriptCall {\n    fn parse_call(\n        &self,\n        receipts: &[Receipt],\n        decoder_config: DecoderConfig,\n        param_type: &ParamType,\n    ) -> Result<Token> {\n        ReceiptParser::new(receipts, decoder_config).parse_script(param_type)\n    }\n}\n"
  },
  {
    "path": "packages/fuels-programs/src/calls/traits/transaction_tuner.rs",
    "content": "use crate::calls::utils::calculate_required_asset_amounts;\nuse crate::{\n    DEFAULT_MAX_FEE_ESTIMATION_TOLERANCE,\n    calls::{\n        ContractCall, ScriptCall,\n        utils::{build_with_tb, sealed, transaction_builder_from_contract_calls},\n    },\n};\nuse fuel_tx::ConsensusParameters;\nuse fuel_types::AssetId;\nuse fuels_accounts::Account;\nuse fuels_core::types::input::Input;\nuse fuels_core::types::{\n    errors::{Context, Result, error},\n    transaction::{ScriptTransaction, TxPolicies},\n    transaction_builders::{\n        BuildableTransaction, ScriptTransactionBuilder, TransactionBuilder, VariableOutputPolicy,\n    },\n};\n\n#[async_trait::async_trait]\npub trait TransactionTuner: sealed::Sealed {\n    fn required_assets(&self, base_asset_id: AssetId) -> Vec<(AssetId, u128)>;\n\n    fn transaction_builder<T: Account>(\n        &self,\n        tx_policies: TxPolicies,\n        variable_output_policy: VariableOutputPolicy,\n        consensus_parameters: &ConsensusParameters,\n        asset_input: Vec<Input>,\n        account: &T,\n    ) -> Result<ScriptTransactionBuilder>;\n\n    async fn build_tx<T: Account>(\n        &self,\n        tb: ScriptTransactionBuilder,\n        account: &T,\n    ) -> Result<ScriptTransaction>;\n}\n\n#[async_trait::async_trait]\nimpl TransactionTuner for ContractCall {\n    fn required_assets(&self, base_asset_id: AssetId) -> Vec<(AssetId, u128)> {\n        calculate_required_asset_amounts(std::slice::from_ref(self), base_asset_id)\n    }\n\n    fn transaction_builder<T: Account>(\n        &self,\n        tx_policies: TxPolicies,\n        variable_output_policy: VariableOutputPolicy,\n        consensus_parameters: &ConsensusParameters,\n        asset_input: Vec<Input>,\n        account: &T,\n    ) -> Result<ScriptTransactionBuilder> {\n        transaction_builder_from_contract_calls(\n            std::slice::from_ref(self),\n            tx_policies,\n            variable_output_policy,\n            consensus_parameters,\n            asset_input,\n            account,\n        )\n    }\n\n    async fn build_tx<T: Account>(\n        &self,\n        tb: ScriptTransactionBuilder,\n        account: &T,\n    ) -> Result<ScriptTransaction> {\n        build_with_tb(std::slice::from_ref(self), tb, account).await\n    }\n}\n\n#[async_trait::async_trait]\nimpl TransactionTuner for ScriptCall {\n    fn required_assets(&self, _: AssetId) -> Vec<(AssetId, u128)> {\n        vec![]\n    }\n\n    fn transaction_builder<T: Account>(\n        &self,\n        tx_policies: TxPolicies,\n        variable_output_policy: VariableOutputPolicy,\n        _: &ConsensusParameters,\n        _: Vec<Input>,\n        _account: &T,\n    ) -> Result<ScriptTransactionBuilder> {\n        let (inputs, outputs) = self.prepare_inputs_outputs()?;\n\n        Ok(ScriptTransactionBuilder::default()\n            .with_variable_output_policy(variable_output_policy)\n            .with_tx_policies(tx_policies)\n            .with_script(self.script_binary.clone())\n            .with_script_data(self.compute_script_data()?)\n            .with_inputs(inputs)\n            .with_outputs(outputs)\n            .with_gas_estimation_tolerance(DEFAULT_MAX_FEE_ESTIMATION_TOLERANCE)\n            .with_max_fee_estimation_tolerance(DEFAULT_MAX_FEE_ESTIMATION_TOLERANCE))\n    }\n\n    async fn build_tx<T: Account>(\n        &self,\n        mut tb: ScriptTransactionBuilder,\n        account: &T,\n    ) -> Result<ScriptTransaction> {\n        account.add_witnesses(&mut tb)?;\n        account\n            .adjust_for_fee(&mut tb, 0)\n            .await\n            .context(\"failed to adjust inputs to cover for missing base asset\")?;\n\n        tb.build(account.try_provider()?).await\n    }\n}\n\nimpl sealed::Sealed for Vec<ContractCall> {}\n\n#[async_trait::async_trait]\nimpl TransactionTuner for Vec<ContractCall> {\n    fn required_assets(&self, base_asset_id: AssetId) -> Vec<(AssetId, u128)> {\n        calculate_required_asset_amounts(self, base_asset_id)\n    }\n\n    fn transaction_builder<T: Account>(\n        &self,\n        tx_policies: TxPolicies,\n        variable_output_policy: VariableOutputPolicy,\n        consensus_parameters: &ConsensusParameters,\n        asset_input: Vec<Input>,\n        account: &T,\n    ) -> Result<ScriptTransactionBuilder> {\n        validate_contract_calls(self)?;\n\n        transaction_builder_from_contract_calls(\n            self,\n            tx_policies,\n            variable_output_policy,\n            consensus_parameters,\n            asset_input,\n            account,\n        )\n    }\n\n    /// Returns the script that executes the contract calls\n    async fn build_tx<T: Account>(\n        &self,\n        tb: ScriptTransactionBuilder,\n        account: &T,\n    ) -> Result<ScriptTransaction> {\n        validate_contract_calls(self)?;\n\n        build_with_tb(self, tb, account).await\n    }\n}\n\nfn validate_contract_calls(calls: &[ContractCall]) -> Result<()> {\n    if calls.is_empty() {\n        return Err(error!(\n            Other,\n            \"no calls added. Have you used '.add_calls()'?\"\n        ));\n    }\n\n    Ok(())\n}\n"
  },
  {
    "path": "packages/fuels-programs/src/calls/traits.rs",
    "content": "mod contract_dep_configurator;\nmod response_parser;\nmod transaction_tuner;\n\npub use contract_dep_configurator::*;\npub use response_parser::*;\npub use transaction_tuner::*;\n"
  },
  {
    "path": "packages/fuels-programs/src/calls/utils.rs",
    "content": "use std::{collections::HashSet, iter, vec};\n\nuse fuel_abi_types::error_codes::FAILED_TRANSFER_TO_ADDRESS_SIGNAL;\nuse fuel_asm::{RegId, op};\nuse fuel_tx::{ConsensusParameters, Output, PanicReason, Receipt, TxPointer, UtxoId};\nuse fuels_accounts::Account;\nuse fuels_core::{\n    offsets::call_script_data_offset,\n    types::{\n        Address, AssetId, Bytes32, ContractId,\n        errors::{Context, Result},\n        input::Input,\n        transaction::{ScriptTransaction, TxPolicies},\n        transaction_builders::{\n            BuildableTransaction, ScriptTransactionBuilder, TransactionBuilder,\n            VariableOutputPolicy,\n        },\n    },\n};\nuse itertools::{Itertools, chain};\n\nuse crate::{\n    DEFAULT_MAX_FEE_ESTIMATION_TOLERANCE,\n    assembly::contract_call::{CallOpcodeParamsOffset, ContractCallInstructions},\n    calls::ContractCall,\n};\n\npub(crate) mod sealed {\n    pub trait Sealed {}\n}\n\n/// Creates a [`ScriptTransactionBuilder`] from contract calls.\npub(crate) fn transaction_builder_from_contract_calls(\n    calls: &[ContractCall],\n    tx_policies: TxPolicies,\n    variable_outputs: VariableOutputPolicy,\n    consensus_parameters: &ConsensusParameters,\n    asset_inputs: Vec<Input>,\n    account: &impl Account,\n) -> Result<ScriptTransactionBuilder> {\n    let calls_instructions_len = compute_calls_instructions_len(calls);\n    let data_offset = call_script_data_offset(consensus_parameters, calls_instructions_len)?;\n\n    let (script_data, call_param_offsets) = build_script_data_from_contract_calls(\n        calls,\n        data_offset,\n        *consensus_parameters.base_asset_id(),\n    )?;\n    let script = get_instructions(call_param_offsets);\n\n    let (inputs, outputs) = get_transaction_inputs_outputs(\n        calls,\n        asset_inputs,\n        account.address(),\n        *consensus_parameters.base_asset_id(),\n    );\n\n    Ok(ScriptTransactionBuilder::default()\n        .with_variable_output_policy(variable_outputs)\n        .with_tx_policies(tx_policies)\n        .with_script(script)\n        .with_script_data(script_data.clone())\n        .with_inputs(inputs)\n        .with_outputs(outputs)\n        .with_gas_estimation_tolerance(DEFAULT_MAX_FEE_ESTIMATION_TOLERANCE)\n        .with_max_fee_estimation_tolerance(DEFAULT_MAX_FEE_ESTIMATION_TOLERANCE))\n}\n\n/// Creates a [`ScriptTransaction`] from contract calls. The internal [Transaction] is\n/// initialized with the actual script instructions, script data needed to perform the call and\n/// transaction inputs/outputs consisting of assets and contracts.\npub(crate) async fn build_with_tb(\n    calls: &[ContractCall],\n    mut tb: ScriptTransactionBuilder,\n    account: &impl Account,\n) -> Result<ScriptTransaction> {\n    let consensus_parameters = account.try_provider()?.consensus_parameters().await?;\n    let base_asset_id = *consensus_parameters.base_asset_id();\n    let required_asset_amounts = calculate_required_asset_amounts(calls, base_asset_id);\n\n    let used_base_amount = required_asset_amounts\n        .iter()\n        .find_map(|(asset_id, amount)| (*asset_id == base_asset_id).then_some(*amount))\n        .unwrap_or_default();\n\n    account.add_witnesses(&mut tb)?;\n    account\n        .adjust_for_fee(&mut tb, used_base_amount)\n        .await\n        .context(\"failed to adjust inputs to cover for missing base asset\")?;\n\n    tb.build(account.try_provider()?).await\n}\n\n/// Compute the length of the calling scripts for the two types of contract calls: those that return\n/// a heap type, and those that don't.\nfn compute_calls_instructions_len(calls: &[ContractCall]) -> usize {\n    calls\n        .iter()\n        .map(|c| {\n            // Use placeholder for `call_param_offsets` and `output_param_type`, because the length of\n            // the calling script doesn't depend on the underlying type, just on whether or not\n            // gas was forwarded.\n            let call_opcode_params = CallOpcodeParamsOffset {\n                gas_forwarded_offset: c.call_parameters.gas_forwarded().map(|_| 0),\n                ..CallOpcodeParamsOffset::default()\n            };\n\n            ContractCallInstructions::new(call_opcode_params)\n                .into_bytes()\n                .count()\n        })\n        .sum()\n}\n\n/// Compute how much of each asset is required based on all `CallParameters` of the `ContractCalls`\npub fn calculate_required_asset_amounts(\n    calls: &[ContractCall],\n    base_asset_id: AssetId,\n) -> Vec<(AssetId, u128)> {\n    let call_param_assets = calls.iter().map(|call| {\n        (\n            call.call_parameters.asset_id().unwrap_or(base_asset_id),\n            call.call_parameters.amount(),\n        )\n    });\n\n    let grouped_assets = calls\n        .iter()\n        .flat_map(|call| call.custom_assets.clone())\n        .map(|((asset_id, _), amount)| (asset_id, amount))\n        .chain(call_param_assets)\n        .sorted_by_key(|(asset_id, _)| *asset_id)\n        .group_by(|(asset_id, _)| *asset_id);\n\n    grouped_assets\n        .into_iter()\n        .filter_map(|(asset_id, groups_w_same_asset_id)| {\n            let total_amount_in_group = groups_w_same_asset_id\n                .map(|(_, amount)| u128::from(amount))\n                .sum();\n\n            (total_amount_in_group != 0).then_some((asset_id, total_amount_in_group))\n        })\n        .collect()\n}\n\n/// Given a list of contract calls, create the actual opcodes used to call the contract\npub(crate) fn get_instructions(offsets: Vec<CallOpcodeParamsOffset>) -> Vec<u8> {\n    offsets\n        .into_iter()\n        .flat_map(|offset| ContractCallInstructions::new(offset).into_bytes())\n        .chain(op::ret(RegId::ONE).to_bytes())\n        .collect()\n}\n\npub(crate) fn build_script_data_from_contract_calls(\n    calls: &[ContractCall],\n    data_offset: usize,\n    base_asset_id: AssetId,\n) -> Result<(Vec<u8>, Vec<CallOpcodeParamsOffset>)> {\n    calls.iter().try_fold(\n        (vec![], vec![]),\n        |(mut script_data, mut param_offsets), call| {\n            let segment_offset = data_offset + script_data.len();\n            let offset = call\n                .data(base_asset_id)?\n                .encode(segment_offset, &mut script_data);\n\n            param_offsets.push(offset);\n            Ok((script_data, param_offsets))\n        },\n    )\n}\n\n/// Returns the assets and contracts that will be consumed ([`Input`]s)\n/// and created ([`Output`]s) by the transaction\npub(crate) fn get_transaction_inputs_outputs(\n    calls: &[ContractCall],\n    asset_inputs: Vec<Input>,\n    address: Address,\n    base_asset_id: AssetId,\n) -> (Vec<Input>, Vec<Output>) {\n    let asset_ids = extract_unique_asset_ids(&asset_inputs, base_asset_id);\n    let contract_ids = extract_unique_contract_ids(calls);\n    let num_of_contracts = contract_ids.len();\n\n    // Custom `Inputs` and `Outputs` should be placed before other inputs and outputs.\n    let custom_inputs = calls.iter().flat_map(|c| c.inputs.clone()).collect_vec();\n    let custom_inputs_len = custom_inputs.len();\n    let custom_outputs = calls.iter().flat_map(|c| c.outputs.clone()).collect_vec();\n\n    let inputs = chain!(\n        custom_inputs,\n        generate_contract_inputs(contract_ids, custom_outputs.len()),\n        asset_inputs\n    )\n    .collect();\n\n    // Note the contract_outputs are placed after the custom outputs and\n    // the contract_inputs are referencing them via `output_index`. The\n    // node will, upon receiving our request, use `output_index` to index\n    // the `inputs` array we've sent over.\n    let outputs = chain!(\n        custom_outputs,\n        generate_contract_outputs(num_of_contracts, custom_inputs_len),\n        generate_asset_change_outputs(address, asset_ids),\n        generate_custom_outputs(calls),\n    )\n    .collect();\n\n    (inputs, outputs)\n}\n\nfn generate_custom_outputs(calls: &[ContractCall]) -> Vec<Output> {\n    calls\n        .iter()\n        .flat_map(|call| &call.custom_assets)\n        .group_by(|custom| (custom.0.0, custom.0.1))\n        .into_iter()\n        .filter_map(|(asset_id_address, groups_w_same_asset_id_address)| {\n            let total_amount_in_group = groups_w_same_asset_id_address\n                .map(|(_, amount)| amount)\n                .sum::<u64>();\n\n            asset_id_address\n                .1\n                .map(|address| Output::coin(address, total_amount_in_group, asset_id_address.0))\n        })\n        .collect::<Vec<_>>()\n}\n\nfn extract_unique_asset_ids(asset_inputs: &[Input], base_asset_id: AssetId) -> HashSet<AssetId> {\n    asset_inputs\n        .iter()\n        .filter_map(|input| match input {\n            Input::ResourceSigned { resource, .. } | Input::ResourcePredicate { resource, .. } => {\n                Some(resource.coin_asset_id().unwrap_or(base_asset_id))\n            }\n            _ => None,\n        })\n        .collect()\n}\n\nfn generate_asset_change_outputs(\n    wallet_address: Address,\n    asset_ids: HashSet<AssetId>,\n) -> Vec<Output> {\n    asset_ids\n        .into_iter()\n        .map(|asset_id| Output::change(wallet_address, 0, asset_id))\n        .collect()\n}\n\n/// Generate contract outputs taking in consideration already existing inputs\npub(crate) fn generate_contract_outputs(\n    num_of_contracts: usize,\n    num_current_inputs: usize,\n) -> Vec<Output> {\n    (0..num_of_contracts)\n        .map(|idx| {\n            Output::contract(\n                (idx + num_current_inputs) as u16,\n                Bytes32::zeroed(),\n                Bytes32::zeroed(),\n            )\n        })\n        .collect()\n}\n\n/// Generate contract inputs taking in consideration already existing outputs\npub(crate) fn generate_contract_inputs(\n    contract_ids: HashSet<ContractId>,\n    num_current_outputs: usize,\n) -> Vec<Input> {\n    contract_ids\n        .into_iter()\n        .enumerate()\n        .map(|(idx, contract_id)| {\n            Input::contract(\n                UtxoId::new(Bytes32::zeroed(), (idx + num_current_outputs) as u16),\n                Bytes32::zeroed(),\n                Bytes32::zeroed(),\n                TxPointer::default(),\n                contract_id,\n            )\n        })\n        .collect()\n}\n\nfn extract_unique_contract_ids(calls: &[ContractCall]) -> HashSet<ContractId> {\n    calls\n        .iter()\n        .flat_map(|call| {\n            call.external_contracts\n                .iter()\n                .copied()\n                .chain(iter::once(call.contract_id))\n        })\n        .collect()\n}\n\npub fn is_missing_output_variables(receipts: &[Receipt]) -> bool {\n    receipts.iter().any(\n        |r| matches!(r, Receipt::Revert { ra, .. } if *ra == FAILED_TRANSFER_TO_ADDRESS_SIGNAL),\n    )\n}\n\npub fn find_ids_of_missing_contracts(receipts: &[Receipt]) -> Vec<ContractId> {\n    receipts\n        .iter()\n        .filter_map(|receipt| match receipt {\n            Receipt::Panic {\n                reason,\n                contract_id,\n                ..\n            } if *reason.reason() == PanicReason::ContractNotInInputs => {\n                let contract_id = contract_id\n                    .expect(\"panic caused by a contract not in inputs must have a contract id\");\n                Some(contract_id)\n            }\n            _ => None,\n        })\n        .collect()\n}\n\n#[cfg(test)]\nmod test {\n    use std::slice;\n\n    use fuels_accounts::signers::private_key::PrivateKeySigner;\n    use fuels_core::types::{coin::Coin, coin_type::CoinType, param_types::ParamType};\n    use rand::{Rng, thread_rng};\n\n    use super::*;\n    use crate::calls::{CallParameters, traits::ContractDependencyConfigurator};\n\n    fn new_contract_call_with_random_id() -> ContractCall {\n        ContractCall {\n            contract_id: random_contract_id(),\n            encoded_args: Ok(Default::default()),\n            encoded_selector: [0; 8].to_vec(),\n            call_parameters: Default::default(),\n            external_contracts: Default::default(),\n            output_param: ParamType::Unit,\n            is_payable: false,\n            custom_assets: Default::default(),\n            inputs: vec![],\n            outputs: vec![],\n        }\n    }\n\n    fn random_contract_id() -> ContractId {\n        rand::thread_rng().r#gen()\n    }\n\n    #[test]\n    fn contract_input_present() {\n        let call = new_contract_call_with_random_id();\n\n        let signer = PrivateKeySigner::random(&mut thread_rng());\n\n        let (inputs, _) = get_transaction_inputs_outputs(\n            slice::from_ref(&call),\n            Default::default(),\n            signer.address(),\n            AssetId::zeroed(),\n        );\n\n        assert_eq!(\n            inputs,\n            vec![Input::contract(\n                UtxoId::new(Bytes32::zeroed(), 0),\n                Bytes32::zeroed(),\n                Bytes32::zeroed(),\n                TxPointer::default(),\n                call.contract_id,\n            )]\n        );\n    }\n\n    #[test]\n    fn contract_input_is_not_duplicated() {\n        let call = new_contract_call_with_random_id();\n        let call_w_same_contract =\n            new_contract_call_with_random_id().with_contract_id(call.contract_id);\n\n        let signer = PrivateKeySigner::random(&mut thread_rng());\n\n        let calls = [call, call_w_same_contract];\n\n        let (inputs, _) = get_transaction_inputs_outputs(\n            &calls,\n            Default::default(),\n            signer.address(),\n            AssetId::zeroed(),\n        );\n\n        assert_eq!(\n            inputs,\n            vec![Input::contract(\n                UtxoId::new(Bytes32::zeroed(), 0),\n                Bytes32::zeroed(),\n                Bytes32::zeroed(),\n                TxPointer::default(),\n                calls[0].contract_id,\n            )]\n        );\n    }\n\n    #[test]\n    fn contract_output_present() {\n        let call = new_contract_call_with_random_id();\n\n        let signer = PrivateKeySigner::random(&mut thread_rng());\n\n        let (_, outputs) = get_transaction_inputs_outputs(\n            &[call],\n            Default::default(),\n            signer.address(),\n            AssetId::zeroed(),\n        );\n\n        assert_eq!(\n            outputs,\n            vec![Output::contract(0, Bytes32::zeroed(), Bytes32::zeroed())]\n        );\n    }\n\n    #[test]\n    fn external_contract_input_present() {\n        // given\n        let external_contract_id = random_contract_id();\n        let call =\n            new_contract_call_with_random_id().with_external_contracts(vec![external_contract_id]);\n\n        let signer = PrivateKeySigner::random(&mut thread_rng());\n\n        // when\n        let (inputs, _) = get_transaction_inputs_outputs(\n            slice::from_ref(&call),\n            Default::default(),\n            signer.address(),\n            AssetId::zeroed(),\n        );\n\n        // then\n        let mut expected_contract_ids: HashSet<ContractId> =\n            [call.contract_id, external_contract_id].into();\n\n        for (index, input) in inputs.into_iter().enumerate() {\n            match input {\n                Input::Contract {\n                    utxo_id,\n                    balance_root,\n                    state_root,\n                    tx_pointer,\n                    contract_id,\n                } => {\n                    assert_eq!(utxo_id, UtxoId::new(Bytes32::zeroed(), index as u16));\n                    assert_eq!(balance_root, Bytes32::zeroed());\n                    assert_eq!(state_root, Bytes32::zeroed());\n                    assert_eq!(tx_pointer, TxPointer::default());\n                    assert!(expected_contract_ids.contains(&contract_id));\n                    expected_contract_ids.remove(&contract_id);\n                }\n                _ => {\n                    panic!(\"expected only inputs of type `Input::Contract`\");\n                }\n            }\n        }\n    }\n\n    #[test]\n    fn external_contract_output_present() {\n        // given\n        let external_contract_id = random_contract_id();\n        let call =\n            new_contract_call_with_random_id().with_external_contracts(vec![external_contract_id]);\n\n        let signer = PrivateKeySigner::random(&mut thread_rng());\n\n        // when\n        let (_, outputs) = get_transaction_inputs_outputs(\n            &[call],\n            Default::default(),\n            signer.address(),\n            AssetId::zeroed(),\n        );\n\n        // then\n        let expected_outputs = (0..=1)\n            .map(|i| Output::contract(i, Bytes32::zeroed(), Bytes32::zeroed()))\n            .collect::<Vec<_>>();\n\n        assert_eq!(outputs, expected_outputs);\n    }\n\n    #[test]\n    fn change_per_asset_id_added() {\n        // given\n        let asset_ids = [AssetId::zeroed(), AssetId::from([1; 32])];\n\n        let coins = asset_ids\n            .into_iter()\n            .map(|asset_id| {\n                let coin = CoinType::Coin(Coin {\n                    amount: 100,\n                    asset_id,\n                    utxo_id: Default::default(),\n                    owner: Default::default(),\n                });\n                Input::resource_signed(coin)\n            })\n            .collect();\n        let call = new_contract_call_with_random_id();\n\n        let signer = PrivateKeySigner::random(&mut thread_rng());\n\n        // when\n        let (_, outputs) =\n            get_transaction_inputs_outputs(&[call], coins, signer.address(), AssetId::zeroed());\n\n        // then\n        let change_outputs: HashSet<Output> = outputs[1..].iter().cloned().collect();\n\n        let expected_change_outputs = asset_ids\n            .into_iter()\n            .map(|asset_id| Output::Change {\n                to: signer.address(),\n                amount: 0,\n                asset_id,\n            })\n            .collect();\n\n        assert_eq!(change_outputs, expected_change_outputs);\n    }\n\n    #[test]\n    fn will_collate_same_asset_ids() {\n        let asset_id_1 = AssetId::from([1; 32]);\n        let asset_id_2 = AssetId::from([2; 32]);\n\n        let calls = [\n            (asset_id_1, 100),\n            (asset_id_2, 200),\n            (asset_id_1, 300),\n            (asset_id_2, 400),\n        ]\n        .map(|(asset_id, amount)| {\n            CallParameters::default()\n                .with_amount(amount)\n                .with_asset_id(asset_id)\n        })\n        .map(|call_parameters| {\n            new_contract_call_with_random_id().with_call_parameters(call_parameters)\n        });\n\n        let asset_id_amounts = calculate_required_asset_amounts(&calls, AssetId::zeroed());\n\n        let expected_asset_id_amounts = [(asset_id_1, 400), (asset_id_2, 600)].into();\n\n        assert_eq!(\n            asset_id_amounts.into_iter().collect::<HashSet<_>>(),\n            expected_asset_id_amounts\n        )\n    }\n\n    mod compute_calls_instructions_len {\n        use fuel_asm::Instruction;\n        use fuels_core::types::param_types::{EnumVariants, ParamType};\n\n        use super::new_contract_call_with_random_id;\n        use crate::calls::utils::compute_calls_instructions_len;\n\n        // movi, movi, lw, movi + call (for gas)\n        const BASE_INSTRUCTION_COUNT: usize = 5;\n        // 2 instructions (movi and lw) added in get_single_call_instructions when gas_offset is set\n        const GAS_OFFSET_INSTRUCTION_COUNT: usize = 2;\n\n        #[test]\n        fn test_simple() {\n            let call = new_contract_call_with_random_id();\n            let instructions_len = compute_calls_instructions_len(&[call]);\n            assert_eq!(instructions_len, Instruction::SIZE * BASE_INSTRUCTION_COUNT);\n        }\n\n        #[test]\n        fn test_with_gas_offset() {\n            let mut call = new_contract_call_with_random_id();\n            call.call_parameters = call.call_parameters.with_gas_forwarded(0);\n            let instructions_len = compute_calls_instructions_len(&[call]);\n            assert_eq!(\n                instructions_len,\n                Instruction::SIZE * (BASE_INSTRUCTION_COUNT + GAS_OFFSET_INSTRUCTION_COUNT)\n            );\n        }\n\n        #[test]\n        fn test_with_enum_with_only_non_heap_variants() {\n            let mut call = new_contract_call_with_random_id();\n            call.output_param = ParamType::Enum {\n                name: \"\".to_string(),\n                enum_variants: EnumVariants::new(vec![\n                    (\"\".to_string(), ParamType::Bool),\n                    (\"\".to_string(), ParamType::U8),\n                ])\n                .unwrap(),\n                generics: Vec::new(),\n            };\n            let instructions_len = compute_calls_instructions_len(&[call]);\n            assert_eq!(\n                instructions_len,\n                // no extra instructions if there are no heap type variants\n                Instruction::SIZE * BASE_INSTRUCTION_COUNT\n            );\n        }\n    }\n}\n"
  },
  {
    "path": "packages/fuels-programs/src/calls.rs",
    "content": "mod call_handler;\nmod contract_call;\npub mod receipt_parser;\nmod script_call;\npub mod traits;\npub mod utils;\n\npub use call_handler::*;\npub use contract_call::*;\nuse fuel_types::BlockHeight;\npub use script_call::*;\n\n/// Used to control simulations/dry-runs\n#[derive(Debug, Clone)]\npub struct Execution {\n    execution_type: ExecutionType,\n    at_height: Option<BlockHeight>,\n}\n\nimpl Execution {\n    /// The transaction will be subject to all validations.\n    /// The tx fee must be covered, witnesses and UTXOs must be valid, etc.\n    pub fn realistic() -> Self {\n        Self {\n            execution_type: ExecutionType::Realistic,\n            at_height: None,\n        }\n    }\n    /// Most validation is disabled. Witnesses are replaced with fake ones, fake base assets are\n    /// added if necessary. Useful for fetching state without needing an account with base assets.\n    pub fn state_read_only() -> Self {\n        Self {\n            execution_type: ExecutionType::StateReadOnly,\n            at_height: None,\n        }\n    }\n\n    /// Simulating at as specific block height is only available if the node is using\n    /// `rocksdb` and has been started with the `historical_execution` flag.\n    pub fn at_height(mut self, height: impl Into<BlockHeight>) -> Self {\n        self.at_height = Some(height.into());\n        self\n    }\n}\n\nimpl Default for Execution {\n    fn default() -> Self {\n        Self::realistic()\n    }\n}\n\n#[derive(Debug, Clone)]\npub(crate) enum ExecutionType {\n    Realistic,\n    StateReadOnly,\n}\n"
  },
  {
    "path": "packages/fuels-programs/src/contract/loader.rs",
    "content": "use std::collections::HashSet;\n\nuse fuel_tx::{Bytes32, ContractId, Salt, StorageSlot};\nuse fuels_accounts::Account;\nuse fuels_core::{\n    constants::WORD_SIZE,\n    types::{\n        errors::{Context, Result, error},\n        transaction::TxPolicies,\n        transaction_builders::{Blob, BlobId, BlobTransactionBuilder, TransactionBuilder},\n    },\n};\n\nuse super::{Contract, DeployResponse, Regular, compute_contract_id_and_state_root};\nuse crate::{DEFAULT_MAX_FEE_ESTIMATION_TOLERANCE, assembly::contract_call::loader_contract_asm};\n\n#[derive(Debug, Clone)]\npub struct BlobsUploaded {\n    blob_ids: Vec<BlobId>,\n}\n\n#[derive(Debug, Clone)]\npub struct BlobsNotUploaded {\n    blobs: Vec<Blob>,\n}\n\n#[derive(Debug, Clone)]\npub struct Loader<Blobs> {\n    as_blobs: Blobs,\n}\n\nimpl Contract<Loader<BlobsNotUploaded>> {\n    pub fn code(&self) -> Vec<u8> {\n        let ids: Vec<_> = self.blob_ids();\n        loader_contract_asm(&ids)\n            .expect(\"a contract to be creatable due to the check done in loader_from_blobs\")\n    }\n\n    pub fn contract_id(&self) -> ContractId {\n        self.compute_roots().0\n    }\n\n    pub fn code_root(&self) -> Bytes32 {\n        self.compute_roots().1\n    }\n\n    pub fn state_root(&self) -> Bytes32 {\n        self.compute_roots().2\n    }\n\n    fn compute_roots(&self) -> (ContractId, Bytes32, Bytes32) {\n        compute_contract_id_and_state_root(&self.code(), &self.salt, &self.storage_slots)\n    }\n\n    /// Creates a loader contract for the code found in `blobs`. Calling `deploy` on this contract\n    /// does two things:\n    /// 1. Uploads the code blobs.\n    /// 2. Deploys the loader contract.\n    ///\n    /// The loader contract, when executed, will load all the given blobs into memory and delegate the call to the original contract code contained in the blobs.\n    pub fn loader_from_blobs(\n        blobs: Vec<Blob>,\n        salt: Salt,\n        storage_slots: Vec<StorageSlot>,\n    ) -> Result<Self> {\n        if blobs.is_empty() {\n            return Err(error!(Other, \"must provide at least one blob\"));\n        }\n\n        let idx_of_last_blob = blobs.len().saturating_sub(1);\n        let idx_of_offender = blobs.iter().enumerate().find_map(|(idx, blob)| {\n            (blob.len() % WORD_SIZE != 0 && idx != idx_of_last_blob).then_some(idx)\n        });\n\n        if let Some(idx) = idx_of_offender {\n            return Err(error!(\n                Other,\n                \"blob {}/{} has a size of {} bytes, which is not a multiple of {WORD_SIZE}\",\n                idx.saturating_add(1),\n                blobs.len(),\n                blobs[idx].len()\n            ));\n        }\n\n        let ids = blobs.iter().map(|blob| blob.id()).collect::<Vec<_>>();\n\n        // Validate that the loader contract can be created.\n        loader_contract_asm(&ids)?;\n\n        Ok(Self {\n            code: Loader {\n                as_blobs: BlobsNotUploaded { blobs },\n            },\n            salt,\n            storage_slots,\n        })\n    }\n\n    pub fn blobs(&self) -> &[Blob] {\n        self.code.as_blobs.blobs.as_slice()\n    }\n\n    pub fn blob_ids(&self) -> Vec<BlobId> {\n        self.code\n            .as_blobs\n            .blobs\n            .iter()\n            .map(|blob| blob.id())\n            .collect()\n    }\n\n    /// Uploads the blobs associated with this contract. Calling `deploy` on the result will only\n    /// deploy the loader contract.\n    pub async fn upload_blobs(\n        self,\n        account: &impl Account,\n        tx_policies: TxPolicies,\n    ) -> Result<Contract<Loader<BlobsUploaded>>> {\n        let provider = account.try_provider()?;\n\n        let all_blob_ids = self.blob_ids();\n        let mut already_uploaded = HashSet::new();\n\n        for blob in self.code.as_blobs.blobs {\n            let id = blob.id();\n\n            if already_uploaded.contains(&id) {\n                continue;\n            }\n\n            if provider.blob_exists(id).await? {\n                already_uploaded.insert(id);\n                continue;\n            }\n\n            let mut tb = BlobTransactionBuilder::default()\n                .with_blob(blob)\n                .with_tx_policies(tx_policies)\n                .with_max_fee_estimation_tolerance(DEFAULT_MAX_FEE_ESTIMATION_TOLERANCE);\n\n            account\n                .adjust_for_fee(&mut tb, 0)\n                .await\n                .context(\"failed to adjust inputs to cover for missing base asset\")?;\n            account.add_witnesses(&mut tb)?;\n\n            let tx = tb.build(provider).await?;\n\n            let tx_status_response = provider.send_transaction_and_await_commit(tx).await;\n            tx_status_response.and_then(|response| response.check(None))?;\n\n            already_uploaded.insert(id);\n        }\n\n        Contract::loader_from_blob_ids(all_blob_ids, self.salt, self.storage_slots)\n    }\n\n    /// Deploys the loader contract after uploading the code blobs.\n    pub async fn deploy(\n        self,\n        account: &impl Account,\n        tx_policies: TxPolicies,\n    ) -> Result<DeployResponse> {\n        self.upload_blobs(account, tx_policies)\n            .await?\n            .deploy(account, tx_policies)\n            .await\n    }\n\n    /// Deploys the loader contract after uploading the code blobs,\n    /// if there is no contract with this ContractId Already.\n    pub async fn deploy_if_not_exists(\n        self,\n        account: &impl Account,\n        tx_policies: TxPolicies,\n    ) -> Result<DeployResponse> {\n        self.upload_blobs(account, tx_policies)\n            .await?\n            .deploy_if_not_exists(account, tx_policies)\n            .await\n    }\n    /// Reverts the contract from a loader contract back to a regular contract.\n    pub fn revert_to_regular(self) -> Contract<Regular> {\n        let code = self\n            .code\n            .as_blobs\n            .blobs\n            .into_iter()\n            .flat_map(Vec::from)\n            .collect();\n\n        Contract::regular(code, self.salt, self.storage_slots)\n    }\n}\n\nimpl Contract<Loader<BlobsUploaded>> {\n    pub fn code(&self) -> Vec<u8> {\n        loader_contract_asm(&self.code.as_blobs.blob_ids)\n            .expect(\"a contract to be creatable due to the check done in loader_for_blobs\")\n    }\n\n    pub fn contract_id(&self) -> ContractId {\n        self.compute_roots().0\n    }\n\n    pub fn code_root(&self) -> Bytes32 {\n        self.compute_roots().1\n    }\n\n    pub fn state_root(&self) -> Bytes32 {\n        self.compute_roots().2\n    }\n\n    pub fn compute_roots(&self) -> (ContractId, Bytes32, Bytes32) {\n        compute_contract_id_and_state_root(&self.code(), &self.salt, &self.storage_slots)\n    }\n\n    /// Creates a loader contract using previously uploaded blobs.\n    ///\n    /// The contract code has been uploaded in blobs with [`BlobId`]s specified in `blob_ids`.\n    /// This will create a loader contract that, when deployed and executed, will load all the specified blobs into memory and delegate the call to the code contained in the blobs.\n    pub fn loader_from_blob_ids(\n        blob_ids: Vec<BlobId>,\n        salt: Salt,\n        storage_slots: Vec<StorageSlot>,\n    ) -> Result<Self> {\n        if blob_ids.is_empty() {\n            return Err(error!(Other, \"must provide at least one blob\"));\n        }\n\n        // Validate that the loader contract can be created.\n        loader_contract_asm(&blob_ids)?;\n\n        Ok(Self {\n            code: Loader {\n                as_blobs: BlobsUploaded { blob_ids },\n            },\n            salt,\n            storage_slots,\n        })\n    }\n\n    pub fn blob_ids(&self) -> &[BlobId] {\n        &self.code.as_blobs.blob_ids\n    }\n\n    /// Deploys the loader contract.\n    pub async fn deploy(\n        self,\n        account: &impl Account,\n        tx_policies: TxPolicies,\n    ) -> Result<DeployResponse> {\n        Contract::regular(self.code(), self.salt, self.storage_slots)\n            .deploy(account, tx_policies)\n            .await\n    }\n\n    pub async fn deploy_if_not_exists(\n        self,\n        account: &impl Account,\n        tx_policies: TxPolicies,\n    ) -> Result<DeployResponse> {\n        Contract::regular(self.code(), self.salt, self.storage_slots)\n            .deploy_if_not_exists(account, tx_policies)\n            .await\n    }\n}\n"
  },
  {
    "path": "packages/fuels-programs/src/contract/regular.rs",
    "content": "use std::{default::Default, fmt::Debug, path::Path};\n\nuse fuel_tx::{StorageSlot, TxId};\nuse fuels_accounts::Account;\nuse fuels_core::{\n    Configurables,\n    constants::WORD_SIZE,\n    error,\n    types::{\n        Bytes32, ContractId, Salt,\n        errors::{Context, Result},\n        transaction::{Transaction, TxPolicies},\n        transaction_builders::{Blob, CreateTransactionBuilder},\n        tx_status::Success,\n    },\n};\n\nuse super::{\n    BlobsNotUploaded, Contract, Loader, StorageConfiguration, compute_contract_id_and_state_root,\n    validate_path_and_extension,\n};\nuse crate::DEFAULT_MAX_FEE_ESTIMATION_TOLERANCE;\n\n#[derive(Clone, Debug)]\npub struct DeployResponse {\n    pub tx_status: Option<Success>,\n    pub tx_id: Option<TxId>,\n    pub contract_id: ContractId,\n}\n\n// In a mod so that we eliminate the footgun of getting the private `code` field without applying\n// configurables\nmod code_types {\n    use fuels_core::Configurables;\n\n    #[derive(Debug, Clone, PartialEq)]\n    pub struct Regular {\n        code: Vec<u8>,\n        configurables: Configurables,\n    }\n\n    impl Regular {\n        pub(crate) fn new(code: Vec<u8>, configurables: Configurables) -> Self {\n            Self {\n                code,\n                configurables,\n            }\n        }\n\n        pub(crate) fn with_code(self, code: Vec<u8>) -> Self {\n            Self { code, ..self }\n        }\n\n        pub(crate) fn with_configurables(self, configurables: Configurables) -> Self {\n            Self {\n                configurables,\n                ..self\n            }\n        }\n\n        pub(crate) fn code(&self) -> Vec<u8> {\n            let mut code = self.code.clone();\n            self.configurables.update_constants_in(&mut code);\n            code\n        }\n    }\n}\npub use code_types::*;\n\nimpl Contract<Regular> {\n    pub fn with_code(self, code: Vec<u8>) -> Self {\n        Self {\n            code: self.code.with_code(code),\n            salt: self.salt,\n            storage_slots: self.storage_slots,\n        }\n    }\n\n    pub fn with_configurables(self, configurables: impl Into<Configurables>) -> Self {\n        Self {\n            code: self.code.with_configurables(configurables.into()),\n            ..self\n        }\n    }\n\n    pub fn code(&self) -> Vec<u8> {\n        self.code.code()\n    }\n\n    pub fn contract_id(&self) -> ContractId {\n        self.compute_roots().0\n    }\n\n    pub fn code_root(&self) -> Bytes32 {\n        self.compute_roots().1\n    }\n\n    pub fn state_root(&self) -> Bytes32 {\n        self.compute_roots().2\n    }\n\n    fn compute_roots(&self) -> (ContractId, Bytes32, Bytes32) {\n        compute_contract_id_and_state_root(&self.code(), &self.salt, &self.storage_slots)\n    }\n\n    /// Loads a contract from a binary file. Salt and storage slots are loaded as well, depending on the configuration provided.\n    pub fn load_from(\n        binary_filepath: impl AsRef<Path>,\n        config: LoadConfiguration,\n    ) -> Result<Contract<Regular>> {\n        let binary_filepath = binary_filepath.as_ref();\n        validate_path_and_extension(binary_filepath, \"bin\")?;\n\n        let binary = std::fs::read(binary_filepath).map_err(|e| {\n            std::io::Error::new(\n                e.kind(),\n                format!(\"failed to read binary: {binary_filepath:?}: {e}\"),\n            )\n        })?;\n\n        let storage_slots = super::determine_storage_slots(config.storage, binary_filepath)?;\n\n        Ok(Contract {\n            code: Regular::new(binary, config.configurables),\n            salt: config.salt,\n            storage_slots,\n        })\n    }\n\n    /// Creates a regular contract with the given code, salt, and storage slots.\n    pub fn regular(\n        code: Vec<u8>,\n        salt: Salt,\n        storage_slots: Vec<StorageSlot>,\n    ) -> Contract<Regular> {\n        Contract {\n            code: Regular::new(code, Configurables::default()),\n            salt,\n            storage_slots,\n        }\n    }\n\n    /// Deploys a compiled contract to a running node.\n    /// To deploy a contract, you need an account with enough assets to pay for deployment.\n    /// This account will also receive the change.\n    pub async fn deploy(\n        self,\n        account: &impl Account,\n        tx_policies: TxPolicies,\n    ) -> Result<DeployResponse> {\n        let contract_id = self.contract_id();\n        let state_root = self.state_root();\n        let salt = self.salt;\n        let storage_slots = self.storage_slots;\n\n        let mut tb = CreateTransactionBuilder::prepare_contract_deployment(\n            self.code.code(),\n            contract_id,\n            state_root,\n            salt,\n            storage_slots.to_vec(),\n            tx_policies,\n        )\n        .with_max_fee_estimation_tolerance(DEFAULT_MAX_FEE_ESTIMATION_TOLERANCE);\n\n        account.add_witnesses(&mut tb)?;\n        account\n            .adjust_for_fee(&mut tb, 0)\n            .await\n            .context(\"failed to adjust inputs to cover for missing base asset\")?;\n\n        let provider = account.try_provider()?;\n        let consensus_parameters = provider.consensus_parameters().await?;\n\n        let tx = tb.build(provider).await?;\n        let tx_id = Some(tx.id(consensus_parameters.chain_id()));\n\n        let tx_status = provider.send_transaction_and_await_commit(tx).await?;\n\n        Ok(DeployResponse {\n            tx_status: Some(tx_status.take_success_checked(None)?),\n            tx_id,\n            contract_id,\n        })\n    }\n\n    /// Deploys a compiled contract to a running node if a contract with\n    /// the corresponding [`ContractId`] doesn't exist.\n    pub async fn deploy_if_not_exists(\n        self,\n        account: &impl Account,\n        tx_policies: TxPolicies,\n    ) -> Result<DeployResponse> {\n        let contract_id = self.contract_id();\n        let provider = account.try_provider()?;\n        if provider.contract_exists(&contract_id).await? {\n            Ok(DeployResponse {\n                tx_status: None,\n                tx_id: None,\n                contract_id,\n            })\n        } else {\n            self.deploy(account, tx_policies).await\n        }\n    }\n\n    /// Converts a regular contract into a loader contract, splitting the code into blobs.\n    pub fn convert_to_loader(\n        self,\n        max_words_per_blob: usize,\n    ) -> Result<Contract<Loader<BlobsNotUploaded>>> {\n        if max_words_per_blob == 0 {\n            return Err(error!(Other, \"blob size must be greater than 0\"));\n        }\n        let blobs = self\n            .code()\n            .chunks(max_words_per_blob.saturating_mul(WORD_SIZE))\n            .map(|chunk| Blob::new(chunk.to_vec()))\n            .collect();\n\n        Contract::loader_from_blobs(blobs, self.salt, self.storage_slots)\n    }\n\n    /// Deploys the contract either as a regular contract or as a loader contract if it exceeds the size limit.\n    pub async fn smart_deploy(\n        self,\n        account: &impl Account,\n        tx_policies: TxPolicies,\n        max_words_per_blob: usize,\n    ) -> Result<DeployResponse> {\n        let provider = account.try_provider()?;\n        let max_contract_size = provider\n            .consensus_parameters()\n            .await?\n            .contract_params()\n            .contract_max_size() as usize;\n\n        if self.code().len() <= max_contract_size {\n            self.deploy(account, tx_policies).await\n        } else {\n            self.convert_to_loader(max_words_per_blob)?\n                .deploy(account, tx_policies)\n                .await\n        }\n    }\n}\n\n/// Configuration for contract deployment.\n#[derive(Debug, Clone, Default)]\npub struct LoadConfiguration {\n    pub(crate) storage: StorageConfiguration,\n    pub(crate) configurables: Configurables,\n    pub(crate) salt: Salt,\n}\n\nimpl LoadConfiguration {\n    pub fn new(\n        storage: StorageConfiguration,\n        configurables: impl Into<Configurables>,\n        salt: impl Into<Salt>,\n    ) -> Self {\n        Self {\n            storage,\n            configurables: configurables.into(),\n            salt: salt.into(),\n        }\n    }\n\n    pub fn with_storage_configuration(mut self, storage: StorageConfiguration) -> Self {\n        self.storage = storage;\n        self\n    }\n\n    pub fn with_configurables(mut self, configurables: impl Into<Configurables>) -> Self {\n        self.configurables = configurables.into();\n        self\n    }\n\n    pub fn with_salt(mut self, salt: impl Into<Salt>) -> Self {\n        self.salt = salt.into();\n        self\n    }\n}\n"
  },
  {
    "path": "packages/fuels-programs/src/contract/storage.rs",
    "content": "use std::{\n    collections::HashMap,\n    default::Default,\n    fmt::Debug,\n    io,\n    path::{Path, PathBuf},\n};\n\nuse fuel_tx::{Bytes32, StorageSlot};\nuse fuels_core::types::errors::{Result, error};\n\n/// Configuration for contract storage\n#[derive(Debug, Clone)]\npub struct StorageConfiguration {\n    autoload_storage: bool,\n    slot_overrides: StorageSlots,\n}\n\nimpl Default for StorageConfiguration {\n    fn default() -> Self {\n        Self {\n            autoload_storage: true,\n            slot_overrides: Default::default(),\n        }\n    }\n}\n\nimpl StorageConfiguration {\n    pub fn new(autoload_enabled: bool, slots: impl IntoIterator<Item = StorageSlot>) -> Self {\n        let config = Self {\n            autoload_storage: autoload_enabled,\n            slot_overrides: Default::default(),\n        };\n\n        config.add_slot_overrides(slots)\n    }\n\n    /// If enabled will try to automatically discover and load the storage configuration from the\n    /// storage config json file.\n    pub fn with_autoload(mut self, enabled: bool) -> Self {\n        self.autoload_storage = enabled;\n        self\n    }\n\n    pub fn autoload_enabled(&self) -> bool {\n        self.autoload_storage\n    }\n\n    /// Slots added via [`add_slot_overrides`] will override any\n    /// existing slots with matching keys.\n    pub fn add_slot_overrides(\n        mut self,\n        storage_slots: impl IntoIterator<Item = StorageSlot>,\n    ) -> Self {\n        self.slot_overrides.add_overrides(storage_slots);\n        self\n    }\n\n    /// Slots added via [`add_slot_overrides_from_file`] will override any\n    /// existing slots with matching keys.\n    ///\n    /// `path` - path to a JSON file containing the storage slots.\n    pub fn add_slot_overrides_from_file(mut self, path: impl AsRef<Path>) -> Result<Self> {\n        let slots = StorageSlots::load_from_file(path.as_ref())?;\n        self.slot_overrides.add_overrides(slots.into_iter());\n        Ok(self)\n    }\n\n    pub fn into_slots(self) -> impl Iterator<Item = StorageSlot> {\n        self.slot_overrides.into_iter()\n    }\n}\n\n#[derive(Debug, Clone, Default)]\npub(crate) struct StorageSlots {\n    storage_slots: HashMap<Bytes32, StorageSlot>,\n}\n\nimpl StorageSlots {\n    fn from(storage_slots: impl IntoIterator<Item = StorageSlot>) -> Self {\n        let pairs = storage_slots.into_iter().map(|slot| (*slot.key(), slot));\n        Self {\n            storage_slots: pairs.collect(),\n        }\n    }\n\n    pub(crate) fn add_overrides(\n        &mut self,\n        storage_slots: impl IntoIterator<Item = StorageSlot>,\n    ) -> &mut Self {\n        let pairs = storage_slots.into_iter().map(|slot| (*slot.key(), slot));\n        self.storage_slots.extend(pairs);\n        self\n    }\n\n    pub(crate) fn load_from_file(storage_path: impl AsRef<Path>) -> Result<Self> {\n        let storage_path = storage_path.as_ref();\n        validate_path_and_extension(storage_path, \"json\")?;\n\n        let storage_json_string = std::fs::read_to_string(storage_path).map_err(|e| {\n            io::Error::new(\n                e.kind(),\n                format!(\"failed to read storage slots from: {storage_path:?}: {e}\"),\n            )\n        })?;\n\n        let decoded_slots = serde_json::from_str::<Vec<StorageSlot>>(&storage_json_string)?;\n\n        Ok(StorageSlots::from(decoded_slots))\n    }\n\n    pub(crate) fn into_iter(self) -> impl Iterator<Item = StorageSlot> {\n        self.storage_slots.into_values()\n    }\n}\n\npub(crate) fn determine_storage_slots(\n    storage_config: StorageConfiguration,\n    binary_filepath: &Path,\n) -> Result<Vec<StorageSlot>> {\n    let autoload_enabled = storage_config.autoload_enabled();\n    let user_overrides = storage_config.into_slots().collect::<Vec<_>>();\n    let slots = if autoload_enabled {\n        let mut slots = autoload_storage_slots(binary_filepath)?;\n        slots.add_overrides(user_overrides);\n        slots.into_iter().collect()\n    } else {\n        user_overrides\n    };\n\n    Ok(slots)\n}\n\npub(crate) fn autoload_storage_slots(contract_binary: &Path) -> Result<StorageSlots> {\n    let storage_file = expected_storage_slots_filepath(contract_binary)\n        .ok_or_else(|| error!(Other, \"could not determine storage slots file\"))?;\n\n    StorageSlots::load_from_file(&storage_file)\n                .map_err(|_| error!(Other, \"could not autoload storage slots from file: {storage_file:?}. \\\n                                    Either provide the file or disable autoloading in `StorageConfiguration`\"))\n}\n\npub(crate) fn expected_storage_slots_filepath(contract_binary: &Path) -> Option<PathBuf> {\n    let dir = contract_binary.parent()?;\n\n    let binary_filename = contract_binary.file_stem()?.to_str()?;\n\n    Some(dir.join(format!(\"{binary_filename}-storage_slots.json\")))\n}\npub(crate) fn validate_path_and_extension(file_path: &Path, extension: &str) -> Result<()> {\n    if !file_path.exists() {\n        return Err(error!(IO, \"file {file_path:?} does not exist\"));\n    }\n\n    let path_extension = file_path\n        .extension()\n        .ok_or_else(|| error!(Other, \"could not extract extension from: {file_path:?}\"))?;\n\n    if extension != path_extension {\n        return Err(error!(\n            Other,\n            \"expected {file_path:?} to have '.{extension}' extension\"\n        ));\n    }\n\n    Ok(())\n}\n\n#[cfg(test)]\nmod tests {\n    use std::collections::HashSet;\n\n    use super::*;\n\n    #[test]\n    fn merging_overrides_storage_slots() {\n        // given\n        let make_slot = |id, value| StorageSlot::new([id; 32].into(), [value; 32].into());\n\n        let slots = (1..3).map(|id| make_slot(id, 100));\n        let original_config = StorageConfiguration::new(false, slots);\n\n        let overlapping_slots = (2..4).map(|id| make_slot(id, 200));\n\n        // when\n        let original_config = original_config.add_slot_overrides(overlapping_slots);\n\n        // then\n        assert_eq!(\n            HashSet::from_iter(original_config.slot_overrides.into_iter()),\n            HashSet::from([make_slot(1, 100), make_slot(2, 200), make_slot(3, 200)])\n        );\n    }\n}\n"
  },
  {
    "path": "packages/fuels-programs/src/contract.rs",
    "content": "mod storage;\n\nuse std::fmt::Debug;\n\nuse fuel_tx::{Bytes32, Contract as FuelContract, ContractId, Salt, StorageSlot};\npub use storage::*;\n\n/// Represents a contract that can be deployed either directly ([`Contract::regular`]) or through a loader [`Contract::convert_to_loader`].\n/// Provides the ability to calculate the `ContractId` ([`Contract::contract_id`]) without needing to deploy the contract.\n/// This struct also manages contract code updates with `configurable`s\n/// ([`Contract::with_configurables`]) and can automatically\n/// load storage slots (via [`Contract::load_from`]).\n#[derive(Debug, Clone, PartialEq)]\npub struct Contract<Code> {\n    code: Code,\n    salt: Salt,\n    storage_slots: Vec<StorageSlot>,\n}\n\nimpl<T> Contract<T> {\n    pub fn salt(&self) -> Salt {\n        self.salt\n    }\n\n    pub fn with_salt(mut self, salt: impl Into<Salt>) -> Self {\n        self.salt = salt.into();\n        self\n    }\n\n    pub fn storage_slots(&self) -> &[StorageSlot] {\n        &self.storage_slots\n    }\n\n    pub fn with_storage_slots(mut self, storage_slots: Vec<StorageSlot>) -> Self {\n        self.storage_slots = storage_slots;\n        self\n    }\n}\n\nmod regular;\npub use regular::*;\n\nmod loader;\n// reexported to avoid doing a breaking change\npub use loader::*;\n\npub use crate::assembly::contract_call::loader_contract_asm;\n\nfn compute_contract_id_and_state_root(\n    binary: &[u8],\n    salt: &Salt,\n    storage_slots: &[StorageSlot],\n) -> (ContractId, Bytes32, Bytes32) {\n    let fuel_contract = FuelContract::from(binary);\n    let code_root = fuel_contract.root();\n    let state_root = FuelContract::initial_state_root(storage_slots.iter());\n\n    let contract_id = FuelContract::id(salt, &code_root, &state_root);\n\n    (contract_id, code_root, state_root)\n}\n\n#[cfg(test)]\nmod tests {\n    use std::path::Path;\n\n    use fuels_core::types::{\n        errors::{Error, Result},\n        transaction_builders::Blob,\n    };\n    use tempfile::tempdir;\n\n    use super::*;\n    use crate::assembly::contract_call::loader_contract_asm;\n\n    #[test]\n    fn autoload_storage_slots() {\n        // given\n        let temp_dir = tempdir().unwrap();\n        let contract_bin = temp_dir.path().join(\"my_contract.bin\");\n        std::fs::write(&contract_bin, \"\").unwrap();\n\n        let storage_file = temp_dir.path().join(\"my_contract-storage_slots.json\");\n\n        let expected_storage_slots = vec![StorageSlot::new([1; 32].into(), [2; 32].into())];\n        save_slots(&expected_storage_slots, &storage_file);\n\n        let storage_config = StorageConfiguration::new(true, vec![]);\n        let load_config = LoadConfiguration::default().with_storage_configuration(storage_config);\n\n        // when\n        let loaded_contract = Contract::load_from(&contract_bin, load_config).unwrap();\n\n        // then\n        assert_eq!(loaded_contract.storage_slots, expected_storage_slots);\n    }\n\n    #[test]\n    fn autoload_fails_if_file_missing() {\n        // given\n        let temp_dir = tempdir().unwrap();\n        let contract_bin = temp_dir.path().join(\"my_contract.bin\");\n        std::fs::write(&contract_bin, \"\").unwrap();\n\n        let storage_config = StorageConfiguration::new(true, vec![]);\n        let load_config = LoadConfiguration::default().with_storage_configuration(storage_config);\n\n        // when\n        let error = Contract::load_from(&contract_bin, load_config)\n            .expect_err(\"should have failed because the storage slots file is missing\");\n\n        // then\n        let storage_slots_path = temp_dir.path().join(\"my_contract-storage_slots.json\");\n        let Error::Other(msg) = error else {\n            panic!(\"expected an error of type `Other`\");\n        };\n        assert_eq!(\n            msg,\n            format!(\n                \"could not autoload storage slots from file: {storage_slots_path:?}. Either provide the file or disable autoloading in `StorageConfiguration`\"\n            )\n        );\n    }\n\n    fn save_slots(slots: &Vec<StorageSlot>, path: &Path) {\n        std::fs::write(\n            path,\n            serde_json::to_string::<Vec<StorageSlot>>(slots).unwrap(),\n        )\n        .unwrap()\n    }\n\n    #[test]\n    fn blob_size_must_be_greater_than_zero() {\n        // given\n        let contract = Contract::regular(vec![0x00], Salt::zeroed(), vec![]);\n\n        // when\n        let err = contract\n            .convert_to_loader(0)\n            .expect_err(\"should have failed because blob size is 0\");\n\n        // then\n        assert_eq!(\n            err.to_string(),\n            \"blob size must be greater than 0\".to_string()\n        );\n    }\n\n    #[test]\n    fn contract_with_no_code_cannot_be_turned_into_a_loader() {\n        // given\n        let contract = Contract::regular(vec![], Salt::zeroed(), vec![]);\n\n        // when\n        let err = contract\n            .convert_to_loader(100)\n            .expect_err(\"should have failed because there is no code\");\n\n        // then\n        assert_eq!(\n            err.to_string(),\n            \"must provide at least one blob\".to_string()\n        );\n    }\n\n    #[test]\n    fn loader_needs_at_least_one_blob() {\n        // given\n        let no_blobs = vec![];\n\n        // when\n        let err = Contract::loader_from_blobs(no_blobs, Salt::default(), vec![])\n            .expect_err(\"should have failed because there are no blobs\");\n\n        // then\n        assert_eq!(\n            err.to_string(),\n            \"must provide at least one blob\".to_string()\n        );\n    }\n\n    #[test]\n    fn loader_requires_all_except_the_last_blob_to_be_word_sized() {\n        // given\n        let blobs = [vec![0; 9], vec![0; 8]].map(Blob::new).to_vec();\n\n        // when\n        let err = Contract::loader_from_blobs(blobs, Salt::default(), vec![])\n            .expect_err(\"should have failed because the first blob is not word-sized\");\n\n        // then\n        assert_eq!(\n            err.to_string(),\n            \"blob 1/2 has a size of 9 bytes, which is not a multiple of 8\".to_string()\n        );\n    }\n\n    #[test]\n    fn last_blob_in_loader_can_be_unaligned() {\n        // given\n        let blobs = [vec![0; 8], vec![0; 9]].map(Blob::new).to_vec();\n\n        // when\n        let result = Contract::loader_from_blobs(blobs, Salt::default(), vec![]);\n\n        // then\n        let _ = result.unwrap();\n    }\n\n    #[test]\n    fn can_load_regular_contract() -> Result<()> {\n        // given\n        let tmp_dir = tempfile::tempdir()?;\n        let code_file = tmp_dir.path().join(\"contract.bin\");\n        let code = b\"some fake contract code\";\n        std::fs::write(&code_file, code)?;\n\n        // when\n        let contract = Contract::load_from(\n            code_file,\n            LoadConfiguration::default()\n                .with_storage_configuration(StorageConfiguration::default().with_autoload(false)),\n        )?;\n\n        // then\n        assert_eq!(contract.code(), code);\n\n        Ok(())\n    }\n\n    #[test]\n    fn can_manually_create_regular_contract() -> Result<()> {\n        // given\n        let binary = b\"some fake contract code\";\n\n        // when\n        let contract = Contract::regular(binary.to_vec(), Salt::zeroed(), vec![]);\n\n        // then\n        assert_eq!(contract.code(), binary);\n\n        Ok(())\n    }\n\n    macro_rules! getters_work {\n        ($contract: ident, $contract_id: expr, $state_root: expr, $code_root: expr, $salt: expr, $code: expr) => {\n            assert_eq!($contract.contract_id(), $contract_id);\n            assert_eq!($contract.state_root(), $state_root);\n            assert_eq!($contract.code_root(), $code_root);\n            assert_eq!($contract.salt(), $salt);\n            assert_eq!($contract.code(), $code);\n        };\n    }\n\n    #[test]\n    fn regular_contract_has_expected_getters() -> Result<()> {\n        let contract_binary = b\"some fake contract code\";\n        let storage_slots = vec![StorageSlot::new([2; 32].into(), [1; 32].into())];\n        let contract = Contract::regular(contract_binary.to_vec(), Salt::zeroed(), storage_slots);\n\n        let expected_contract_id =\n            \"93c9f1e61efb25458e3c56fdcfee62acb61c0533364eeec7ba61cb2957aa657b\".parse()?;\n        let expected_state_root =\n            \"852b7b7527124dbcd44302e52453b864dc6f4d9544851c729da666a430b84c97\".parse()?;\n        let expected_code_root =\n            \"69ca130191e9e469f1580229760b327a0729237f1aff65cf1d076b2dd8360031\".parse()?;\n        let expected_salt = Salt::zeroed();\n\n        getters_work!(\n            contract,\n            expected_contract_id,\n            expected_state_root,\n            expected_code_root,\n            expected_salt,\n            contract_binary\n        );\n\n        Ok(())\n    }\n\n    #[test]\n    fn regular_can_be_turned_into_loader_and_back() -> Result<()> {\n        let contract_binary = b\"some fake contract code\";\n\n        let contract_original = Contract::regular(contract_binary.to_vec(), Salt::zeroed(), vec![]);\n\n        let loader_contract = contract_original.clone().convert_to_loader(1)?;\n\n        let regular_recreated = loader_contract.clone().revert_to_regular();\n\n        assert_eq!(regular_recreated, contract_original);\n\n        Ok(())\n    }\n\n    #[test]\n    fn unuploaded_loader_contract_has_expected_getters() -> Result<()> {\n        let contract_binary = b\"some fake contract code\";\n\n        let storage_slots = vec![StorageSlot::new([2; 32].into(), [1; 32].into())];\n        let original = Contract::regular(contract_binary.to_vec(), Salt::zeroed(), storage_slots);\n        let loader = original.clone().convert_to_loader(1024)?;\n\n        let loader_asm = loader_contract_asm(&loader.blob_ids()).unwrap();\n        let manual_loader = original.with_code(loader_asm);\n\n        getters_work!(\n            loader,\n            manual_loader.contract_id(),\n            manual_loader.state_root(),\n            manual_loader.code_root(),\n            manual_loader.salt(),\n            manual_loader.code()\n        );\n\n        Ok(())\n    }\n\n    #[test]\n    fn unuploaded_loader_requires_at_least_one_blob() -> Result<()> {\n        // given\n        let no_blob_ids = vec![];\n\n        // when\n        let loader = Contract::loader_from_blob_ids(no_blob_ids, Salt::default(), vec![])\n            .expect_err(\"should have failed because there are no blobs\");\n\n        // then\n        assert_eq!(\n            loader.to_string(),\n            \"must provide at least one blob\".to_string()\n        );\n        Ok(())\n    }\n\n    #[test]\n    fn uploaded_loader_has_expected_getters() -> Result<()> {\n        let contract_binary = b\"some fake contract code\";\n        let original_contract = Contract::regular(contract_binary.to_vec(), Salt::zeroed(), vec![]);\n\n        let blob_ids = original_contract\n            .clone()\n            .convert_to_loader(1024)?\n            .blob_ids();\n\n        // we pretend we uploaded the blobs\n        let loader = Contract::loader_from_blob_ids(blob_ids.clone(), Salt::default(), vec![])?;\n\n        let loader_asm = loader_contract_asm(&blob_ids).unwrap();\n        let manual_loader = original_contract.with_code(loader_asm);\n\n        getters_work!(\n            loader,\n            manual_loader.contract_id(),\n            manual_loader.state_root(),\n            manual_loader.code_root(),\n            manual_loader.salt(),\n            manual_loader.code()\n        );\n\n        Ok(())\n    }\n}\n"
  },
  {
    "path": "packages/fuels-programs/src/debug.rs",
    "content": "use fuel_asm::{Instruction, Opcode};\nuse fuels_core::{error, types::errors::Result};\nuse itertools::Itertools;\n\nuse crate::{\n    assembly::{\n        contract_call::{ContractCallData, ContractCallInstructions},\n        script_and_predicate_loader::{\n            LoaderCode, get_offset_for_section_containing_configurables,\n        },\n    },\n    utils::prepend_msg,\n};\n\n#[derive(Debug, Clone, PartialEq, Eq)]\npub struct ScriptCallData {\n    pub code: Vec<u8>,\n    /// This will be renamed in next breaking release. For binary generated with sway 0.66.5 this will be data_offset\n    /// and for binary generated with sway 0.66.6 and above this will probably be data_section_offset and configurable_section_offset.\n    pub data_section_offset: Option<u64>,\n    pub data: Vec<u8>,\n}\n\nimpl ScriptCallData {\n    pub fn data_section(&self) -> Option<&[u8]> {\n        self.data_section_offset.map(|offset| {\n            let offset = offset as usize;\n            &self.code[offset..]\n        })\n    }\n}\n\n#[derive(Debug, Clone, PartialEq, Eq)]\npub enum ScriptType {\n    ContractCall(Vec<ContractCallData>),\n    Loader {\n        script: ScriptCallData,\n        blob_id: [u8; 32],\n    },\n    Other(ScriptCallData),\n}\n\nfn parse_script_call(script: &[u8], script_data: &[u8]) -> Result<ScriptCallData> {\n    let data_section_offset = if script.len() >= 16 {\n        let offset = get_offset_for_section_containing_configurables(script)?;\n\n        if offset >= script.len() {\n            None\n        } else {\n            Some(offset as u64)\n        }\n    } else {\n        None\n    };\n\n    Ok(ScriptCallData {\n        data: script_data.to_vec(),\n        data_section_offset,\n        code: script.to_vec(),\n    })\n}\n\nfn parse_contract_calls(\n    script: &[u8],\n    script_data: &[u8],\n) -> Result<Option<Vec<ContractCallData>>> {\n    let instructions: std::result::Result<Vec<Instruction>, _> =\n        fuel_asm::from_bytes(script.to_vec()).try_collect();\n\n    let Ok(instructions) = instructions else {\n        return Ok(None);\n    };\n\n    let Some(call_instructions) = extract_call_instructions(&instructions) else {\n        return Ok(None);\n    };\n\n    let Some(minimum_call_offset) = call_instructions.iter().map(|i| i.call_data_offset()).min()\n    else {\n        return Ok(None);\n    };\n\n    let num_calls = call_instructions.len();\n\n    call_instructions.iter().enumerate().map(|(idx, current_call_instructions)| {\n            let data_start =\n                (current_call_instructions.call_data_offset() - minimum_call_offset) as usize;\n\n            let data_end = if idx + 1 < num_calls {\n                (call_instructions[idx + 1].call_data_offset()\n                    - current_call_instructions.call_data_offset()) as usize\n            } else {\n                script_data.len()\n            };\n\n            if data_start > script_data.len() || data_end > script_data.len() {\n                return Err(error!(\n                    Other,\n                    \"call data offset requires data section of length {}, but data section is only {} bytes long\",\n                    data_end,\n                    script_data.len()\n                ));\n            }\n\n            let contract_call_data = ContractCallData::decode(\n                &script_data[data_start..data_end],\n                current_call_instructions.is_gas_fwd_variant(),\n            )?;\n\n            Ok(contract_call_data)\n        }).collect::<Result<_>>().map(Some)\n}\n\nfn extract_call_instructions(\n    mut instructions: &[Instruction],\n) -> Option<Vec<ContractCallInstructions>> {\n    let mut call_instructions = vec![];\n\n    while let Some(extracted_instructions) = ContractCallInstructions::extract_from(instructions) {\n        let num_instructions = extracted_instructions.len();\n        debug_assert!(num_instructions > 0);\n\n        instructions = &instructions[num_instructions..];\n        call_instructions.push(extracted_instructions);\n    }\n\n    if !instructions.is_empty() {\n        match instructions {\n            [single_instruction] if single_instruction.opcode() == Opcode::RET => {}\n            _ => return None,\n        }\n    }\n\n    Some(call_instructions)\n}\n\nimpl ScriptType {\n    pub fn detect(script: &[u8], data: &[u8]) -> Result<Self> {\n        if let Some(contract_calls) = parse_contract_calls(script, data)\n            .map_err(prepend_msg(\"while decoding contract call\"))?\n        {\n            return Ok(Self::ContractCall(contract_calls));\n        }\n\n        if let Some((script, blob_id)) = parse_loader_script(script, data)? {\n            return Ok(Self::Loader { script, blob_id });\n        }\n\n        Ok(Self::Other(parse_script_call(script, data)?))\n    }\n}\n\nfn parse_loader_script(script: &[u8], data: &[u8]) -> Result<Option<(ScriptCallData, [u8; 32])>> {\n    let Some(loader_code) = LoaderCode::from_loader_binary(script)\n        .map_err(prepend_msg(\"while decoding loader script\"))?\n    else {\n        return Ok(None);\n    };\n\n    Ok(Some((\n        ScriptCallData {\n            code: script.to_vec(),\n            data: data.to_vec(),\n            data_section_offset: Some(loader_code.configurables_section_offset() as u64),\n        },\n        loader_code.blob_id(),\n    )))\n}\n\n#[cfg(test)]\nmod tests {\n\n    use fuel_asm::RegId;\n    use fuels_core::types::errors::Error;\n    use rand::{RngCore, SeedableRng};\n    use test_case::test_case;\n\n    use super::*;\n    use crate::assembly::{\n        contract_call::{CallOpcodeParamsOffset, ContractCallInstructions},\n        script_and_predicate_loader::loader_instructions_w_configurables,\n    };\n\n    #[test]\n    fn can_handle_empty_scripts() {\n        // given\n        let empty_script = [];\n\n        // when\n        let res = ScriptType::detect(&empty_script, &[]).unwrap();\n\n        // then\n        assert_eq!(\n            res,\n            ScriptType::Other(ScriptCallData {\n                code: vec![],\n                data_section_offset: None,\n                data: vec![]\n            })\n        )\n    }\n\n    #[test]\n    fn is_fine_with_malformed_scripts() {\n        let mut script = vec![0; 100 * Instruction::SIZE];\n        let jmpf = fuel_asm::op::jmpf(0x0, 0x04).to_bytes();\n\n        let mut rng = rand::rngs::StdRng::from_seed([0; 32]);\n        rng.fill_bytes(&mut script);\n        script[4..8].copy_from_slice(&jmpf);\n\n        let script_type = ScriptType::detect(&script, &[]).unwrap();\n\n        assert_eq!(\n            script_type,\n            ScriptType::Other(ScriptCallData {\n                code: script,\n                data_section_offset: None,\n                data: vec![]\n            })\n        );\n    }\n\n    fn example_contract_call_data(has_args: bool, gas_fwd: bool) -> Vec<u8> {\n        let mut data = vec![];\n        data.extend_from_slice(&100u64.to_be_bytes());\n        data.extend_from_slice(&[0; 32]);\n        data.extend_from_slice(&[1; 32]);\n        data.extend_from_slice(&[0; 8]);\n        data.extend_from_slice(&[0; 8]);\n        data.extend_from_slice(&\"test\".len().to_be_bytes());\n        data.extend_from_slice(\"test\".as_bytes());\n        if has_args {\n            data.extend_from_slice(&[0; 8]);\n        }\n        if gas_fwd {\n            data.extend_from_slice(&[0; 8]);\n        }\n        data\n    }\n\n    #[test_case(108, \"amount\")]\n    #[test_case(100, \"asset id\")]\n    #[test_case(68, \"contract id\")]\n    #[test_case(36, \"function selector offset\")]\n    #[test_case(28, \"encoded args offset\")]\n    #[test_case(20, \"function selector length\")]\n    #[test_case(12, \"function selector\")]\n    #[test_case(8, \"forwarded gas\")]\n    fn catches_missing_data(amount_of_data_to_steal: usize, expected_msg: &str) {\n        // given\n        let script = ContractCallInstructions::new(CallOpcodeParamsOffset {\n            call_data_offset: 0,\n            amount_offset: 0,\n            asset_id_offset: 0,\n            gas_forwarded_offset: Some(1),\n        })\n        .into_bytes()\n        .collect_vec();\n\n        let ok_data = example_contract_call_data(false, true);\n        let not_enough_data = ok_data[..ok_data.len() - amount_of_data_to_steal].to_vec();\n\n        // when\n        let err = ScriptType::detect(&script, &not_enough_data).unwrap_err();\n\n        // then\n        let Error::Other(mut msg) = err else {\n            panic!(\"expected Error::Other\");\n        };\n\n        let expected_msg =\n            format!(\"while decoding contract call: while decoding {expected_msg}: not enough data\");\n        msg.truncate(expected_msg.len());\n\n        assert_eq!(expected_msg, msg);\n    }\n\n    #[test]\n    fn handles_invalid_utf8_fn_selector() {\n        // given\n        let script = ContractCallInstructions::new(CallOpcodeParamsOffset {\n            call_data_offset: 0,\n            amount_offset: 0,\n            asset_id_offset: 0,\n            gas_forwarded_offset: Some(1),\n        })\n        .into_bytes()\n        .collect_vec();\n\n        let invalid_utf8 = {\n            let invalid_data = [0x80, 0xBF, 0xC0, 0xAF, 0xFF];\n            assert!(String::from_utf8(invalid_data.to_vec()).is_err());\n            invalid_data\n        };\n\n        let mut ok_data = example_contract_call_data(false, true);\n        ok_data[96..101].copy_from_slice(&invalid_utf8);\n\n        // when\n        let script_type = ScriptType::detect(&script, &ok_data).unwrap();\n\n        // then\n        let ScriptType::ContractCall(calls) = script_type else {\n            panic!(\"expected ScriptType::Other\");\n        };\n        let Error::Codec(err) = calls[0].decode_fn_selector().unwrap_err() else {\n            panic!(\"expected Error::Codec\");\n        };\n\n        assert_eq!(\n            err,\n            \"cannot decode function selector: invalid utf-8 sequence of 1 bytes from index 0\"\n        );\n    }\n\n    #[test]\n    fn loader_script_without_a_blob() {\n        // given\n        let script = loader_instructions_w_configurables()\n            .iter()\n            .flat_map(|i| i.to_bytes())\n            .collect::<Vec<_>>();\n\n        // when\n        let err = ScriptType::detect(&script, &[]).unwrap_err();\n\n        // then\n        let Error::Other(msg) = err else {\n            panic!(\"expected Error::Other\");\n        };\n        assert_eq!(\n            \"while decoding loader script: while decoding blob id: not enough data, available: 0, requested: 32\",\n            msg\n        );\n    }\n\n    #[test]\n    fn loader_script_with_almost_matching_instructions() {\n        // given\n        let mut loader_instructions = loader_instructions_w_configurables().to_vec();\n\n        loader_instructions.insert(\n            loader_instructions.len() - 2,\n            fuel_asm::op::movi(RegId::ZERO, 0),\n        );\n        let script = loader_instructions\n            .iter()\n            .flat_map(|i| i.to_bytes())\n            .collect::<Vec<_>>();\n\n        // when\n        let script_type = ScriptType::detect(&script, &[]).unwrap();\n\n        // then\n        assert_eq!(\n            script_type,\n            ScriptType::Other(ScriptCallData {\n                code: script,\n                data_section_offset: None,\n                data: vec![]\n            })\n        );\n    }\n\n    #[test]\n    fn extra_instructions_in_contract_calling_scripts_not_tolerated() {\n        // given\n        let mut contract_call_script = ContractCallInstructions::new(CallOpcodeParamsOffset {\n            call_data_offset: 0,\n            amount_offset: 0,\n            asset_id_offset: 0,\n            gas_forwarded_offset: Some(1),\n        })\n        .into_bytes()\n        .collect_vec();\n\n        contract_call_script.extend(fuel_asm::op::movi(RegId::ZERO, 10).to_bytes());\n        let script_data = example_contract_call_data(false, true);\n\n        // when\n        let script_type = ScriptType::detect(&contract_call_script, &script_data).unwrap();\n\n        // then\n        assert_eq!(\n            script_type,\n            ScriptType::Other(ScriptCallData {\n                code: contract_call_script,\n                data_section_offset: None,\n                data: script_data\n            })\n        );\n    }\n\n    #[test]\n    fn handles_invalid_call_data_offset() {\n        // given\n        let contract_call_1 = ContractCallInstructions::new(CallOpcodeParamsOffset {\n            call_data_offset: 0,\n            amount_offset: 0,\n            asset_id_offset: 0,\n            gas_forwarded_offset: Some(1),\n        })\n        .into_bytes();\n\n        let contract_call_2 = ContractCallInstructions::new(CallOpcodeParamsOffset {\n            call_data_offset: u16::MAX as usize,\n            amount_offset: 0,\n            asset_id_offset: 0,\n            gas_forwarded_offset: Some(1),\n        })\n        .into_bytes();\n\n        let data_only_for_one_call = example_contract_call_data(false, true);\n\n        let together = contract_call_1.chain(contract_call_2).collect_vec();\n\n        // when\n        let err = ScriptType::detect(&together, &data_only_for_one_call).unwrap_err();\n\n        // then\n        let Error::Other(msg) = err else {\n            panic!(\"expected Error::Other\");\n        };\n\n        assert_eq!(\n            \"while decoding contract call: call data offset requires data section of length 65535, but data section is only 108 bytes long\",\n            msg\n        );\n    }\n}\n"
  },
  {
    "path": "packages/fuels-programs/src/executable.rs",
    "content": "use fuels_core::{\n    Configurables,\n    types::{\n        errors::{Context, Result},\n        transaction::Transaction,\n        transaction_builders::{Blob, BlobTransactionBuilder},\n        tx_response::TxResponse,\n    },\n};\n\nuse crate::{\n    DEFAULT_MAX_FEE_ESTIMATION_TOLERANCE,\n    assembly::script_and_predicate_loader::{\n        LoaderCode, extract_configurables_offset, extract_data_offset,\n        has_configurables_section_offset,\n    },\n};\n\n/// This struct represents a standard executable with its associated bytecode and configurables.\n#[derive(Debug, Clone, PartialEq)]\npub struct Regular {\n    code: Vec<u8>,\n    configurables: Configurables,\n}\n\nimpl Regular {\n    pub fn new(code: Vec<u8>, configurables: Configurables) -> Self {\n        Self {\n            code,\n            configurables,\n        }\n    }\n}\n\n/// Used to transform Script or Predicate code into a loader variant, where the code is uploaded as\n/// a blob and the binary itself is substituted with code that will load the blob code and apply\n/// the given configurables to the Script/Predicate.\n#[derive(Debug, Clone, PartialEq)]\npub struct Executable<State> {\n    state: State,\n}\n\nimpl Executable<Regular> {\n    pub fn from_bytes(code: Vec<u8>) -> Self {\n        Executable {\n            state: Regular::new(code, Default::default()),\n        }\n    }\n\n    /// Loads an `Executable<Regular>` from a file at the given path.\n    ///\n    /// # Parameters\n    ///\n    /// - `path`: The file path to load the executable from.\n    ///\n    /// # Returns\n    ///\n    /// A `Result` containing the `Executable<Regular>` or an error if loading fails.\n    pub fn load_from(path: &str) -> Result<Executable<Regular>> {\n        let code = std::fs::read(path)?;\n\n        Ok(Executable {\n            state: Regular::new(code, Default::default()),\n        })\n    }\n\n    pub fn with_configurables(self, configurables: impl Into<Configurables>) -> Self {\n        Executable {\n            state: Regular {\n                configurables: configurables.into(),\n                ..self.state\n            },\n        }\n    }\n\n    pub fn data_offset_in_code(&self) -> Result<usize> {\n        extract_data_offset(&self.state.code)\n    }\n\n    pub fn configurables_offset_in_code(&self) -> Result<Option<usize>> {\n        if has_configurables_section_offset(&self.state.code)? {\n            Ok(Some(extract_configurables_offset(&self.state.code)?))\n        } else {\n            Ok(None)\n        }\n    }\n\n    /// Returns the code of the executable with configurables applied.\n    ///\n    /// # Returns\n    ///\n    /// The bytecode of the executable with configurables updated.\n    pub fn code(&self) -> Vec<u8> {\n        let mut code = self.state.code.clone();\n        self.state.configurables.update_constants_in(&mut code);\n        code\n    }\n\n    /// Converts the `Executable<Regular>` into an `Executable<Loader>`.\n    ///\n    /// # Returns\n    ///\n    /// A `Result` containing the `Executable<Loader>` or an error if loader code cannot be\n    /// generated for the given binary.\n    pub fn convert_to_loader(self) -> Result<Executable<Loader>> {\n        validate_loader_can_be_made_from_code(\n            self.state.code.clone(),\n            self.state.configurables.clone(),\n        )?;\n\n        Ok(Executable {\n            state: Loader {\n                code: self.state.code,\n                configurables: self.state.configurables,\n            },\n        })\n    }\n}\n\npub struct Loader {\n    code: Vec<u8>,\n    configurables: Configurables,\n}\n\nimpl Executable<Loader> {\n    pub fn with_configurables(self, configurables: impl Into<Configurables>) -> Self {\n        Executable {\n            state: Loader {\n                configurables: configurables.into(),\n                ..self.state\n            },\n        }\n    }\n\n    #[deprecated(note = \"Use `configurables_offset_in_code` instead\")]\n    pub fn data_offset_in_code(&self) -> usize {\n        self.loader_code().configurables_section_offset()\n    }\n\n    pub fn configurables_offset_in_code(&self) -> usize {\n        self.loader_code().configurables_section_offset()\n    }\n\n    fn loader_code(&self) -> LoaderCode {\n        let mut code = self.state.code.clone();\n\n        self.state.configurables.update_constants_in(&mut code);\n\n        LoaderCode::from_normal_binary(code)\n            .expect(\"checked before turning into a Executable<Loader>\")\n    }\n\n    /// Returns the code of the loader executable with configurables applied.\n    pub fn code(&self) -> Vec<u8> {\n        self.loader_code().as_bytes().to_vec()\n    }\n\n    /// A Blob containing the original executable code minus the data section.\n    pub fn blob(&self) -> Blob {\n        // we don't apply configurables because they touch the data section which isn't part of the\n        // blob\n        LoaderCode::extract_blob(&self.state.code)\n            .expect(\"checked before turning into a Executable<Loader>\")\n    }\n\n    /// If not previously uploaded, uploads a blob containing the original executable code minus the data section.\n    pub async fn upload_blob(\n        &self,\n        account: impl fuels_accounts::Account,\n    ) -> Result<Option<TxResponse>> {\n        let blob = self.blob();\n        let provider = account.try_provider()?;\n        let consensus_parameters = provider.consensus_parameters().await?;\n\n        if provider.blob_exists(blob.id()).await? {\n            return Ok(None);\n        }\n\n        let mut tb = BlobTransactionBuilder::default()\n            .with_blob(self.blob())\n            .with_max_fee_estimation_tolerance(DEFAULT_MAX_FEE_ESTIMATION_TOLERANCE);\n\n        account\n            .adjust_for_fee(&mut tb, 0)\n            .await\n            .context(\"failed to adjust inputs to cover for missing base asset\")?;\n        account.add_witnesses(&mut tb)?;\n\n        let tx = tb.build(provider).await?;\n        let tx_id = tx.id(consensus_parameters.chain_id());\n\n        let tx_status = provider.send_transaction_and_await_commit(tx).await?;\n\n        Ok(Some(TxResponse {\n            tx_status: tx_status.take_success_checked(None)?,\n            tx_id,\n        }))\n    }\n}\n\nfn validate_loader_can_be_made_from_code(\n    mut code: Vec<u8>,\n    configurables: Configurables,\n) -> Result<()> {\n    configurables.update_constants_in(&mut code);\n\n    let _ = LoaderCode::from_normal_binary(code)?;\n\n    Ok(())\n}\n\n#[cfg(test)]\nmod tests {\n    use std::io::Write;\n\n    use fuels_core::{Configurable, Configurables};\n    use tempfile::NamedTempFile;\n\n    use super::*;\n\n    fn legacy_indicating_instruction() -> Vec<u8> {\n        fuel_asm::op::jmpf(0x0, 0x02).to_bytes().to_vec()\n    }\n\n    #[test]\n    fn test_executable_regular_from_bytes() {\n        // Given: Some bytecode\n        let code = vec![1u8, 2, 3, 4];\n\n        // When: Creating an Executable<Regular> from bytes\n        let executable = Executable::<Regular>::from_bytes(code.clone());\n\n        // Then: The executable should have the given code and default configurables\n        assert_eq!(executable.state.code, code);\n        assert_eq!(executable.state.configurables, Default::default());\n    }\n\n    #[test]\n    fn test_executable_regular_load_from() {\n        // Given: A temporary file containing some bytecode\n        let code = vec![5u8, 6, 7, 8];\n        let mut temp_file = NamedTempFile::new().expect(\"Failed to create temp file\");\n        temp_file\n            .write_all(&code)\n            .expect(\"Failed to write to temp file\");\n        let path = temp_file.path().to_str().unwrap();\n\n        // When: Loading an Executable<Regular> from the file\n        let executable_result = Executable::<Regular>::load_from(path);\n\n        // Then: The executable should be created successfully with the correct code\n        assert!(executable_result.is_ok());\n        let executable = executable_result.unwrap();\n        assert_eq!(executable.state.code, code);\n        assert_eq!(executable.state.configurables, Default::default());\n    }\n\n    #[test]\n    fn test_executable_regular_load_from_invalid_path() {\n        // Given: An invalid file path\n        let invalid_path = \"/nonexistent/path/to/file\";\n\n        // When: Attempting to load an Executable<Regular> from the invalid path\n        let executable_result = Executable::<Regular>::load_from(invalid_path);\n\n        // Then: The operation should fail with an error\n        assert!(executable_result.is_err());\n    }\n\n    #[test]\n    fn test_executable_regular_with_configurables() {\n        // Given: An Executable<Regular> and some configurables\n        let code = vec![1u8, 2, 3, 4];\n        let executable = Executable::<Regular>::from_bytes(code);\n        let configurables = Configurables::new(vec![Configurable {\n            offset: 2,\n            data: vec![1],\n        }]);\n\n        // When: Setting new configurables\n        let new_executable = executable.with_configurables(configurables.clone());\n\n        // Then: The executable should have the new configurables\n        assert_eq!(new_executable.state.configurables, configurables);\n    }\n\n    #[test]\n    fn test_executable_regular_code() {\n        // Given: An Executable<Regular> with some code and configurables\n        let code = vec![1u8, 2, 3, 4];\n        let configurables = Configurables::new(vec![Configurable {\n            offset: 1,\n            data: vec![1],\n        }]);\n        let executable =\n            Executable::<Regular>::from_bytes(code.clone()).with_configurables(configurables);\n\n        // When: Retrieving the code after applying configurables\n        let modified_code = executable.code();\n\n        assert_eq!(modified_code, vec![1, 1, 3, 4]);\n    }\n\n    #[test]\n    fn test_loader_extracts_code_and_data_section_legacy_format() {\n        let padding = vec![0; 4];\n        let jmpf = legacy_indicating_instruction();\n        let data_offset = 28u64.to_be_bytes().to_vec();\n        let remaining_padding = vec![0; 8];\n        let some_random_instruction = vec![1, 2, 3, 4];\n        let data_section = vec![5, 6, 7, 8];\n\n        let code = [\n            padding.clone(),\n            jmpf.clone(),\n            data_offset.clone(),\n            remaining_padding.clone(),\n            some_random_instruction.clone(),\n            data_section.clone(),\n        ]\n        .concat();\n\n        let executable = Executable::<Regular>::from_bytes(code.clone());\n\n        let loader = executable.convert_to_loader().unwrap();\n\n        let blob = loader.blob();\n        let data_stripped_code = [\n            padding,\n            jmpf.clone(),\n            data_offset,\n            remaining_padding.clone(),\n            some_random_instruction,\n        ]\n        .concat();\n        assert_eq!(blob.as_ref(), data_stripped_code);\n\n        // And: Loader code should match expected binary\n        let loader_code = loader.code();\n\n        assert_eq!(\n            loader_code,\n            LoaderCode::from_normal_binary(code).unwrap().as_bytes()\n        );\n    }\n\n    #[test]\n    fn test_loader_extracts_code_and_configurable_section_new_format() {\n        let padding = vec![0; 4];\n        let jmpf = legacy_indicating_instruction();\n        let data_offset = 28u64.to_be_bytes().to_vec();\n        let configurable_offset = vec![0; 8];\n        let data_section = vec![5, 6, 7, 8];\n        let configurable_section = vec![9, 9, 9, 9];\n\n        let code = [\n            padding.clone(),\n            jmpf.clone(),\n            data_offset.clone(),\n            configurable_offset.clone(),\n            data_section.clone(),\n            configurable_section,\n        ]\n        .concat();\n\n        let executable = Executable::<Regular>::from_bytes(code.clone());\n\n        let loader = executable.convert_to_loader().unwrap();\n\n        let blob = loader.blob();\n        let configurable_stripped_code = [\n            padding,\n            jmpf,\n            data_offset,\n            configurable_offset,\n            data_section,\n        ]\n        .concat();\n        assert_eq!(blob.as_ref(), configurable_stripped_code);\n\n        // And: Loader code should match expected binary\n        let loader_code = loader.code();\n        assert_eq!(\n            loader_code,\n            LoaderCode::from_normal_binary(code).unwrap().as_bytes()\n        );\n    }\n\n    #[test]\n    fn test_executable_regular_convert_to_loader_with_invalid_code() {\n        // Given: An Executable<Regular> with invalid code (too short)\n        let code = vec![1u8, 2]; // Insufficient length for a valid data offset\n        let executable = Executable::<Regular>::from_bytes(code);\n\n        // When: Attempting to convert to a loader\n        let result = executable.convert_to_loader();\n\n        // Then: The conversion should fail with an error\n        assert!(result.is_err());\n    }\n\n    #[test]\n    fn executable_with_no_data_section() {\n        // to skip over the first 2 half words and skip over the offset itself, basically stating\n        // that there is no data section\n        let data_section_offset = 16u64;\n\n        let jmpf = legacy_indicating_instruction();\n        let mut initial_bytes = vec![0; 16];\n        initial_bytes[4..8].copy_from_slice(&jmpf);\n\n        let code = [initial_bytes, data_section_offset.to_be_bytes().to_vec()].concat();\n\n        Executable::from_bytes(code).convert_to_loader().unwrap();\n    }\n}\n"
  },
  {
    "path": "packages/fuels-programs/src/lib.rs",
    "content": "#[cfg(feature = \"std\")]\npub mod calls;\n#[cfg(feature = \"std\")]\npub mod contract;\n#[cfg(feature = \"std\")]\npub mod executable;\n#[cfg(feature = \"std\")]\npub mod responses;\n\npub const DEFAULT_MAX_FEE_ESTIMATION_TOLERANCE: f32 = 0.50;\n\npub mod debug;\n\npub(crate) mod assembly;\npub(crate) mod utils;\n"
  },
  {
    "path": "packages/fuels-programs/src/responses/call.rs",
    "content": "use std::fmt::Debug;\n\nuse fuel_tx::TxId;\nuse fuels_core::{\n    codec::{LogDecoder, LogResult},\n    traits::{Parameterize, Tokenizable},\n    types::{errors::Result, tx_status::Success},\n};\n\n/// [`CallResponse`] is a struct that is returned by a call to the contract or script. Its value\n/// field holds the decoded typed value returned by the contract's method. The other field holds all\n/// the receipts returned by the call.\n#[derive(Clone, Debug)]\n// ANCHOR: call_response\npub struct CallResponse<D> {\n    pub value: D,\n    pub tx_status: Success,\n    pub tx_id: Option<TxId>,\n    pub log_decoder: LogDecoder,\n}\n// ANCHOR_END: call_response\n\nimpl<D> CallResponse<D> {\n    pub fn decode_logs(&self) -> LogResult {\n        self.log_decoder.decode_logs(&self.tx_status.receipts)\n    }\n\n    pub fn decode_logs_with_type<T: Tokenizable + Parameterize + 'static>(&self) -> Result<Vec<T>> {\n        self.log_decoder\n            .decode_logs_with_type::<T>(&self.tx_status.receipts)\n    }\n}\n"
  },
  {
    "path": "packages/fuels-programs/src/responses/submit.rs",
    "content": "use std::fmt::Debug;\n\nuse fuel_types::Bytes32;\nuse fuels_accounts::Account;\nuse fuels_core::{\n    traits::{Parameterize, Tokenizable},\n    types::errors::Result,\n};\n\nuse crate::{\n    calls::{\n        CallHandler, ContractCall,\n        traits::{ContractDependencyConfigurator, ResponseParser, TransactionTuner},\n    },\n    responses::CallResponse,\n};\n\n/// Represents the response of a submitted transaction with customizable retry behavior.\n///\n/// This struct holds information about the retry configuration, transaction ID (`tx_id`),\n/// and the call handler that manages the type of call (contract or script).\n///\n/// # Type Parameters\n///\n/// - `T`: The account type associated with the transaction.\n/// - `D`: The data type representing the response value.\n/// - `C`: The call type.\n///\n/// # Fields\n///\n/// - `retry_config`: The retry configuration for the transaction.\n/// - `tx_id`: The optional transaction ID of the submitted transaction.\n/// - `call_handler`: The call handler that manages the type of call.\n///\n/// ```\n#[derive(Debug)]\npub struct SubmitResponse<A, C, T> {\n    tx_id: Bytes32,\n    call_handler: CallHandler<A, C, T>,\n}\n\nimpl<A, C, T> SubmitResponse<A, C, T>\nwhere\n    A: Account,\n    C: ContractDependencyConfigurator + TransactionTuner + ResponseParser,\n    T: Tokenizable + Parameterize + Debug,\n{\n    pub fn new(tx_id: Bytes32, call_handler: CallHandler<A, C, T>) -> Self {\n        Self {\n            tx_id,\n            call_handler,\n        }\n    }\n\n    pub async fn response(self) -> Result<CallResponse<T>> {\n        let provider = self.call_handler.account.try_provider()?;\n        let tx_status = provider.tx_status(&self.tx_id).await?;\n\n        self.call_handler.get_response(tx_status)\n    }\n\n    pub fn tx_id(&self) -> Bytes32 {\n        self.tx_id\n    }\n}\n\n/// Represents the response of a submitted transaction with multiple contract calls.\nimpl<A: Account> SubmitResponse<A, Vec<ContractCall>, ()> {\n    pub fn new(tx_id: Bytes32, call_handler: CallHandler<A, Vec<ContractCall>, ()>) -> Self {\n        Self {\n            tx_id,\n            call_handler,\n        }\n    }\n\n    pub async fn response<T: Tokenizable + Debug>(self) -> Result<CallResponse<T>> {\n        let provider = self.call_handler.account.try_provider()?;\n        let tx_status = provider.tx_status(&self.tx_id).await?;\n\n        self.call_handler.get_response(tx_status)\n    }\n\n    pub fn tx_id(&self) -> Bytes32 {\n        self.tx_id\n    }\n}\n"
  },
  {
    "path": "packages/fuels-programs/src/responses.rs",
    "content": "mod call;\nmod submit;\n\npub use call::*;\npub use submit::*;\n"
  },
  {
    "path": "packages/fuels-programs/src/utils.rs",
    "content": "use fuels_core::types::errors::{Error, error};\n\npub fn prepend_msg<'a>(msg: impl AsRef<str> + 'a) -> impl Fn(Error) -> Error + 'a {\n    move |err| match err {\n        Error::IO(orig_msg) => {\n            error!(IO, \"{}: {}\", msg.as_ref(), orig_msg)\n        }\n        Error::Codec(orig_msg) => {\n            error!(Codec, \"{}: {}\", msg.as_ref(), orig_msg)\n        }\n        Error::Transaction(reason) => Error::Transaction(reason),\n        Error::Provider(orig_msg) => {\n            error!(Provider, \"{}: {}\", msg.as_ref(), orig_msg)\n        }\n        Error::Other(orig_msg) => {\n            error!(Other, \"{}: {}\", msg.as_ref(), orig_msg)\n        }\n    }\n}\n"
  },
  {
    "path": "packages/fuels-test-helpers/Cargo.toml",
    "content": "[package]\nname = \"fuels-test-helpers\"\nversion = { workspace = true }\nauthors = { workspace = true }\nedition = { workspace = true }\nhomepage = { workspace = true }\nlicense = { workspace = true }\nrepository = { workspace = true }\nrust-version = { workspace = true }\ndescription = \"Fuel Rust SDK test helpers.\"\n\n[dependencies]\nfuel-core = { workspace = true, default-features = false, features = [\n  \"test-helpers\",\n  \"wasm-executor\",\n], optional = true }\nfuel-core-chain-config = { workspace = true, features = [\"test-helpers\"] }\nfuel-core-client = { workspace = true }\nfuel-core-poa = { workspace = true }\nfuel-core-services = { workspace = true }\nfuel-core-types = { workspace = true }\nfuel-crypto = { workspace = true }\nfuel-tx = { workspace = true }\nfuel-types = { workspace = true, features = [\"random\"] }\nfuels-accounts = { workspace = true, optional = true }\nfuels-core = { workspace = true }\nfutures = { workspace = true }\nportpicker = { workspace = true }\nrand = { workspace = true, default-features = false }\ntempfile = { workspace = true, default-features = false }\ntokio = { workspace = true, default-features = false }\nwhich = { workspace = true, default-features = false }\n\n[features]\ndefault = [\"fuels-accounts\", \"std\"]\nstd = [\"fuels-accounts?/std\", \"fuels-core/std\", \"fuel-core-chain-config/std\"]\nfuel-core-lib = [\"dep:fuel-core\"]\nrocksdb = [\"fuel-core?/rocksdb\"]\nfault-proving = [\"fuel-core?/fault-proving\", \"fuel-core-chain-config/fault-proving\", \"fuel-core-client/fault-proving\", \"fuel-core-poa/fault-proving\", \"fuels-accounts?/fault-proving\", \"fuels-core/fault-proving\"]\n"
  },
  {
    "path": "packages/fuels-test-helpers/src/accounts.rs",
    "content": "use std::mem::size_of;\n\nuse fuel_crypto::SecretKey;\nuse fuels_accounts::{signers::private_key::PrivateKeySigner, wallet::Wallet};\nuse fuels_core::types::errors::Result;\n\nuse crate::{\n    node_types::{ChainConfig, NodeConfig},\n    setup_custom_assets_coins, setup_test_provider,\n    wallets_config::*,\n};\n\n/// Launches a local Fuel node, instantiates a provider, and returns a wallet.\n/// The provider and the wallets are instantiated with the default configs.\n/// For more configurable options, see the `launch_custom_provider_and_get_wallets` function.\n/// # Examples\n/// ```\n/// use fuels_test_helpers::launch_provider_and_get_wallet;\n/// use fuels_accounts::ViewOnlyAccount;\n///\n/// async fn single_wallet() -> Result<(), Box<dyn std::error::Error>> {\n///   let wallet = launch_provider_and_get_wallet().await?;\n///   dbg!(wallet.address());\n///   Ok(())\n/// }\n/// ```\npub async fn launch_provider_and_get_wallet() -> Result<Wallet> {\n    let mut wallets =\n        launch_custom_provider_and_get_wallets(WalletsConfig::new(Some(1), None, None), None, None)\n            .await?;\n\n    Ok(wallets.pop().expect(\"should have one wallet\"))\n}\n\n/// Launches a custom node and provider, along with a configurable number of wallets.\n///\n/// # Examples\n/// ```\n/// use fuels_test_helpers::launch_custom_provider_and_get_wallets;\n/// use fuels_test_helpers::WalletsConfig;\n/// use fuels_accounts::ViewOnlyAccount;\n///\n/// async fn multiple_wallets() -> Result<(), Box<dyn std::error::Error>> {\n///   let num_wallets = 2;\n///   let num_coins = 1;\n///   let amount = 1;\n///   let config = WalletsConfig::new(Some(num_wallets), Some(num_coins), Some(amount));\n///\n///   let mut wallets = launch_custom_provider_and_get_wallets(config, None, None).await?;\n///   let first_wallet = wallets.pop().unwrap();\n///   dbg!(first_wallet.address());\n///   Ok(())\n/// }\n/// ```\npub async fn launch_custom_provider_and_get_wallets(\n    wallet_config: WalletsConfig,\n    node_config: Option<NodeConfig>,\n    chain_config: Option<ChainConfig>,\n) -> Result<Vec<Wallet>> {\n    const SIZE_SECRET_KEY: usize = size_of::<SecretKey>();\n    const PADDING_BYTES: usize = SIZE_SECRET_KEY - size_of::<u64>();\n\n    let signers: Vec<_> = (1..=wallet_config.num_wallets())\n        .map(|wallet_counter| {\n            let mut secret_key: [u8; SIZE_SECRET_KEY] = [0; SIZE_SECRET_KEY];\n            secret_key[PADDING_BYTES..].copy_from_slice(&wallet_counter.to_be_bytes());\n\n            let key = SecretKey::try_from(secret_key.as_slice())\n                .expect(\"This should never happen as we provide a [u8; SIZE_SECRET_KEY] array\");\n\n            PrivateKeySigner::new(key)\n        })\n        .collect();\n\n    let all_coins = signers\n        .iter()\n        .flat_map(|signer| setup_custom_assets_coins(signer.address(), wallet_config.assets()))\n        .collect::<Vec<_>>();\n\n    let provider = setup_test_provider(all_coins, vec![], node_config, chain_config).await?;\n\n    let wallets = signers\n        .into_iter()\n        .map(|signer| Wallet::new(signer, provider.clone()))\n        .collect::<Vec<_>>();\n\n    Ok(wallets)\n}\n\n#[cfg(test)]\nmod tests {\n    use fuel_core_chain_config::ChainConfig;\n    use fuel_tx::{ConsensusParameters, TxParameters};\n    use fuel_types::AssetId;\n    use fuels_accounts::ViewOnlyAccount;\n    use fuels_core::types::{coin_type::CoinType, errors::Result};\n    use rand::Fill;\n\n    use crate::{AssetConfig, WalletsConfig, launch_custom_provider_and_get_wallets};\n\n    #[tokio::test]\n    async fn test_wallet_config() -> Result<()> {\n        let num_wallets = 2;\n        let num_coins = 3;\n        let amount = 100;\n        let config = WalletsConfig::new(Some(num_wallets), Some(num_coins), Some(amount));\n\n        let wallets = launch_custom_provider_and_get_wallets(config, None, None).await?;\n        let provider = wallets.first().unwrap().try_provider()?;\n        let consensus_parameters = provider.consensus_parameters().await?;\n\n        assert_eq!(wallets.len(), num_wallets as usize);\n\n        for wallet in &wallets {\n            let coins = wallet\n                .get_coins(*consensus_parameters.base_asset_id())\n                .await?;\n\n            assert_eq!(coins.len(), num_coins as usize);\n\n            for coin in &coins {\n                assert_eq!(coin.amount, amount);\n            }\n        }\n        Ok(())\n    }\n\n    #[tokio::test]\n    async fn test_wallet_config_multiple_assets()\n    -> std::result::Result<(), Box<dyn std::error::Error>> {\n        let mut rng = rand::thread_rng();\n        let num_wallets = 3;\n\n        let asset_base = AssetConfig {\n            id: AssetId::zeroed(),\n            num_coins: 2,\n            coin_amount: 4,\n        };\n\n        let mut asset_id_1 = AssetId::zeroed();\n        asset_id_1.try_fill(&mut rng)?;\n        let asset_1 = AssetConfig {\n            id: asset_id_1,\n            num_coins: 6,\n            coin_amount: 8,\n        };\n\n        let mut asset_id_2 = AssetId::zeroed();\n        asset_id_2.try_fill(&mut rng)?;\n        let asset_2 = AssetConfig {\n            id: asset_id_2,\n            num_coins: 10,\n            coin_amount: 12,\n        };\n\n        let assets = vec![asset_base, asset_1, asset_2];\n\n        let config = WalletsConfig::new_multiple_assets(num_wallets, assets.clone());\n        let wallets = launch_custom_provider_and_get_wallets(config, None, None).await?;\n        assert_eq!(wallets.len(), num_wallets as usize);\n\n        for asset in assets {\n            for wallet in &wallets {\n                let resources = wallet\n                    .get_spendable_resources(\n                        asset.id,\n                        (asset.num_coins * asset.coin_amount).into(),\n                        None,\n                    )\n                    .await?;\n                assert_eq!(resources.len() as u64, asset.num_coins);\n\n                for resource in resources {\n                    assert_eq!(resource.amount(), asset.coin_amount);\n                    match resource {\n                        CoinType::Coin(coin) => {\n                            assert_eq!(coin.owner, wallet.address())\n                        }\n                        CoinType::Message(_) => panic!(\"resources contained messages\"),\n                        CoinType::Unknown => panic!(\"resources contained unknown coins\"),\n                    }\n                }\n            }\n        }\n        Ok(())\n    }\n\n    #[tokio::test]\n    async fn generated_wallets_are_deterministic() -> Result<()> {\n        let num_wallets = 32;\n        let num_coins = 1;\n        let amount = 100;\n        let config = WalletsConfig::new(Some(num_wallets), Some(num_coins), Some(amount));\n\n        let wallets = launch_custom_provider_and_get_wallets(config, None, None).await?;\n\n        assert_eq!(\n            wallets.get(31).unwrap().address().to_string(),\n            \"1c25f74846784d11715dfbe926fc41aca80e005fb782225aa8ad0dadf871cfc5\".to_string()\n        );\n        Ok(())\n    }\n\n    #[tokio::test]\n    async fn generated_wallets_with_custom_chain_config() -> Result<()> {\n        let mut consensus_parameters = ConsensusParameters::default();\n\n        let block_gas_limit = 10_000_000_000;\n        consensus_parameters.set_block_gas_limit(block_gas_limit);\n\n        let max_gas_per_tx = 10_000_000_000;\n        let tx_params = TxParameters::default().with_max_gas_per_tx(max_gas_per_tx);\n        consensus_parameters.set_tx_params(tx_params);\n\n        let chain_config = ChainConfig {\n            consensus_parameters,\n            ..ChainConfig::default()\n        };\n\n        let num_wallets = 4;\n        let num_coins = 3;\n        let coin_amount = 2_000_000_000;\n        let wallets = launch_custom_provider_and_get_wallets(\n            WalletsConfig::new(Some(num_wallets), Some(num_coins), Some(coin_amount)),\n            None,\n            Some(chain_config),\n        )\n        .await?;\n\n        assert_eq!(wallets.len() as u64, num_wallets);\n\n        for wallet in wallets.into_iter() {\n            assert_eq!(\n                wallet\n                    .try_provider()?\n                    .consensus_parameters()\n                    .await?\n                    .tx_params()\n                    .max_gas_per_tx(),\n                max_gas_per_tx\n            );\n            assert_eq!(\n                wallet.get_coins(AssetId::zeroed()).await?.len() as u64,\n                num_coins\n            );\n            assert_eq!(\n                *wallet\n                    .get_balances()\n                    .await?\n                    .get(\"0000000000000000000000000000000000000000000000000000000000000000\")\n                    .expect(\"failed to get value\"),\n                (num_coins * coin_amount) as u128\n            );\n        }\n\n        Ok(())\n    }\n}\n"
  },
  {
    "path": "packages/fuels-test-helpers/src/fuel_bin_service.rs",
    "content": "use std::{\n    net::{IpAddr, SocketAddr},\n    path::PathBuf,\n    time::Duration,\n};\n\nuse fuel_core_chain_config::{ChainConfig, SnapshotWriter, StateConfig};\nuse fuel_core_client::client::FuelClient;\nuse fuel_core_services::State;\nuse fuel_core_types::blockchain::header::LATEST_STATE_TRANSITION_VERSION;\nuse fuels_core::{error, types::errors::Result as FuelResult};\nuse portpicker::{is_free, pick_unused_port};\nuse tempfile::{TempDir, tempdir};\nuse tokio::{process::Command, spawn, task::JoinHandle, time::sleep};\n\nuse crate::node_types::{DbType, NodeConfig, Trigger};\n\n#[derive(Debug)]\npub(crate) struct ExtendedConfig {\n    pub node_config: NodeConfig,\n    pub chain_config: ChainConfig,\n    pub state_config: StateConfig,\n    pub snapshot_dir: TempDir,\n}\n\nimpl ExtendedConfig {\n    pub fn args_vec(&self) -> fuels_core::types::errors::Result<Vec<String>> {\n        let port = self.node_config.addr.port().to_string();\n        let mut args = vec![\n            \"run\".to_string(),\n            \"--ip\".to_string(),\n            \"127.0.0.1\".to_string(),\n            \"--port\".to_string(),\n            port,\n            \"--snapshot\".to_string(),\n            self.snapshot_dir\n                .path()\n                .to_str()\n                .expect(\"Failed to find config file\")\n                .to_string(),\n        ];\n\n        args.push(\"--db-type\".to_string());\n        match &self.node_config.database_type {\n            DbType::InMemory => args.push(\"in-memory\".to_string()),\n            DbType::RocksDb(path_to_db) => {\n                args.push(\"rocks-db\".to_string());\n                let path = path_to_db.as_ref().cloned().unwrap_or_else(|| {\n                    PathBuf::from(std::env::var(\"HOME\").expect(\"HOME env var missing\"))\n                        .join(\".fuel/db\")\n                });\n                args.push(\"--db-path\".to_string());\n                args.push(path.to_string_lossy().to_string());\n            }\n        }\n\n        if let Some(cache_size) = self.node_config.max_database_cache_size {\n            args.push(\"--max-database-cache-size\".to_string());\n            args.push(cache_size.to_string());\n        }\n\n        match self.node_config.block_production {\n            Trigger::Instant => {\n                args.push(\"--poa-instant=true\".to_string());\n            }\n            Trigger::Never => {\n                args.push(\"--poa-instant=false\".to_string());\n            }\n            Trigger::Interval { block_time } => {\n                args.push(format!(\n                    \"--poa-interval-period={}ms\",\n                    block_time.as_millis()\n                ));\n            }\n            Trigger::Open { period } => {\n                args.push(format!(\"--poa-open-period={}ms\", period.as_millis()));\n            }\n        };\n\n        let body_limit = self.node_config.graphql_request_body_bytes_limit;\n        args.push(format!(\"--graphql-request-body-bytes-limit={body_limit}\"));\n\n        // This ensures forward compatibility when running against a newer node with a different native executor version.\n        // If the node detects our older version in the chain configuration, it defaults to using the wasm executor.\n        // However, since we don't include a wasm executor, this would lead to code loading failure and a node crash.\n        // To prevent this, we force the node to use our version number to refer to its native executor.\n        let executor_version = self\n            .chain_config\n            .genesis_state_transition_version\n            .unwrap_or(LATEST_STATE_TRANSITION_VERSION);\n        args.push(format!(\"--native-executor-version={executor_version}\"));\n\n        args.extend(\n            [\n                (self.node_config.vm_backtrace, \"--vm-backtrace\"),\n                (self.node_config.utxo_validation, \"--utxo-validation\"),\n                (\n                    self.node_config.historical_execution,\n                    \"--historical-execution\",\n                ),\n                (self.node_config.debug, \"--debug\"),\n            ]\n            .into_iter()\n            .filter(|(flag, _)| *flag)\n            .map(|(_, arg)| arg.to_string()),\n        );\n\n        args.push(format!(\n            \"--starting-gas-price={}\",\n            self.node_config.starting_gas_price\n        ));\n\n        Ok(args)\n    }\n\n    pub fn write_temp_snapshot_files(self) -> FuelResult<TempDir> {\n        let writer = SnapshotWriter::json(self.snapshot_dir.path());\n        writer\n            .write_state_config(self.state_config, &self.chain_config)\n            .map_err(|e| error!(Other, \"could not write state config: {}\", e))?;\n\n        Ok(self.snapshot_dir)\n    }\n}\n\npub struct FuelService {\n    pub bound_address: SocketAddr,\n    handle: JoinHandle<()>,\n}\n\nimpl FuelService {\n    pub async fn new_node(\n        node_config: NodeConfig,\n        chain_config: ChainConfig,\n        state_config: StateConfig,\n    ) -> FuelResult<Self> {\n        let requested_port = node_config.addr.port();\n\n        let bound_address = match requested_port {\n            0 => get_socket_address()?,\n            _ if is_free(requested_port) => node_config.addr,\n            _ => {\n                return Err(error!(\n                    IO,\n                    \"could not find a free port to start a fuel node\"\n                ));\n            }\n        };\n\n        let node_config = NodeConfig {\n            addr: bound_address,\n            ..node_config\n        };\n\n        let extended_config = ExtendedConfig {\n            node_config,\n            state_config,\n            chain_config,\n            snapshot_dir: tempdir()?,\n        };\n\n        let addr = extended_config.node_config.addr;\n        let handle = run_node(extended_config).await?;\n        server_health_check(addr).await?;\n\n        Ok(FuelService {\n            bound_address,\n            handle,\n        })\n    }\n\n    pub fn stop(&self) -> FuelResult<State> {\n        self.handle.abort();\n        Ok(State::Stopped)\n    }\n}\n\nasync fn server_health_check(address: SocketAddr) -> FuelResult<()> {\n    let client = FuelClient::from(address);\n\n    let mut attempts = 5;\n    let mut healthy = client.health().await.unwrap_or(false);\n    let between_attempts = Duration::from_millis(300);\n\n    while attempts > 0 && !healthy {\n        healthy = client.health().await.unwrap_or(false);\n        sleep(between_attempts).await;\n        attempts -= 1;\n    }\n\n    if !healthy {\n        return Err(error!(Other, \"could not connect to fuel core server\"));\n    }\n\n    Ok(())\n}\n\nfn get_socket_address() -> FuelResult<SocketAddr> {\n    let free_port = pick_unused_port().ok_or(error!(Other, \"could not pick a free port\"))?;\n    let address: IpAddr = \"127.0.0.1\".parse().expect(\"is valid ip\");\n\n    Ok(SocketAddr::new(address, free_port))\n}\n\nasync fn run_node(extended_config: ExtendedConfig) -> FuelResult<JoinHandle<()>> {\n    let args = extended_config.args_vec()?;\n    let tempdir = extended_config.write_temp_snapshot_files()?;\n\n    let binary_name = \"fuel-core\";\n\n    let paths = which::which_all(binary_name)\n        .map_err(|_| error!(Other, \"failed to list `{binary_name}` binaries\"))?\n        .collect::<Vec<_>>();\n\n    let path = paths\n        .first()\n        .ok_or_else(|| error!(Other, \"no `{binary_name}` in PATH\"))?;\n\n    if paths.len() > 1 {\n        eprintln!(\n            \"found more than one `{binary_name}` binary in PATH, using `{}`\",\n            path.display()\n        );\n    }\n\n    let mut command = Command::new(path);\n    let running_node = command.args(args).kill_on_drop(true).env_clear().output();\n\n    let join_handle = spawn(async move {\n        // ensure drop is not called on the tmp dir and it lives throughout the lifetime of the node\n        let _unused = tempdir;\n        let result = running_node\n            .await\n            .expect(\"error: could not find `fuel-core` in PATH`\");\n        let stdout = String::from_utf8_lossy(&result.stdout);\n        let stderr = String::from_utf8_lossy(&result.stderr);\n        eprintln!(\n            \"the exit status from the fuel binary was: {result:?}, stdout: {stdout}, stderr: {stderr}\"\n        );\n    });\n\n    Ok(join_handle)\n}\n"
  },
  {
    "path": "packages/fuels-test-helpers/src/lib.rs",
    "content": "//! Testing helpers/utilities for Fuel SDK.\nextern crate core;\n\n#[cfg(feature = \"fuels-accounts\")]\npub use accounts::*;\nuse fuel_tx::{Bytes32, ConsensusParameters, ContractParameters, TxParameters, UtxoId};\nuse fuel_types::{AssetId, Nonce};\nuse fuels_accounts::provider::Provider;\nuse fuels_core::types::{\n    Address,\n    coin::Coin,\n    errors::Result,\n    message::{Message, MessageStatus},\n};\npub use node_types::*;\nuse rand::{Fill, Rng, SeedableRng, rngs::StdRng};\nuse utils::{into_coin_configs, into_message_configs};\npub use wallets_config::*;\nmod node_types;\n\n#[cfg(not(feature = \"fuel-core-lib\"))]\npub(crate) mod fuel_bin_service;\n\n#[cfg(feature = \"fuels-accounts\")]\nmod accounts;\n\npub use service::*;\nmod service;\n\nmod utils;\nmod wallets_config;\n\n/// Create a vector of `num_asset`*`coins_per_asset` UTXOs and a vector of the unique corresponding\n/// asset IDs. `AssetId`. Each UTXO (=coin) contains `amount_per_coin` amount of a random asset. The\n/// output of this function can be used with `setup_test_provider` to get a client with some\n/// pre-existing coins, with `num_asset` different asset ids. Note that one of the assets is the\n/// base asset to pay for gas.\npub fn setup_multiple_assets_coins(\n    owner: Address,\n    num_asset: u64,\n    coins_per_asset: u64,\n    amount_per_coin: u64,\n) -> (Vec<Coin>, Vec<AssetId>) {\n    let mut rng = rand::thread_rng();\n    // Create `num_asset-1` asset ids so there is `num_asset` in total with the base asset\n    let asset_ids = (0..(num_asset - 1))\n        .map(|_| {\n            let mut random_asset_id = AssetId::zeroed();\n            random_asset_id\n                .try_fill(&mut rng)\n                .expect(\"failed to fill with random data\");\n            random_asset_id\n        })\n        .chain([AssetId::zeroed()])\n        .collect::<Vec<AssetId>>();\n\n    let coins = asset_ids\n        .iter()\n        .flat_map(|id| setup_single_asset_coins(owner, *id, coins_per_asset, amount_per_coin))\n        .collect::<Vec<Coin>>();\n\n    (coins, asset_ids)\n}\n\n/// Create a vector of UTXOs with the provided AssetIds, num_coins, and amount_per_coin\npub fn setup_custom_assets_coins(owner: Address, assets: &[AssetConfig]) -> Vec<Coin> {\n    assets\n        .iter()\n        .flat_map(|asset| {\n            setup_single_asset_coins(owner, asset.id, asset.num_coins, asset.coin_amount)\n        })\n        .collect::<Vec<Coin>>()\n}\n\n/// Create a vector of `num_coins` UTXOs containing `amount_per_coin` amount of asset `asset_id`.\n/// The output of this function can be used with `setup_test_provider` to get a client with some\n/// pre-existing coins, but with only one asset ID.\npub fn setup_single_asset_coins(\n    owner: Address,\n    asset_id: AssetId,\n    num_coins: u64,\n    amount_per_coin: u64,\n) -> Vec<Coin> {\n    let mut rng = rand::thread_rng();\n\n    let coins: Vec<Coin> = (1..=num_coins)\n        .map(|_i| {\n            let mut r = Bytes32::zeroed();\n            r.try_fill(&mut rng)\n                .expect(\"failed to fill with random data\");\n            let utxo_id = UtxoId::new(r, 0);\n\n            Coin {\n                owner,\n                utxo_id,\n                amount: amount_per_coin,\n                asset_id,\n            }\n        })\n        .collect();\n\n    coins\n}\n\npub fn setup_single_message(\n    sender: Address,\n    recipient: Address,\n    amount: u64,\n    nonce: Nonce,\n    data: Vec<u8>,\n) -> Message {\n    Message {\n        sender,\n        recipient,\n        nonce,\n        amount,\n        data,\n        da_height: 0,\n        status: MessageStatus::Unspent,\n    }\n}\n\npub async fn setup_test_provider(\n    coins: Vec<Coin>,\n    messages: Vec<Message>,\n    node_config: Option<NodeConfig>,\n    chain_config: Option<ChainConfig>,\n) -> Result<Provider> {\n    let node_config = node_config.unwrap_or_default();\n    let chain_config = chain_config.unwrap_or_else(testnet_chain_config);\n\n    let coin_configs = into_coin_configs(coins);\n    let message_configs = into_message_configs(messages);\n\n    let state_config = StateConfig {\n        coins: coin_configs,\n        messages: message_configs,\n        ..StateConfig::local_testnet()\n    };\n\n    let srv = FuelService::start(node_config, chain_config, state_config).await?;\n\n    let address = srv.bound_address();\n\n    tokio::spawn(async move {\n        let _own_the_handle = srv;\n        let () = futures::future::pending().await;\n    });\n\n    Provider::from(address).await\n}\n\n// Testnet ChainConfig with increased tx size and contract size limits\nfn testnet_chain_config() -> ChainConfig {\n    let mut consensus_parameters = ConsensusParameters::default();\n    let tx_params = TxParameters::default().with_max_size(10_000_000);\n    // on a best effort basis, if we're given an old core we won't fail only because we couldn't\n    // set the limit here\n    let _ = consensus_parameters.set_block_transaction_size_limit(10_000_000);\n\n    let contract_params = ContractParameters::default().with_contract_max_size(1_000_000);\n    consensus_parameters.set_tx_params(tx_params);\n    consensus_parameters.set_contract_params(contract_params);\n\n    ChainConfig {\n        consensus_parameters,\n        ..ChainConfig::local_testnet()\n    }\n}\n\npub fn generate_random_salt() -> [u8; 32] {\n    StdRng::from_entropy().r#gen()\n}\n\n#[cfg(test)]\nmod tests {\n    use std::net::{Ipv4Addr, SocketAddr};\n\n    use fuel_tx::{ConsensusParameters, ContractParameters, FeeParameters, TxParameters};\n\n    use super::*;\n\n    #[tokio::test]\n    async fn test_setup_single_asset_coins() -> Result<()> {\n        let mut rng = rand::thread_rng();\n        let address = rng.r#gen();\n\n        let mut asset_id = AssetId::zeroed();\n        asset_id\n            .try_fill(&mut rng)\n            .expect(\"failed to fill with random data\");\n\n        let number_of_coins = 11;\n        let amount_per_coin = 10;\n        let coins = setup_single_asset_coins(address, asset_id, number_of_coins, amount_per_coin);\n\n        assert_eq!(coins.len() as u64, number_of_coins);\n        for coin in coins {\n            assert_eq!(coin.asset_id, asset_id);\n            assert_eq!(coin.amount, amount_per_coin);\n            assert_eq!(coin.owner, address);\n        }\n\n        Ok(())\n    }\n\n    #[tokio::test]\n    async fn test_setup_multiple_assets_coins() -> Result<()> {\n        let mut rng = rand::thread_rng();\n        let address = rng.r#gen();\n\n        let number_of_assets = 7;\n        let coins_per_asset = 10;\n        let amount_per_coin = 13;\n        let (coins, unique_asset_ids) = setup_multiple_assets_coins(\n            address,\n            number_of_assets,\n            coins_per_asset,\n            amount_per_coin,\n        );\n\n        assert_eq!(coins.len() as u64, number_of_assets * coins_per_asset);\n        assert_eq!(unique_asset_ids.len() as u64, number_of_assets);\n        // Check that the wallet has base assets to pay for gas\n        assert!(\n            unique_asset_ids\n                .iter()\n                .any(|&asset_id| asset_id == AssetId::zeroed())\n        );\n        for asset_id in unique_asset_ids {\n            let coins_asset_id: Vec<Coin> = coins\n                .clone()\n                .into_iter()\n                .filter(|c| c.asset_id == asset_id)\n                .collect();\n            assert_eq!(coins_asset_id.len() as u64, coins_per_asset);\n            for coin in coins_asset_id {\n                assert_eq!(coin.owner, address);\n                assert_eq!(coin.amount, amount_per_coin);\n            }\n        }\n\n        Ok(())\n    }\n\n    #[tokio::test]\n    async fn test_setup_custom_assets_coins() -> Result<()> {\n        let mut rng = rand::thread_rng();\n        let address = rng.r#gen();\n\n        let asset_base = AssetConfig {\n            id: AssetId::zeroed(),\n            num_coins: 2,\n            coin_amount: 4,\n        };\n\n        let mut asset_id_1 = AssetId::zeroed();\n        asset_id_1\n            .try_fill(&mut rng)\n            .expect(\"failed to fill with random data\");\n        let asset_1 = AssetConfig {\n            id: asset_id_1,\n            num_coins: 6,\n            coin_amount: 8,\n        };\n\n        let mut asset_id_2 = AssetId::zeroed();\n        asset_id_2\n            .try_fill(&mut rng)\n            .expect(\"failed to fill with random data\");\n        let asset_2 = AssetConfig {\n            id: asset_id_2,\n            num_coins: 10,\n            coin_amount: 12,\n        };\n\n        let assets = vec![asset_base, asset_1, asset_2];\n        let coins = setup_custom_assets_coins(address, &assets);\n\n        for asset in assets {\n            let coins_asset_id: Vec<Coin> = coins\n                .clone()\n                .into_iter()\n                .filter(|c| c.asset_id == asset.id)\n                .collect();\n            assert_eq!(coins_asset_id.len() as u64, asset.num_coins);\n            for coin in coins_asset_id {\n                assert_eq!(coin.owner, address);\n                assert_eq!(coin.amount, asset.coin_amount);\n            }\n        }\n        Ok(())\n    }\n\n    #[tokio::test]\n    async fn test_setup_test_provider_custom_config() -> Result<()> {\n        let socket = SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), 4000);\n        let config = NodeConfig {\n            addr: socket,\n            ..NodeConfig::default()\n        };\n\n        let provider = setup_test_provider(vec![], vec![], Some(config.clone()), None).await?;\n        let node_info = provider\n            .node_info()\n            .await\n            .expect(\"Failed to retrieve node info!\");\n\n        assert_eq!(provider.url(), format!(\"http://127.0.0.1:4000\"));\n        assert_eq!(node_info.utxo_validation, config.utxo_validation);\n\n        Ok(())\n    }\n\n    #[tokio::test]\n    async fn test_setup_test_client_consensus_parameters_config() -> Result<()> {\n        let tx_params = TxParameters::default()\n            .with_max_gas_per_tx(2)\n            .with_max_inputs(58);\n        let fee_params = FeeParameters::default().with_gas_per_byte(2);\n        let contract_params = ContractParameters::default().with_max_storage_slots(83);\n\n        let mut consensus_parameters = ConsensusParameters::default();\n        consensus_parameters.set_tx_params(tx_params);\n        consensus_parameters.set_fee_params(fee_params);\n        consensus_parameters.set_contract_params(contract_params);\n\n        let chain_config = ChainConfig {\n            consensus_parameters: consensus_parameters.clone(),\n            ..ChainConfig::default()\n        };\n        let provider = setup_test_provider(vec![], vec![], None, Some(chain_config)).await?;\n\n        let retrieved_parameters = provider.consensus_parameters().await?;\n\n        assert_eq!(retrieved_parameters, consensus_parameters);\n\n        Ok(())\n    }\n\n    #[tokio::test]\n    async fn test_chain_config_and_consensus_parameters() -> Result<()> {\n        let max_inputs = 123;\n        let gas_per_byte = 456;\n\n        let mut consensus_parameters = ConsensusParameters::default();\n\n        let tx_params = TxParameters::default().with_max_inputs(max_inputs);\n        consensus_parameters.set_tx_params(tx_params);\n\n        let fee_params = FeeParameters::default().with_gas_per_byte(gas_per_byte);\n        consensus_parameters.set_fee_params(fee_params);\n\n        let chain_name = \"fuel-0\".to_string();\n        let chain_config = ChainConfig {\n            chain_name: chain_name.clone(),\n            consensus_parameters,\n            ..ChainConfig::local_testnet()\n        };\n\n        let provider = setup_test_provider(vec![], vec![], None, Some(chain_config)).await?;\n\n        let chain_info = provider.chain_info().await?;\n\n        assert_eq!(chain_info.name, chain_name);\n        assert_eq!(\n            chain_info.consensus_parameters.tx_params().max_inputs(),\n            max_inputs\n        );\n        assert_eq!(\n            chain_info.consensus_parameters.fee_params().gas_per_byte(),\n            gas_per_byte\n        );\n        Ok(())\n    }\n}\n"
  },
  {
    "path": "packages/fuels-test-helpers/src/node_types.rs",
    "content": "use std::{\n    net::{Ipv4Addr, SocketAddr},\n    path::PathBuf,\n    time::Duration,\n};\n\npub use fuel_core_chain_config::{ChainConfig, StateConfig};\n\n#[derive(Clone, Debug)]\npub enum Trigger {\n    Instant,\n    Never,\n    Interval { block_time: Duration },\n    Open { period: Duration },\n}\n\n#[cfg(feature = \"fuel-core-lib\")]\nimpl From<Trigger> for fuel_core_poa::Trigger {\n    fn from(value: Trigger) -> Self {\n        match value {\n            Trigger::Instant => fuel_core_poa::Trigger::Instant,\n            Trigger::Never => fuel_core_poa::Trigger::Never,\n            Trigger::Interval { block_time } => fuel_core_poa::Trigger::Interval { block_time },\n            Trigger::Open { period } => fuel_core_poa::Trigger::Open { period },\n        }\n    }\n}\n\n#[derive(Clone, Debug)]\npub enum DbType {\n    InMemory,\n    RocksDb(Option<PathBuf>),\n}\n\n#[cfg(feature = \"fuel-core-lib\")]\nimpl From<DbType> for fuel_core::service::DbType {\n    fn from(value: DbType) -> Self {\n        match value {\n            DbType::InMemory => fuel_core::service::DbType::InMemory,\n            DbType::RocksDb(..) => fuel_core::service::DbType::RocksDb,\n        }\n    }\n}\n\n#[derive(Clone, Debug)]\npub struct NodeConfig {\n    pub addr: SocketAddr,\n    pub max_database_cache_size: Option<usize>,\n    pub database_type: DbType,\n    pub utxo_validation: bool,\n    pub historical_execution: bool,\n    pub debug: bool,\n    pub block_production: Trigger,\n    pub vm_backtrace: bool,\n    pub silent: bool,\n    pub starting_gas_price: u64,\n    pub graphql_request_body_bytes_limit: u64,\n}\n\nimpl Default for NodeConfig {\n    fn default() -> Self {\n        Self {\n            addr: SocketAddr::new(Ipv4Addr::new(127, 0, 0, 1).into(), 0),\n            max_database_cache_size: None,\n            database_type: DbType::InMemory,\n            utxo_validation: true,\n            historical_execution: false,\n            debug: true,\n            block_production: Trigger::Instant,\n            vm_backtrace: false,\n            silent: true,\n            starting_gas_price: 1,\n            graphql_request_body_bytes_limit: u64::MAX,\n        }\n    }\n}\n"
  },
  {
    "path": "packages/fuels-test-helpers/src/service.rs",
    "content": "#[cfg(feature = \"fuel-core-lib\")]\nuse fuel_core::service::{Config as ServiceConfig, FuelService as CoreFuelService};\nuse fuel_core_chain_config::{ChainConfig, StateConfig};\nuse fuel_core_services::State;\nuse fuels_core::types::errors::{Result, error};\nuse std::net::SocketAddr;\n\nuse crate::NodeConfig;\n#[cfg(not(feature = \"fuel-core-lib\"))]\nuse crate::fuel_bin_service::FuelService as BinFuelService;\n\npub struct FuelService {\n    #[cfg(feature = \"fuel-core-lib\")]\n    service: CoreFuelService,\n    #[cfg(not(feature = \"fuel-core-lib\"))]\n    service: BinFuelService,\n    bound_address: SocketAddr,\n}\n\nimpl FuelService {\n    pub async fn start(\n        node_config: NodeConfig,\n        chain_config: ChainConfig,\n        state_config: StateConfig,\n    ) -> Result<Self> {\n        #[cfg(feature = \"fuel-core-lib\")]\n        let service = {\n            let config = Self::service_config(node_config, chain_config, state_config);\n            CoreFuelService::new_node(config)\n                .await\n                .map_err(|err| error!(Other, \"{err}\"))?\n        };\n\n        #[cfg(not(feature = \"fuel-core-lib\"))]\n        let service = BinFuelService::new_node(node_config, chain_config, state_config).await?;\n\n        let bound_address = service.bound_address;\n\n        Ok(FuelService {\n            service,\n            bound_address,\n        })\n    }\n\n    pub async fn stop(&self) -> Result<State> {\n        #[cfg(feature = \"fuel-core-lib\")]\n        let result = self.service.send_stop_signal_and_await_shutdown().await;\n\n        #[cfg(not(feature = \"fuel-core-lib\"))]\n        let result = self.service.stop();\n\n        result.map_err(|err| error!(Other, \"{err}\"))\n    }\n\n    pub fn bound_address(&self) -> SocketAddr {\n        self.bound_address\n    }\n\n    #[cfg(feature = \"fuel-core-lib\")]\n    fn service_config(\n        node_config: NodeConfig,\n        chain_config: ChainConfig,\n        state_config: StateConfig,\n    ) -> ServiceConfig {\n        use std::time::Duration;\n\n        #[cfg(feature = \"rocksdb\")]\n        use fuel_core::state::rocks_db::{ColumnsPolicy, DatabaseConfig};\n        use fuel_core::{\n            combined_database::CombinedDatabaseConfig,\n            fuel_core_graphql_api::ServiceConfig as GraphQLConfig, service::config::GasPriceConfig,\n        };\n        use fuel_core_chain_config::SnapshotReader;\n\n        use crate::DbType;\n\n        let snapshot_reader = SnapshotReader::new_in_memory(chain_config, state_config);\n\n        let combined_db_config = CombinedDatabaseConfig {\n            database_path: match &node_config.database_type {\n                DbType::InMemory => Default::default(),\n                DbType::RocksDb(path) => path.clone().unwrap_or_default(),\n            },\n            database_type: node_config.database_type.into(),\n            #[cfg(feature = \"rocksdb\")]\n            database_config: DatabaseConfig {\n                cache_capacity: node_config.max_database_cache_size,\n                max_fds: 512,\n                columns_policy: ColumnsPolicy::Lazy,\n            },\n            #[cfg(feature = \"rocksdb\")]\n            state_rewind_policy:\n                fuel_core::state::historical_rocksdb::StateRewindPolicy::RewindFullRange,\n        };\n\n        ServiceConfig {\n            graphql_config: GraphQLConfig {\n                addr: node_config.addr,\n                max_queries_depth: 16,\n                max_queries_complexity: 80000,\n                max_queries_recursive_depth: 16,\n                max_queries_resolver_recursive_depth: 1,\n                max_queries_directives: 10,\n                max_concurrent_queries: 1024,\n                required_fuel_block_height_tolerance: 10,\n                required_fuel_block_height_timeout: Duration::from_secs(30),\n                request_body_bytes_limit: 16 * 1024 * 1024,\n                block_subscriptions_queue: 100,\n                query_log_threshold_time: Duration::from_secs(2),\n                api_request_timeout: Duration::from_secs(60),\n                database_batch_size: 100,\n                assemble_tx_dry_run_limit: 3,\n                assemble_tx_estimate_predicates_limit: 5,\n                costs: Default::default(),\n                number_of_threads: 2,\n            },\n            combined_db_config,\n            snapshot_reader,\n            historical_execution: node_config.historical_execution,\n            utxo_validation: node_config.utxo_validation,\n            debug: node_config.debug,\n            block_production: node_config.block_production.into(),\n            gas_price_config: GasPriceConfig {\n                starting_exec_gas_price: node_config.starting_gas_price,\n                ..GasPriceConfig::local_node()\n            },\n            ..ServiceConfig::local_node()\n        }\n    }\n}\n"
  },
  {
    "path": "packages/fuels-test-helpers/src/utils.rs",
    "content": "use fuel_core_chain_config::{CoinConfig, MessageConfig};\nuse fuels_core::types::{coin::Coin, message::Message};\n\npub(crate) fn into_coin_configs(coins: Vec<Coin>) -> Vec<CoinConfig> {\n    coins\n        .into_iter()\n        .map(Into::into)\n        .collect::<Vec<CoinConfig>>()\n}\n\npub(crate) fn into_message_configs(messages: Vec<Message>) -> Vec<MessageConfig> {\n    messages\n        .into_iter()\n        .map(Into::into)\n        .collect::<Vec<MessageConfig>>()\n}\n"
  },
  {
    "path": "packages/fuels-test-helpers/src/wallets_config.rs",
    "content": "use fuel_types::AssetId;\n\n// These constants define the default number of wallets to be setup,\n// the number of coins per wallet and the amount per coin\npub const DEFAULT_NUM_WALLETS: u64 = 10;\npub const DEFAULT_NUM_COINS: u64 = 1;\npub const DEFAULT_COIN_AMOUNT: u64 = 1_000_000_000;\n\n#[derive(Debug, Clone)]\npub struct AssetConfig {\n    pub id: AssetId,\n    pub num_coins: u64,\n    pub coin_amount: u64,\n}\n\n#[derive(Debug)]\npub struct WalletsConfig {\n    num_wallets: u64,\n    assets: Vec<AssetConfig>,\n}\n\nimpl WalletsConfig {\n    pub fn new(num_wallets: Option<u64>, num_coins: Option<u64>, coin_amount: Option<u64>) -> Self {\n        Self {\n            num_wallets: num_wallets.unwrap_or(DEFAULT_NUM_WALLETS),\n            assets: vec![AssetConfig {\n                id: AssetId::zeroed(),\n                num_coins: num_coins.unwrap_or(DEFAULT_NUM_COINS),\n                coin_amount: coin_amount.unwrap_or(DEFAULT_COIN_AMOUNT),\n            }],\n        }\n    }\n\n    pub fn new_multiple_assets(num_wallets: u64, assets: Vec<AssetConfig>) -> Self {\n        Self {\n            num_wallets,\n            assets,\n        }\n    }\n\n    pub fn num_wallets(&self) -> u64 {\n        self.num_wallets\n    }\n\n    pub fn assets(&self) -> &[AssetConfig] {\n        &self.assets[..]\n    }\n}\n\nimpl Default for WalletsConfig {\n    fn default() -> Self {\n        Self {\n            num_wallets: DEFAULT_NUM_WALLETS,\n            assets: vec![AssetConfig {\n                id: AssetId::zeroed(),\n                num_coins: DEFAULT_NUM_COINS,\n                coin_amount: DEFAULT_COIN_AMOUNT,\n            }],\n        }\n    }\n}\n"
  },
  {
    "path": "rustfmt.toml",
    "content": "fn_params_layout = \"Tall\"\nhard_tabs = false\nmatch_arm_leading_pipes = \"Never\"\nmax_width = 100\nmerge_derives = true\nremove_nested_parens = true\nreorder_imports = true\nreorder_modules = true\ntab_spaces = 4\nuse_field_init_shorthand = false\nuse_small_heuristics = \"Default\"\nuse_try_shorthand = false\n"
  },
  {
    "path": "scripts/change-log/Cargo.toml",
    "content": "[package]\nname = \"change-log\"\nversion = { workspace = true }\nauthors = { workspace = true }\nedition = { workspace = true }\nhomepage = { workspace = true }\nlicense = { workspace = true }\npublish = false\nrepository = { workspace = true }\nrust-version = { workspace = true }\n\n[dependencies]\ndialoguer = { version = \"0.11\", features = [\"fuzzy-select\"] }\ndotenv = { workspace = true }\noctocrab = { workspace = true, features = [\"default\"] }\nregex = { workspace = true }\nserde_json = { workspace = true }\ntokio = { workspace = true, features = [\"rt-multi-thread\", \"macros\"] }\n"
  },
  {
    "path": "scripts/change-log/src/adapters/octocrab.rs",
    "content": "use octocrab::{Octocrab, models::pulls::PullRequest};\nuse regex::Regex;\nuse serde_json::Value;\n\nuse crate::{\n    domain::{changelog::capitalize, models::ChangelogInfo},\n    ports::github::GitHubPort,\n};\n\npub struct OctocrabAdapter {\n    client: Octocrab,\n}\n\nimpl OctocrabAdapter {\n    pub fn new(token: &str) -> Self {\n        let client = Octocrab::builder()\n            .personal_token(token.to_string())\n            .build()\n            .unwrap();\n        Self { client }\n    }\n\n    /// Retrieve the pull request associated with a commit SHA.\n    async fn get_pr_for_commit(\n        &self,\n        owner: &str,\n        repo: &str,\n        commit_sha: &str,\n    ) -> Result<PullRequest, Box<dyn std::error::Error>> {\n        let pr_info = self\n            .client\n            .repos(owner, repo)\n            .list_pulls(commit_sha.to_string())\n            .send()\n            .await?;\n\n        if pr_info.items.is_empty() {\n            return Err(\"No PR found for this commit SHA\".into());\n        }\n\n        let pr = pr_info.items.into_iter().next().unwrap();\n\n        // Ignore PRs from \"fuel-service-user\"\n        if pr.user.as_ref().map_or(\"\", |u| &u.login) == \"fuel-service-user\" {\n            return Err(\"PR from fuel-service-user ignored\".into());\n        }\n\n        Ok(pr)\n    }\n\n    pub async fn search_branches(\n        &self,\n        owner: &str,\n        repo: &str,\n        query: &str,\n    ) -> Result<Vec<String>, Box<dyn std::error::Error>> {\n        let payload = serde_json::json!({\n            \"query\": r#\"\n                query($owner: String!, $repo: String!, $query: String!) {\n                    repository(owner: $owner, name: $repo) {\n                        refs(refPrefix: \"refs/heads/\", query: $query, first: 100) {\n                            nodes {\n                                name\n                            }\n                        }\n                    }\n                }\n            \"#,\n            \"variables\": {\n                \"owner\": owner,\n                \"repo\": repo,\n                \"query\": query,\n            }\n        });\n\n        let response: Value = self.client.graphql(&payload).await?;\n\n        let nodes = response[\"data\"][\"repository\"][\"refs\"][\"nodes\"]\n            .as_array()\n            .ok_or(\"Could not parse branch nodes from response\")?;\n\n        let branch_names = nodes\n            .iter()\n            .filter_map(|node| node[\"name\"].as_str().map(|s| s.to_owned()))\n            .collect();\n\n        Ok(branch_names)\n    }\n\n    /// Query GitHub for all releases in the repository.\n    pub async fn get_releases(\n        &self,\n        owner: &str,\n        repo: &str,\n    ) -> Result<Vec<String>, Box<dyn std::error::Error>> {\n        let releases = self\n            .client\n            .repos(owner, repo)\n            .releases()\n            .list()\n            .per_page(100)\n            .send()\n            .await?;\n\n        let release_tags = releases\n            .items\n            .into_iter()\n            .map(|release| release.tag_name)\n            .collect();\n\n        Ok(release_tags)\n    }\n\n    /// Build a ChangelogInfo instance from a commit.\n    async fn build_changelog_info(\n        &self,\n        owner: &str,\n        repo: &str,\n        commit_sha: &str,\n    ) -> Result<ChangelogInfo, Box<dyn std::error::Error>> {\n        let pr = self.get_pr_for_commit(owner, repo, commit_sha).await?;\n\n        let pr_title_full = pr.title.as_ref().unwrap_or(&\"\".to_string()).clone();\n        let pr_type = pr_title_full\n            .split(':')\n            .next()\n            .unwrap_or(\"misc\")\n            .to_string();\n        let is_breaking = pr_title_full.contains('!');\n        let title_description = pr_title_full\n            .split(':')\n            .nth(1)\n            .unwrap_or(\"\")\n            .trim()\n            .to_string();\n        let pr_number = pr.number;\n        let pr_author = pr.user.as_ref().map_or(\"\", |u| &u.login).to_string();\n        let pr_url = pr.html_url.map(|u| u.to_string()).unwrap_or_default();\n\n        let bullet_point = format!(\n            \"- [#{}]({}) - {}, by @{}\",\n            pr_number, pr_url, title_description, pr_author\n        );\n\n        let breaking_changes_regex = Regex::new(r\"(?s)# Breaking Changes\\s*(.*)\")?;\n        let breaking_changes = breaking_changes_regex\n            .captures(pr.body.as_ref().unwrap_or(&String::new()))\n            .and_then(|cap| cap.get(1))\n            .map(|m| {\n                m.as_str()\n                    .split(\"\\n# \")\n                    .next()\n                    .unwrap_or(\"\")\n                    .trim()\n                    .to_string()\n            })\n            .unwrap_or_default();\n\n        let release_notes_regex = Regex::new(r\"(?s)In this release, we:\\s*(.*)\")?;\n        let release_notes = release_notes_regex\n            .captures(pr.body.as_ref().unwrap_or(&String::new()))\n            .and_then(|cap| cap.get(1))\n            .map(|m| {\n                m.as_str()\n                    .split(\"\\n# \")\n                    .next()\n                    .unwrap_or(\"\")\n                    .trim()\n                    .to_string()\n            })\n            .unwrap_or_default();\n\n        let migration_note = format!(\n            \"### [{} - {}]({})\\n\\n{}\",\n            pr_number,\n            capitalize(&title_description),\n            pr_url,\n            breaking_changes\n        );\n\n        Ok(ChangelogInfo {\n            is_breaking,\n            pr_type,\n            bullet_point,\n            migration_note,\n            release_notes,\n        })\n    }\n}\n\nimpl GitHubPort for OctocrabAdapter {\n    async fn get_changelog_infos(\n        &self,\n        owner: &str,\n        repo: &str,\n        base: &str,\n        head: &str,\n    ) -> Result<Vec<ChangelogInfo>, Box<dyn std::error::Error>> {\n        let comparison = self\n            .client\n            .commits(owner, repo)\n            .compare(base, head)\n            .send()\n            .await?;\n\n        let mut changelogs = Vec::new();\n\n        for commit in comparison.commits {\n            match self.build_changelog_info(owner, repo, &commit.sha).await {\n                Ok(info) => changelogs.push(info),\n                Err(e) => {\n                    eprintln!(\"Error retrieving PR for commit {}: {}\", commit.sha, e);\n                    continue;\n                }\n            }\n        }\n\n        changelogs.sort_by(|a, b| a.pr_type.cmp(&b.pr_type));\n\n        Ok(changelogs)\n    }\n\n    async fn get_latest_release_tag(\n        &self,\n        owner: &str,\n        repo: &str,\n    ) -> Result<String, Box<dyn std::error::Error>> {\n        let latest_release = self\n            .client\n            .repos(owner, repo)\n            .releases()\n            .get_latest()\n            .await?;\n        Ok(latest_release.tag_name)\n    }\n}\n"
  },
  {
    "path": "scripts/change-log/src/adapters.rs",
    "content": "pub mod octocrab;\n"
  },
  {
    "path": "scripts/change-log/src/domain/changelog.rs",
    "content": "use std::collections::{HashMap, HashSet};\n\nuse crate::domain::models::ChangelogInfo;\n\nfn category_from_pr_type(pr_type: &str) -> Option<&'static str> {\n    match pr_type.trim_end_matches('!') {\n        \"feat\" => Some(\"Features\"),\n        \"fix\" => Some(\"Fixes\"),\n        \"chore\" => Some(\"Chores\"),\n        _ => None,\n    }\n}\n\npub fn generate_changelog(changelogs: Vec<ChangelogInfo>) -> String {\n    let mut content = String::new();\n\n    let mut non_breaking: HashMap<&str, Vec<String>> = HashMap::new();\n    let mut breaking: HashMap<&str, Vec<String>> = HashMap::new();\n    let mut migration_notes: Vec<String> = Vec::new();\n    let mut summary_set: HashSet<String> = HashSet::new();\n\n    for changelog in &changelogs {\n        if !changelog.release_notes.is_empty() {\n            summary_set.insert(changelog.release_notes.clone());\n        }\n        if let Some(category) = category_from_pr_type(&changelog.pr_type) {\n            if changelog.is_breaking {\n                breaking\n                    .entry(category)\n                    .or_default()\n                    .push(changelog.bullet_point.clone());\n                migration_notes.push(changelog.migration_note.clone());\n            } else {\n                non_breaking\n                    .entry(category)\n                    .or_default()\n                    .push(changelog.bullet_point.clone());\n            }\n        }\n    }\n\n    if !summary_set.is_empty() {\n        content.push_str(\"# Summary\\n\\nIn this release, we:\\n\");\n        let mut summary_lines: Vec<String> = summary_set.into_iter().collect();\n        summary_lines.sort();\n        for line in summary_lines {\n            content.push_str(&format!(\"{}\\n\", line));\n        }\n        content.push('\\n');\n    }\n\n    let categories = [\"Features\", \"Fixes\", \"Chores\"];\n    if !breaking.is_empty() {\n        content.push_str(\"# Breaking\\n\\n\");\n        for cat in &categories {\n            if let Some(items) = breaking.get(cat) {\n                content.push_str(&format!(\"- {}\\n\", cat));\n\n                let indented = items\n                    .iter()\n                    .map(|s| format!(\"\\t{}\", s))\n                    .collect::<Vec<_>>()\n                    .join(\"\\n\");\n                content.push_str(&format!(\"{}\\n\\n\", indented));\n            }\n        }\n    }\n\n    let mut write_section = |title: &str, items: &[String]| {\n        if !items.is_empty() {\n            content.push_str(&format!(\"# {}\\n\\n\", title));\n            content.push_str(&format!(\"{}\\n\\n\", items.join(\"\\n\\n\")));\n        }\n    };\n\n    for cat in &categories {\n        if let Some(items) = non_breaking.get(cat) {\n            write_section(cat, items);\n        }\n    }\n\n    if !migration_notes.is_empty() {\n        write_section(\"Migration Notes\", &migration_notes);\n    }\n\n    content.trim().to_string()\n}\n\n/// Utility function to capitalize a string.\npub fn capitalize(s: &str) -> String {\n    let mut c = s.chars();\n    match c.next() {\n        None => String::new(),\n        Some(f) => f.to_uppercase().collect::<String>() + c.as_str(),\n    }\n}\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use crate::domain::models::ChangelogInfo;\n\n    #[test]\n    fn test_generate_changelog_exact() {\n        let changelog1 = ChangelogInfo {\n            is_breaking: false,\n            pr_type: \"feat\".to_string(),\n            bullet_point: \"- [#1](http://example.com) - Added feature, by @alice\".to_string(),\n            migration_note: \"\".to_string(),\n            release_notes: \"Added feature\".to_string(),\n        };\n\n        let changelog2 = ChangelogInfo {\n            is_breaking: true,\n            pr_type: \"fix!\".to_string(),\n            bullet_point: \"- [#2](http://example.com) - Fixed bug, by @bob\".to_string(),\n            migration_note: \"### [2 - Fixed bug](http://example.com)\\n\\nCritical fix\".to_string(),\n            release_notes: \"Fixed bug\".to_string(),\n        };\n\n        let changelog3 = ChangelogInfo {\n            is_breaking: false,\n            pr_type: \"chore\".to_string(),\n            bullet_point: \"- [#3](http://example.com) - Update dependencies, by @carol\".to_string(),\n            migration_note: \"\".to_string(),\n            release_notes: \"\".to_string(),\n        };\n\n        let changelogs = vec![changelog1, changelog2, changelog3];\n        let markdown = generate_changelog(changelogs);\n\n        let expected = \"\\\n# Summary\n\nIn this release, we:\nAdded feature\nFixed bug\n\n# Breaking\n\n- Fixes\n\\t- [#2](http://example.com) - Fixed bug, by @bob\n\n# Features\n\n- [#1](http://example.com) - Added feature, by @alice\n\n# Chores\n\n- [#3](http://example.com) - Update dependencies, by @carol\n\n# Migration Notes\n\n### [2 - Fixed bug](http://example.com)\n\nCritical fix\";\n\n        assert_eq!(markdown, expected);\n    }\n}\n"
  },
  {
    "path": "scripts/change-log/src/domain/models.rs",
    "content": "#[derive(Debug, Clone)]\npub struct ChangelogInfo {\n    pub is_breaking: bool,\n    pub pr_type: String,\n    pub bullet_point: String,\n    pub migration_note: String,\n    pub release_notes: String,\n}\n"
  },
  {
    "path": "scripts/change-log/src/domain.rs",
    "content": "pub mod changelog;\npub mod models;\n"
  },
  {
    "path": "scripts/change-log/src/lib.rs",
    "content": "pub mod adapters;\npub mod domain;\npub mod ports;\n"
  },
  {
    "path": "scripts/change-log/src/main.rs",
    "content": "use std::env;\n\nuse change_log::{\n    adapters::octocrab::OctocrabAdapter, domain::changelog::generate_changelog,\n    ports::github::GitHubPort,\n};\nuse dialoguer::FuzzySelect;\nuse dotenv::dotenv;\n\n#[tokio::main]\nasync fn main() -> Result<(), Box<dyn std::error::Error>> {\n    dotenv().ok();\n\n    let github_token =\n        env::var(\"GITHUB_TOKEN\").expect(\"GITHUB_TOKEN is not set in the environment\");\n    let repo_owner = env::var(\"GITHUB_REPOSITORY_OWNER\").unwrap_or_else(|_| \"FuelLabs\".to_string());\n    let repo_name = env::var(\"GITHUB_REPOSITORY_NAME\").unwrap_or_else(|_| \"fuels-rs\".to_string());\n\n    let github_adapter = OctocrabAdapter::new(&github_token);\n\n    let branches = {\n        let mut branches = vec![\"master\".to_string()];\n        let lts_branches = github_adapter\n            .search_branches(&repo_owner, &repo_name, \"lts/\")\n            .await?;\n        branches.extend(lts_branches);\n        branches\n    };\n\n    let branch_selection = FuzzySelect::new()\n        .with_prompt(\"Select the target branch (start typing to filter)\")\n        .items(&branches)\n        .default(0)\n        .interact()?;\n\n    let target_branch = branches[branch_selection].clone();\n\n    let releases = github_adapter.get_releases(&repo_owner, &repo_name).await?;\n    if releases.is_empty() {\n        return Err(\"No releases found for the repository\".into());\n    }\n    let release_selection = FuzzySelect::new()\n        .with_prompt(\"Select the previous release tag\")\n        .items(&releases)\n        .default(0)\n        .interact()?;\n    let previous_release_tag = releases[release_selection].clone();\n\n    eprintln!(\"Using branch: {}\", target_branch);\n    eprintln!(\"Using previous release: {}\", previous_release_tag);\n\n    let changelog_infos = github_adapter\n        .get_changelog_infos(\n            &repo_owner,\n            &repo_name,\n            &previous_release_tag,\n            &target_branch,\n        )\n        .await?;\n\n    let changelog_markdown = generate_changelog(changelog_infos);\n\n    println!(\"{changelog_markdown}\");\n\n    Ok(())\n}\n"
  },
  {
    "path": "scripts/change-log/src/ports/github.rs",
    "content": "use crate::domain::models::ChangelogInfo;\n\n#[allow(async_fn_in_trait)]\npub trait GitHubPort {\n    /// Retrieve a collection of changelog infos based on the commit comparison between `base` and `head`.\n    async fn get_changelog_infos(\n        &self,\n        owner: &str,\n        repo: &str,\n        base: &str,\n        head: &str,\n    ) -> Result<Vec<ChangelogInfo>, Box<dyn std::error::Error>>;\n\n    /// Retrieve the latest release tag for the given repository.\n    async fn get_latest_release_tag(\n        &self,\n        owner: &str,\n        repo: &str,\n    ) -> Result<String, Box<dyn std::error::Error>>;\n}\n"
  },
  {
    "path": "scripts/change-log/src/ports.rs",
    "content": "pub mod github;\n"
  },
  {
    "path": "scripts/check-docs/Cargo.toml",
    "content": "[package]\nname = \"check-docs\"\nversion = { workspace = true }\nauthors = { workspace = true }\nedition = { workspace = true }\nhomepage = { workspace = true }\nlicense = { workspace = true }\npublish = false\nrepository = { workspace = true }\nrust-version = { workspace = true }\n\n[dependencies]\nanyhow = \"1.0.75\"\nitertools = { workspace = true }\nregex = { workspace = true }\n"
  },
  {
    "path": "scripts/check-docs/src/lib.rs",
    "content": "use std::{\n    collections::HashSet,\n    path::{Path, PathBuf},\n};\n\nuse anyhow::{Error, anyhow, bail};\nuse itertools::{Itertools, chain};\nuse regex::Regex;\n\npub fn report_errors(error_type: &str, errors: &[Error]) {\n    if !errors.is_empty() {\n        eprintln!(\"\\nInvalid {error_type} detected!\\n\");\n        for error in errors {\n            eprintln!(\"{error}\\n\")\n        }\n    }\n}\n\npub fn report_warnings(warnings: &[Error]) {\n    if !warnings.is_empty() {\n        eprintln!(\"\\nWarnings detected!\\n\");\n        for warning in warnings {\n            eprintln!(\"{warning}\\n\")\n        }\n    }\n}\n\npub fn validate_includes(\n    includes: Vec<Include>,\n    valid_anchors: Vec<Anchor>,\n) -> (Vec<Error>, Vec<Error>) {\n    let (pairs, errors): (Vec<_>, Vec<_>) = includes\n        .into_iter()\n        .filter(|include| !include.anchor_name.is_empty())\n        .map(|include| {\n            let mut maybe_anchor = valid_anchors.iter().find(|anchor| {\n                anchor.file == include.anchor_file && anchor.name == include.anchor_name\n            });\n\n            match maybe_anchor.take() {\n                Some(anchor) => Ok(anchor.clone()),\n                None => Err(anyhow!(\n                    \"No anchor available to satisfy include {include:?}\"\n                )),\n            }\n        })\n        .partition_result();\n\n    let additional_warnings = valid_anchors\n        .iter()\n        .filter(|valid_anchor| {\n            let anchor_used_in_a_pair = pairs.iter().any(|anchor| anchor == *valid_anchor);\n            !anchor_used_in_a_pair\n        })\n        .map(|unused_anchor| anyhow!(\"Anchor unused: {unused_anchor:?}!\"))\n        .collect::<Vec<_>>();\n\n    (errors, additional_warnings)\n}\n\n#[allow(dead_code)]\n#[derive(Debug, Clone)]\npub struct Include {\n    pub anchor_name: String,\n    pub anchor_file: PathBuf,\n    pub include_file: PathBuf,\n    pub line_no: usize,\n}\n\npub fn parse_includes(text_w_includes: String) -> (Vec<Include>, Vec<Error>) {\n    let apply_regex = |regex: Regex| {\n        let (includes, errors): (Vec<_>, Vec<_>) = text_w_includes\n            .lines()\n            .filter_map(|line| regex.captures(line))\n            .map(|capture| {\n                let include_file = PathBuf::from(&capture[1]).canonicalize()?;\n                let line_no = capture[2].parse()?;\n                let anchor_file = PathBuf::from(&capture[3]);\n                let anchor_name = capture.get(4).map_or(\"\", |m| m.as_str()).to_string();\n\n                let the_path = include_file.parent().unwrap().join(anchor_file);\n\n                let anchor_file = the_path.canonicalize().map_err(|err| {\n                    anyhow!(\n                        \"{the_path:?} when canonicalized gives error {err:?}\\ninclude_file: {:?}\",\n                        include_file\n                    )\n                })?;\n\n                Ok(Include {\n                    anchor_name,\n                    anchor_file,\n                    include_file,\n                    line_no,\n                })\n            })\n            .partition_result();\n        (includes, errors)\n    };\n\n    apply_regex(\n        Regex::new(r\"^(\\S+):(\\d+):\\s*\\{\\{\\s*#include\\s*(\\S+?)\\s*(?::\\s*(\\S+)\\s*)?\\}\\}\")\n            .expect(\"could not construct regex\"),\n    )\n}\n\npub fn filter_valid_anchors(starts: Vec<Anchor>, ends: Vec<Anchor>) -> (Vec<Anchor>, Vec<Error>) {\n    let find_anchor_end_by_name = |anchor_name: &str, file: &Path| {\n        ends.iter()\n            .filter(|el| el.name == *anchor_name && el.file == file)\n            .collect::<Vec<_>>()\n    };\n\n    let (pairs, errors):(Vec<_>, Vec<_>) = starts.into_iter().map(|start| {\n        let matches_by_name = find_anchor_end_by_name(&start.name, &start.file);\n\n        let (begin, end) = match matches_by_name.as_slice() {\n            [single_match] => Ok((start, (*single_match).clone())),\n            [] => Err(anyhow!(\"Couldn't find a matching end anchor for {start:?}\")),\n            multiple_ends => Err(anyhow!(\"Found too many matching anchor ends for anchor: {start:?}. The matching ends are: {multiple_ends:?}\")),\n        }?;\n\n        match check_validity_of_anchor_pair(&begin, &end) {\n            None => Ok((begin, end)),\n            Some(err) => {\n                let err_msg = err.to_string();\n                Err(anyhow!(\"{err_msg}\"))\n            }\n        }\n    }).partition_result();\n\n    let additional_errors = filter_unused_ends(&ends, &pairs)\n        .into_iter()\n        .map(|unused_end| anyhow!(\"Missing anchor start for {unused_end:?}\"))\n        .collect::<Vec<_>>();\n\n    let start_only = pairs.into_iter().map(|(begin, _)| begin).collect();\n\n    (start_only, chain!(errors, additional_errors).collect())\n}\n\npub fn filter_unused_ends<'a>(ends: &'a [Anchor], pairs: &[(Anchor, Anchor)]) -> Vec<&'a Anchor> {\n    ends.iter()\n        .filter(|end| {\n            let end_used_in_pairs = pairs.iter().any(|(_, used_end)| *end == used_end);\n            !end_used_in_pairs\n        })\n        .collect()\n}\n\npub fn check_validity_of_anchor_pair(begin: &Anchor, end: &Anchor) -> Option<anyhow::Error> {\n    if begin.line_no > end.line_no {\n        Some(anyhow!(\n            \"The end of the anchor appears before the beginning. End anchor: {end:?}. Begin anchor: {begin:?}\"\n        ))\n    } else {\n        None\n    }\n}\n\n#[derive(Debug, Clone, Hash, Eq, PartialEq)]\npub struct Anchor {\n    pub line_no: usize,\n    pub name: String,\n    pub file: PathBuf,\n}\n\npub fn extract_starts_and_ends(\n    text_w_anchors: &str,\n) -> anyhow::Result<(Vec<Anchor>, Vec<Anchor>), Error> {\n    let apply_regex = |regex: Regex| {\n        text_w_anchors\n            .lines()\n            .filter_map(|line| regex.captures(line))\n            .map(|capture| {\n                let file = PathBuf::from(&capture[1]).canonicalize()?;\n                let line_no = &capture[2];\n                let anchor_name = &capture[3];\n\n                Ok(Anchor {\n                    line_no: line_no.parse()?,\n                    name: anchor_name.to_string(),\n                    file,\n                })\n            })\n            .collect::<Result<Vec<_>, Error>>()\n    };\n\n    let begins = apply_regex(Regex::new(\n        r\"^(.+):(\\d+):\\s*(?:/{2,}|/\\*)\\s*ANCHOR\\s*:\\s*([\\w_-]+)\\s*(?:\\*/)?\",\n    )?)?;\n    let ends = apply_regex(Regex::new(\n        r\"^(.+):(\\d+):\\s*(?:/{2,}|/\\*)\\s*ANCHOR_END\\s*:\\s*([\\w_-]+)\\s*(?:\\*/)?\",\n    )?)?;\n\n    Ok((begins, ends))\n}\n\npub fn parse_md_files(text_w_files: String, path: &str) -> HashSet<PathBuf> {\n    let regex = Regex::new(r\"\\((.*\\.md)\\)\").expect(\"could not construct regex\");\n\n    text_w_files\n        .lines()\n        .filter_map(|line| regex.captures(line))\n        .map(|capture| {\n            let path = PathBuf::from(path).join(&capture[1]);\n            path.canonicalize()\n                .unwrap_or_else(|e| panic!(\"could not canonicalize md path: {e} {path:?}\"))\n        })\n        .collect()\n}\n\npub fn validate_md_files(\n    md_files_summary: HashSet<PathBuf>,\n    md_files_in_src: String,\n) -> Vec<Error> {\n    md_files_in_src\n        .lines()\n        .filter_map(|file| {\n            let file = PathBuf::from(file)\n                .canonicalize()\n                .expect(\"could not canonicalize md path\");\n\n            (!md_files_summary.contains(&file))\n                .then(|| anyhow!(\"file `{}` not in SUMMARY.md\", file.to_str().unwrap()))\n        })\n        .collect()\n}\n\npub fn search_for_pattern(pattern: &str, location: &str) -> anyhow::Result<String> {\n    let grep_project = std::process::Command::new(\"grep\")\n        .arg(\"-H\") // print filename\n        .arg(\"-n\") // print line-number\n        .arg(\"-r\") // search recursively\n        .arg(\"--binary-files=without-match\")\n        .arg(\"--exclude-dir=check-docs\")\n        .arg(pattern)\n        .arg(location)\n        .output()\n        .expect(\"failed grep command\");\n\n    if !grep_project.status.success() {\n        bail!(\"Failed running `grep` command for pattern '{}'\", pattern);\n    }\n\n    Ok(String::from_utf8(grep_project.stdout)?)\n}\n\npub fn find_files(pattern: &str, location: &str, exclude: &str) -> anyhow::Result<String> {\n    let find = std::process::Command::new(\"find\")\n        .args([\n            location, \"-type\", \"f\", \"-name\", pattern, \"!\", \"-name\", exclude,\n        ])\n        .output()\n        .expect(\"Program `find` not in PATH\");\n\n    if !find.status.success() {\n        bail!(\"Failed running `find` command for pattern {}\", pattern);\n    }\n\n    Ok(String::from_utf8(find.stdout)?)\n}\n"
  },
  {
    "path": "scripts/check-docs/src/main.rs",
    "content": "use anyhow::{Error, bail};\nuse check_docs::{\n    extract_starts_and_ends, filter_valid_anchors, find_files, parse_includes, parse_md_files,\n    report_errors, search_for_pattern, validate_includes, validate_md_files,\n};\n\nfn main() -> anyhow::Result<(), Error> {\n    let text_w_anchors = search_for_pattern(\"ANCHOR\", \".\")?;\n    let (starts, ends) = extract_starts_and_ends(&text_w_anchors)?;\n    let (valid_anchors, anchor_errors) = filter_valid_anchors(starts, ends);\n\n    let text_mentioning_include = search_for_pattern(\"{{#include\", \".\")?;\n    let (includes, include_path_errors) = parse_includes(text_mentioning_include);\n    let (include_errors, additional_warnings) = validate_includes(includes, valid_anchors);\n\n    let text_with_md_files = search_for_pattern(\".md\", \"./docs/src/SUMMARY.md\")?;\n    let md_files_in_summary = parse_md_files(text_with_md_files, \"./docs/src/\");\n    let md_files_in_src = find_files(\"*.md\", \"./docs/src/\", \"SUMMARY.md\")?;\n    let md_files_errors = validate_md_files(md_files_in_summary, md_files_in_src);\n\n    report_errors(\"warning\", &additional_warnings);\n    report_errors(\"include paths\", &include_path_errors);\n    report_errors(\"anchors\", &anchor_errors);\n    report_errors(\"includes\", &include_errors);\n    report_errors(\"md files\", &md_files_errors);\n\n    if !anchor_errors.is_empty()\n        || !include_errors.is_empty()\n        || !include_path_errors.is_empty()\n        || !additional_warnings.is_empty()\n        || !md_files_errors.is_empty()\n    {\n        bail!(\"Finished with errors\");\n    }\n\n    Ok(())\n}\n"
  },
  {
    "path": "scripts/check-docs/tests/harness.rs",
    "content": "use anyhow::Error;\nuse check_docs::{\n    Anchor, Include, extract_starts_and_ends, filter_valid_anchors, find_files, parse_includes,\n    parse_md_files, search_for_pattern, validate_includes, validate_md_files,\n};\n\nenum TestEnum {\n    Anchor(Vec<Anchor>),\n    Include(Vec<Include>),\n    Errors(Vec<Error>),\n}\n\nfn contains_any(vec: &TestEnum, str: &str) -> bool {\n    match vec {\n        TestEnum::Anchor(anchor_vec) => anchor_vec.iter().any(|anchor| anchor.name == str),\n        TestEnum::Include(include_vec) => {\n            include_vec.iter().any(|include| include.anchor_name == str)\n        }\n        TestEnum::Errors(err_vec) => err_vec.iter().any(|err| err.to_string().contains(str)),\n    }\n}\n\n#[test]\nfn test_anchors() -> anyhow::Result<()> {\n    let test_data = search_for_pattern(\"ANCHOR\", \".\")?;\n\n    let (starts, ends) = extract_starts_and_ends(&test_data)?;\n    let (valid_anchors, anchor_errors) = filter_valid_anchors(starts, ends);\n\n    let valid_vec = TestEnum::Anchor(valid_anchors.clone());\n    let anchor_err_vec = TestEnum::Errors(anchor_errors);\n\n    assert!(contains_any(&valid_vec, \"test_anchor_line_comment\"));\n    assert!(contains_any(&valid_vec, \"test_anchor_block_comment\"));\n    assert!(contains_any(&valid_vec, \"test_with_more_forward_slashes\"));\n    assert!(!contains_any(&valid_vec, \"no_anchor_with_this_name\"));\n\n    assert!(contains_any(\n        &anchor_err_vec,\n        \"Missing anchor start for Anchor { line_no: 10, name: \\\"test_no_anchor_beginning\\\"\"\n    ));\n    assert!(contains_any(\n        &anchor_err_vec,\n        \"Couldn't find a matching end anchor for Anchor { line_no: 12, name: \\\"test_no_anchor_end\\\"\"\n    ));\n    assert!(contains_any(\n        &anchor_err_vec,\n        \"The end of the anchor appears before the beginning. End anchor: Anchor { line_no: 14, name: \\\"test_end_before_beginning\\\"\"\n    ));\n\n    assert!(contains_any(\n        &anchor_err_vec,\n        \"Found too many matching anchor ends for anchor: Anchor { line_no: 17, name: \\\"test_same_name_multiple_time\\\"\"\n    ));\n    assert!(contains_any(\n        &anchor_err_vec,\n        \"Found too many matching anchor ends for anchor: Anchor { line_no: 20, name: \\\"test_same_name_multiple_time\\\"\"\n    ));\n    // Caused by too many matching anchors\n    assert!(contains_any(\n        &anchor_err_vec,\n        \"Missing anchor start for Anchor { line_no: 18, name: \\\"test_same_name_multiple_time\\\"\"\n    ));\n    assert!(contains_any(\n        &anchor_err_vec,\n        \"Missing anchor start for Anchor { line_no: 21, name: \\\"test_same_name_multiple_time\\\"\"\n    ));\n\n    let text_mentioning_include = search_for_pattern(\"{{#include\", \".\")?;\n\n    let (includes, include_path_errors) = parse_includes(text_mentioning_include);\n\n    let includes_vec = TestEnum::Include(includes.clone());\n\n    assert!(contains_any(&includes_vec, \"test_anchor_line_comment\"));\n    assert!(contains_any(&includes_vec, \"test_anchor_block_comment\"));\n    assert!(contains_any(\n        &includes_vec,\n        \"test_with_more_forward_slashes\"\n    ));\n    assert!(contains_any(&includes_vec, \"\")); //Check the file include without anchor\n\n    let include_path_errors = TestEnum::Errors(include_path_errors);\n\n    assert!(contains_any(\n        &include_path_errors,\n        \"test_anchor_data2.rs\\\" when canonicalized gives error Os { code: 2, kind: NotFound\"\n    ));\n\n    assert!(contains_any(\n        &include_path_errors,\n        \"test_anchor_data3.rs\\\" when canonicalized gives error Os { code: 2, kind: NotFound\"\n    ));\n\n    let (include_errors, _) = validate_includes(includes, valid_anchors);\n\n    let include_err_vec = TestEnum::Errors(include_errors);\n\n    assert!(contains_any(\n        &include_err_vec,\n        \"No anchor available to satisfy include Include { anchor_name: \\\"no_existing_anchor\\\"\"\n    ));\n\n    Ok(())\n}\n\n#[test]\nfn test_unused_md() -> anyhow::Result<()> {\n    let text_with_md_files = search_for_pattern(\".md\", \"./tests/test_data/docs/src/SUMMARY.md\")?;\n    let md_files_in_summary = parse_md_files(text_with_md_files, \"./tests/test_data/docs/src/\");\n    let md_files_in_src = find_files(\"*.md\", \"./tests/test_data/docs/src/\", \"SUMMARY.md\")?;\n    let md_files_errors = validate_md_files(md_files_in_summary, md_files_in_src);\n\n    let error_msg = md_files_errors.first().unwrap().to_string();\n\n    assert!(error_msg.contains(\"test-not-there.md` not in SUMMARY.md\"));\n\n    Ok(())\n}\n"
  },
  {
    "path": "scripts/check-docs/tests/test_data/docs/src/SUMMARY.md",
    "content": "- [Test](./test.md)\n"
  },
  {
    "path": "scripts/check-docs/tests/test_data/docs/src/test-not-there.md",
    "content": ""
  },
  {
    "path": "scripts/check-docs/tests/test_data/docs/src/test.md",
    "content": ""
  },
  {
    "path": "scripts/check-docs/tests/test_data/test_anchor_data.rs",
    "content": "// ANCHOR: test_anchor_line_comment\n///// ANCHOR_END: test_anchor_line_comment\n\n/* ANCHOR: test_anchor_block_comment */\n/* ANCHOR_END: test_anchor_block_comment */\n\n// ANCHOR: test_with_more_forward_slashes\n///// ANCHOR_END: test_with_more_forward_slashes\n\n// ANCHOR_END: test_no_anchor_beginning\n\n// ANCHOR: test_no_anchor_end\n\n// ANCHOR_END: test_end_before_beginning\n// ANCHOR: test_end_before_beginning\n\n// ANCHOR: test_same_name_multiple_time\n// ANCHOR_END: test_same_name_multiple_time\n\n// ANCHOR: test_same_name_multiple_time\n// ANCHOR_END: test_same_name_multiple_time\n"
  },
  {
    "path": "scripts/check-docs/tests/test_data/test_include_data.md",
    "content": "\n```rust,ignore\n{{#include ./test_anchor_data.rs:test_anchor_line_comment}}\n```\n\n```rust,ignore\n{{#include ./test_anchor_data.rs:test_anchor_block_comment}}\n```\n\n```rust,ignore\n{{#include ./test_anchor_data.rs:test_with_more_forward_slashes}}\n```\n\n```rust,ignore\n{{#include ./test_anchor_data.rs:no_existing_anchor}}\n```\n\nInclude file with correct path\n\n```rust,ignore\n{{#include ./test_anchor_data.rs}}\n```\n\nInclude file with wrong path\n\n```rust,ignore\n{{#include ./test_anchor_data2.rs}}\n```\n\nAnother include file with wrong path\n\n```rust,ignore\n{{#include ./test_anchor_data3.rs}}\n```\n"
  },
  {
    "path": "scripts/fuel-core-version/Cargo.toml",
    "content": "[package]\nname = \"fuel-core-version\"\nversion = { workspace = true }\nauthors = { workspace = true }\nedition = { workspace = true }\nhomepage = { workspace = true }\nlicense = { workspace = true }\npublish = false\nrepository = { workspace = true }\nrust-version = { workspace = true }\n\n[dependencies]\nclap = { version = \"4.5.3\", features = [\"derive\"] }\ncolor-eyre = \"0.6.2\"\nfuels-accounts = { workspace = true, features = [\"std\"] }\nsemver = { workspace = true }\ntoml = { workspace = true, features = [\"parse\"] }\n"
  },
  {
    "path": "scripts/fuel-core-version/src/main.rs",
    "content": "use std::{\n    fs,\n    path::{Path, PathBuf},\n};\n\nuse clap::{Parser, Subcommand};\nuse color_eyre::{\n    Result,\n    eyre::{ContextCompat, OptionExt, bail},\n};\nuse fuels_accounts::provider::SUPPORTED_FUEL_CORE_VERSION;\nuse semver::Version;\nuse toml::Value;\n\nfn write_version_to_file(version: Version, version_file_path: impl AsRef<Path>) -> Result<()> {\n    let Version {\n        major,\n        minor,\n        patch,\n        ..\n    } = version;\n    let text = format!(\"Version::new({major}, {minor}, {patch})\");\n    fs::write(version_file_path, text.as_bytes())?;\n    Ok(())\n}\n\nfn get_version_file_path(\n    manifest_path: impl AsRef<Path>,\n) -> Result<PathBuf, color_eyre::eyre::Error> {\n    Ok(manifest_path\n        .as_ref()\n        .parent()\n        .wrap_err(\"Invalid manifest path\")?\n        .join(\"scripts/fuel-core-version/version.rs\"))\n}\n\nfn verify_version_from_file(version: Version) -> Result<()> {\n    if version != SUPPORTED_FUEL_CORE_VERSION {\n        bail!(\n            \"fuel_core version in version.rs ({}) doesn't match one in Cargo.toml ({})\",\n            SUPPORTED_FUEL_CORE_VERSION,\n            version\n        );\n    }\n    println!(\n        \"fuel_core versions in versions.rs and Cargo.toml match ({})\",\n        version\n    );\n    Ok(())\n}\n\n#[derive(Debug, Parser)]\nstruct App {\n    #[clap(subcommand)]\n    command: Command,\n    #[clap(long)]\n    manifest_path: PathBuf,\n}\n\n#[derive(Debug, Subcommand)]\nenum Command {\n    Write,\n    Verify,\n}\n\nfn main() -> Result<()> {\n    let App {\n        command,\n        manifest_path,\n    } = App::parse();\n    let version = read_fuel_core_version(&manifest_path)?;\n    let version_file_path = get_version_file_path(&manifest_path)?;\n    match command {\n        Command::Write => write_version_to_file(version, version_file_path)?,\n        Command::Verify => verify_version_from_file(version)?,\n    }\n    Ok(())\n}\n\npub fn read_fuel_core_version(path: impl AsRef<Path>) -> color_eyre::Result<Version> {\n    let cargo_toml: Value = fs::read_to_string(path.as_ref())?.parse::<Value>()?;\n\n    let str_version =\n        find_dependency_version(&cargo_toml).ok_or_eyre(\"could not find fuel-core version\")?;\n\n    Ok(str_version.parse()?)\n}\n\nfn find_dependency_version(toml: &Value) -> Option<String> {\n    match toml\n        .get(\"workspace\")?\n        .get(\"dependencies\")?\n        .get(\"fuel-core\")?\n    {\n        Value::String(version) => Some(version.clone()),\n        Value::Table(table) => table\n            .get(\"version\")\n            .and_then(|v| v.as_str())\n            .map(String::from),\n        _ => None,\n    }\n}\n"
  },
  {
    "path": "scripts/versions-replacer/Cargo.toml",
    "content": "[package]\nname = \"versions-replacer\"\nversion = { workspace = true }\nauthors = { workspace = true }\nedition = { workspace = true }\nhomepage = { workspace = true }\nlicense = { workspace = true }\npublish = false\nrepository = { workspace = true }\nrust-version = { workspace = true }\n\n[dependencies]\nargh = \"0.1.12\"\ncargo_metadata = \"0.18.1\"\ncolor-eyre = \"0.6.2\"\nonce_cell = \"1.18.0\"\nregex = { workspace = true }\nserde = { workspace = true, features = [\"derive\"] }\nwalkdir = \"2.4.0\"\n"
  },
  {
    "path": "scripts/versions-replacer/src/lib.rs",
    "content": "pub mod metadata;\npub mod replace;\n"
  },
  {
    "path": "scripts/versions-replacer/src/main.rs",
    "content": "use std::path::PathBuf;\n\nuse argh::FromArgs;\nuse color_eyre::{\n    Result,\n    eyre::{Context, eyre},\n};\nuse regex::Regex;\nuse versions_replacer::{\n    metadata::collect_versions_from_cargo_toml, replace::replace_versions_in_file,\n};\nuse walkdir::WalkDir;\n\n#[derive(FromArgs)]\n/// Replace variables like '{{{{versions.fuels}}}}' with correct versions from Cargo.toml.\n/// Uses versions from '[workspace.members]' and '[workspace.metadata.versions-replacer.external-versions]'.\nstruct VersionsReplacer {\n    /// path to directory with files containing variables\n    #[argh(positional)]\n    path: PathBuf,\n    /// path to Cargo.toml with versions\n    #[argh(option)]\n    manifest_path: PathBuf,\n    /// regex to filter filenames (example: \"\\.md$\")\n    #[argh(option)]\n    filename_regex: Option<Regex>,\n}\n\nfn main() -> Result<()> {\n    let args: VersionsReplacer = argh::from_env();\n    let versions = collect_versions_from_cargo_toml(&args.manifest_path)?;\n\n    let mut total_replacements: Vec<usize> = Vec::new();\n\n    for entry in WalkDir::new(&args.path) {\n        let entry = entry.wrap_err(\"failed to get directory entry\")?;\n\n        if entry.path().is_file() {\n            if let Some(filename_regex) = &args.filename_regex {\n                let file_name = entry\n                    .path()\n                    .file_name()\n                    .ok_or_else(|| eyre!(\"{:?} has an invalid file name\", entry.path()))?\n                    .to_str()\n                    .ok_or_else(|| eyre!(\"filename is not valid UTF-8\"))?;\n                if !filename_regex.is_match(file_name) {\n                    continue;\n                }\n            }\n\n            let replacement_count = replace_versions_in_file(entry.path(), &versions)\n                .wrap_err_with(|| format!(\"failed to replace versions in {:?}\", entry.path()))?;\n            if replacement_count > 0 {\n                total_replacements.push(replacement_count);\n            }\n        }\n    }\n\n    println!(\n        \"replaced {} variables across {} files\",\n        total_replacements.iter().sum::<usize>(),\n        total_replacements.len()\n    );\n    Ok(())\n}\n"
  },
  {
    "path": "scripts/versions-replacer/src/metadata.rs",
    "content": "use std::{collections::HashMap, path::Path};\n\nuse cargo_metadata::MetadataCommand;\nuse color_eyre::{Result, eyre::Context};\nuse serde::Deserialize;\n\n#[derive(Deserialize)]\n#[serde(rename_all = \"kebab-case\")]\npub struct WorkspaceMetadata {\n    pub versions_replacer: VersionsReplacerMetadata,\n}\n\n#[derive(Deserialize)]\n#[serde(rename_all = \"kebab-case\")]\npub struct VersionsReplacerMetadata {\n    pub external_versions: HashMap<String, String>,\n}\n\npub fn collect_versions_from_cargo_toml(\n    manifest_path: impl AsRef<Path>,\n) -> Result<HashMap<String, String>> {\n    let metadata = MetadataCommand::new()\n        .manifest_path(manifest_path.as_ref())\n        .exec()\n        .wrap_err(\"failed to execute 'cargo metadata'\")?;\n    let version_map = metadata\n        .packages\n        .iter()\n        .map(|package| (package.name.clone(), package.version.to_string()))\n        .collect::<HashMap<_, _>>();\n    Ok(version_map)\n}\n"
  },
  {
    "path": "scripts/versions-replacer/src/replace.rs",
    "content": "use std::{borrow::Cow, collections::HashMap, fs, path::Path};\n\nuse color_eyre::{Result, eyre::Context};\nuse once_cell::sync::Lazy;\nuse regex::{Captures, Regex};\n\npub static VERSIONS_REGEX: Lazy<Regex> =\n    Lazy::new(|| Regex::new(r\"\\{\\{versions\\.([\\w_-]+)\\}\\}\").unwrap());\n\npub fn replace_versions_in_file(\n    path: impl AsRef<Path>,\n    versions: &HashMap<String, String>,\n) -> Result<usize> {\n    let path = path.as_ref();\n    let contents =\n        fs::read_to_string(path).wrap_err_with(|| format!(\"failed to read {:?}\", path))?;\n    let (replaced_contents, replacement_count) = replace_versions_in_string(&contents, versions);\n    if replacement_count > 0 {\n        fs::write(path, replaced_contents.as_bytes())\n            .wrap_err_with(|| format!(\"failed to write back to {:?}\", path))?;\n    }\n    Ok(replacement_count)\n}\n\npub fn replace_versions_in_string<'a>(\n    s: &'a str,\n    versions: &HashMap<String, String>,\n) -> (Cow<'a, str>, usize) {\n    let mut replacement_count = 0;\n    let replaced_s = VERSIONS_REGEX.replace_all(s, |caps: &Captures| {\n        if let Some(version) = versions.get(&caps[1]) {\n            replacement_count += 1;\n            version.clone()\n        } else {\n            // leave unchanged\n            caps[0].to_string()\n        }\n    });\n    (replaced_s, replacement_count)\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    fn test_versions() -> HashMap<String, String> {\n        [(\"fuels\", \"0.47.0\"), (\"fuel-types\", \"0.35.3\")]\n            .map(|(name, version)| (name.to_string(), version.to_string()))\n            .into()\n    }\n\n    #[test]\n    fn test_valid_replacements() {\n        let s = \"docs.rs/fuels/{{versions.fuels}}/fuels\\ndocs.rs/fuel-types/{{versions.fuel-types}}/fuel-types\";\n        let versions = test_versions();\n        let (replaced, count) = replace_versions_in_string(s, &versions);\n        assert_eq!(\n            replaced,\n            format!(\n                \"docs.rs/fuels/{}/fuels\\ndocs.rs/fuel-types/{}/fuel-types\",\n                versions[\"fuels\"], versions[\"fuel-types\"]\n            )\n        );\n        assert_eq!(count, 2);\n    }\n\n    #[test]\n    fn test_invalid_replacement() {\n        let s = \"```rust,ignore\n{{#include ../../../examples/contracts/src/lib.rs:deployed_contracts}}\n```\";\n        let versions = test_versions();\n        let (replaced, count) = replace_versions_in_string(s, &versions);\n        assert_eq!(replaced, s);\n        assert_eq!(count, 0);\n    }\n\n    #[test]\n    fn test_invalid_package_name() {\n        let s = \"docs.rs/fuels-wrong-name/{{versions.fuels-wrong-name}}/fuels-wrong-name\";\n        let versions = test_versions();\n        let (replaced, count) = replace_versions_in_string(s, &versions);\n        assert_eq!(replaced, s);\n        assert_eq!(count, 0);\n    }\n}\n"
  },
  {
    "path": "wasm-tests/.cargo/config.toml",
    "content": "[build]\ntarget = \"wasm32-unknown-unknown\"\n\n[target.wasm32-unknown-unknown]\nrunner = \"wasm-bindgen-test-runner\""
  },
  {
    "path": "wasm-tests/Cargo.toml",
    "content": "[package]\nname = \"wasm-tests\"\nversion = { workspace = true }\nauthors = { workspace = true }\nedition = { workspace = true }\nhomepage = { workspace = true }\nlicense = { workspace = true }\npublish = false\nrepository = { workspace = true }\nrust-version = { workspace = true }\n\n[lib]\ncrate-type = ['cdylib']\n\n[dev-dependencies]\nfuels = { workspace = true }\nfuels-core = { workspace = true }\ngetrandom = { version = \"0.2.11\", features = [\"js\"] }\nhex = { workspace = true }\nwasm-bindgen-test = \"0.3.39\"\n"
  },
  {
    "path": "wasm-tests/src/lib.rs",
    "content": "extern crate alloc;\n\n#[cfg(all(test, target_arch = \"wasm32\"))]\nmod tests {\n    use std::{default::Default, str::FromStr};\n\n    use fuels::{\n        accounts::predicate::Predicate,\n        core::{codec::ABIEncoder, traits::Tokenizable},\n        macros::wasm_abigen,\n        programs::debug::ScriptType,\n        types::{AssetId, bech32::Bech32Address, errors::Result},\n    };\n    use fuels_core::codec::abi_formatter::ABIFormatter;\n    use wasm_bindgen_test::wasm_bindgen_test;\n\n    #[wasm_bindgen_test]\n    fn decoding_and_encoding() -> Result<()> {\n        wasm_abigen!(Contract(\n            name = \"no_name\",\n            // abi generated with: \"e2e/sway/abi/wasm_contract\"\n            abi = r#\"\n            {\n              \"programType\": \"contract\",\n              \"specVersion\": \"1\",\n              \"encodingVersion\": \"1\",\n              \"concreteTypes\": [\n                {\n                  \"type\": \"()\",\n                  \"concreteTypeId\": \"2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d\"\n                },\n                {\n                  \"type\": \"enum SomeEnum<struct SomeStruct>\",\n                  \"concreteTypeId\": \"744ffecb34b691a157f3f4b4657ea215fd23e3cc79fd7a3b7f15431751b46134\",\n                  \"metadataTypeId\": 1,\n                  \"typeArguments\": [\n                    \"c672b07b5808bcc04715d73ca6d42eaabd332266144c1017c20833ef05a4a484\"\n                  ]\n                },\n                {\n                  \"type\": \"struct SomeStruct\",\n                  \"concreteTypeId\": \"c672b07b5808bcc04715d73ca6d42eaabd332266144c1017c20833ef05a4a484\",\n                  \"metadataTypeId\": 3\n                }\n              ],\n              \"metadataTypes\": [\n                {\n                  \"type\": \"bool\",\n                  \"metadataTypeId\": 0\n                },\n                {\n                  \"type\": \"enum SomeEnum\",\n                  \"metadataTypeId\": 1,\n                  \"components\": [\n                    {\n                      \"name\": \"V1\",\n                      \"typeId\": \"2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d\"\n                    },\n                    {\n                      \"name\": \"V2\",\n                      \"typeId\": 2\n                    }\n                  ],\n                  \"typeParameters\": [\n                    2\n                  ]\n                },\n                {\n                  \"type\": \"generic T\",\n                  \"metadataTypeId\": 2\n                },\n                {\n                  \"type\": \"struct SomeStruct\",\n                  \"metadataTypeId\": 3,\n                  \"components\": [\n                    {\n                      \"name\": \"a\",\n                      \"typeId\": 4\n                    },\n                    {\n                      \"name\": \"b\",\n                      \"typeId\": 0\n                    }\n                  ]\n                },\n                {\n                  \"type\": \"u32\",\n                  \"metadataTypeId\": 4\n                }\n              ],\n              \"functions\": [\n                {\n                  \"inputs\": [\n                    {\n                      \"name\": \"_arg\",\n                      \"concreteTypeId\": \"744ffecb34b691a157f3f4b4657ea215fd23e3cc79fd7a3b7f15431751b46134\"\n                    }\n                  ],\n                  \"name\": \"test_function\",\n                  \"output\": \"2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d\"\n                }\n              ],\n              \"loggedTypes\": [],\n              \"messagesTypes\": [],\n              \"configurables\": []\n         }\n        \"#\n        ));\n\n        let original = SomeEnum::V2(SomeStruct { a: 123, b: false });\n\n        let bytes = ABIEncoder::default().encode(&[original.clone().into_token()])?;\n\n        let expected_bytes = [\n            0, 0, 0, 0, 0, 0, 0, 1, // enum discriminant\n            0, 0, 0, 123, 0, // SomeStruct\n        ]\n        .to_vec();\n\n        assert_eq!(expected_bytes, bytes);\n\n        let reconstructed = bytes.try_into().unwrap();\n\n        assert_eq!(original, reconstructed);\n\n        Ok(())\n    }\n\n    #[wasm_bindgen_test]\n    fn predicate_abigen() -> Result<()> {\n        wasm_abigen!(Predicate(\n            name = \"MyPredicate\",\n            // abi generated with: \"e2e/sway/abi/wasm_predicate\"\n            abi = r#\"\n            {\n              \"programType\": \"predicate\",\n              \"specVersion\": \"1\",\n              \"encodingVersion\": \"1\",\n              \"concreteTypes\": [\n                {\n                  \"type\": \"bool\",\n                  \"concreteTypeId\": \"b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903\"\n                },\n                {\n                  \"type\": \"u64\",\n                  \"concreteTypeId\": \"1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0\"\n                }\n              ],\n              \"metadataTypes\": [],\n              \"functions\": [\n                {\n                  \"inputs\": [\n                    {\n                      \"name\": \"val\",\n                      \"concreteTypeId\": \"1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0\"\n                    }\n                  ],\n                  \"name\": \"main\",\n                  \"output\": \"b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903\",\n                  \"attributes\": null\n                }\n              ],\n              \"loggedTypes\": [],\n              \"messagesTypes\": [],\n              \"configurables\": [\n                {\n                  \"name\": \"U64\",\n                  \"concreteTypeId\": \"1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0\",\n                  \"offset\": 376\n                }\n              ]\n            }\n            \"#\n        ));\n\n        let code = vec![\n            26, 24, 48, 0, 116, 0, 0, 2, 0, 0, 0, 0, 0, 0, 1, 12, 93, 255, 192, 1, 16, 255, 255, 0,\n            145, 0, 0, 8, 8, 235, 24, 0, 8, 228, 0, 8, 8, 224, 64, 0, 32, 248, 51, 0, 88, 251, 224,\n            2, 8, 251, 224, 4, 116, 0, 0, 28, 26, 236, 8, 0, 145, 0, 0, 16, 113, 64, 0, 3, 97, 69,\n            2, 0, 19, 73, 16, 0, 118, 72, 0, 6, 114, 72, 0, 2, 19, 69, 2, 128, 118, 68, 0, 1, 54,\n            0, 0, 0, 97, 65, 2, 74, 116, 0, 0, 1, 97, 65, 2, 12, 95, 237, 0, 1, 8, 67, 176, 8, 26,\n            233, 0, 0, 32, 248, 51, 0, 88, 251, 224, 2, 8, 251, 224, 4, 116, 0, 0, 32, 26, 67, 28,\n            0, 26, 233, 0, 0, 32, 248, 51, 0, 88, 251, 224, 2, 8, 251, 224, 4, 116, 0, 0, 42, 26,\n            67, 28, 0, 36, 64, 0, 0, 149, 0, 0, 15, 15, 8, 0, 0, 26, 236, 8, 0, 145, 0, 0, 16, 26,\n            67, 16, 0, 26, 71, 128, 0, 26, 75, 224, 0, 95, 237, 0, 0, 26, 235, 176, 0, 32, 248, 51,\n            0, 88, 251, 224, 2, 8, 251, 224, 4, 116, 0, 0, 11, 26, 67, 28, 0, 95, 237, 0, 1, 8, 67,\n            176, 8, 114, 76, 0, 8, 4, 69, 4, 192, 26, 244, 0, 0, 146, 0, 0, 16, 26, 249, 32, 0,\n            152, 8, 0, 0, 151, 0, 0, 15, 74, 248, 0, 0, 149, 0, 0, 31, 15, 8, 0, 0, 26, 236, 8, 0,\n            26, 83, 16, 0, 26, 67, 224, 0, 93, 69, 64, 0, 93, 69, 16, 0, 93, 73, 64, 0, 114, 76, 0,\n            8, 16, 73, 36, 192, 95, 81, 32, 0, 26, 245, 16, 0, 26, 249, 0, 0, 152, 8, 0, 0, 151, 0,\n            0, 31, 74, 248, 0, 0, 149, 0, 0, 7, 15, 8, 0, 0, 26, 236, 8, 0, 26, 67, 16, 0, 26, 71,\n            224, 0, 93, 72, 64, 0, 19, 65, 4, 128, 26, 245, 0, 0, 26, 249, 16, 0, 152, 8, 0, 0,\n            151, 0, 0, 7, 74, 248, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128,\n        ];\n        let value = 129;\n\n        let predicate_data = MyPredicateEncoder::default().encode_data(value)?;\n        let configurables = MyPredicateConfigurables::default().with_U64(value)?;\n\n        let predicate: Predicate = Predicate::from_code(code.clone())\n            .with_data(predicate_data)\n            .with_configurables(configurables);\n\n        let mut expected_code = code.clone();\n        *expected_code.last_mut().unwrap() = value as u8;\n\n        assert_eq!(*predicate.code(), expected_code);\n\n        let expected_address = Bech32Address::from_str(\n            \"fuel1c7rzx6ljxdz8egkcfjswffe7w8u06rm4nfvyu4lelyjua7qlcmdss9jkjm\",\n        )?;\n\n        assert_eq!(*predicate.address(), expected_address);\n\n        Ok(())\n    }\n\n    #[wasm_bindgen_test]\n    fn can_decode_a_contract_calling_script() -> Result<()> {\n        let script = hex::decode(\n            \"724028d8724428b05d451000724828b82d41148a724029537244292b5d451000724829332d41148a24040000\",\n        )?;\n        let script_data = hex::decode(\n            \"000000000000000a00000000000000000000000000000000000000000000000000000000000000001e62ecaa5c32f1e51954f46149d5e542472bdba45838199406464af46ab147ed000000000000290800000000000029260000000000000016636865636b5f7374727563745f696e746567726974790000000201000000000000001400000000000000000000000000000000000000000000000000000000000000001e62ecaa5c32f1e51954f46149d5e542472bdba45838199406464af46ab147ed000000000000298300000000000029a20000000000000017695f616d5f63616c6c65645f646966666572656e746c7900000002011e62ecaa5c32f1e51954f46149d5e542472bdba45838199406464af46ab147ed000000000000007b00000000000001c8\",\n        )?;\n\n        let abi = r#\"{\n            \"programType\": \"contract\",\n            \"specVersion\": \"1\",\n            \"encodingVersion\": \"1\",\n            \"concreteTypes\": [\n                {\n                \"type\": \"()\",\n                \"concreteTypeId\": \"2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d\"\n                },\n                {\n                \"type\": \"bool\",\n                \"concreteTypeId\": \"b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903\"\n                },\n                {\n                \"type\": \"struct AllStruct\",\n                \"concreteTypeId\": \"91804f0112892169cddf041007c9f16f95281d45c3f363e544c33dffc8179266\",\n                \"metadataTypeId\": 1\n                },\n                {\n                \"type\": \"struct CallData\",\n                \"concreteTypeId\": \"c1b2644ef8de5c5b7a95aaadf3f5cedd40f42286d459bcd051c3cc35fa1ce5ec\",\n                \"metadataTypeId\": 2\n                },\n                {\n                \"type\": \"struct MemoryAddress\",\n                \"concreteTypeId\": \"0b7b6a791f80f65fe493c3e0d0283bf8206871180c9b696797ff0098ff63b474\",\n                \"metadataTypeId\": 3\n                }\n            ],\n            \"metadataTypes\": [\n                {\n                \"type\": \"b256\",\n                \"metadataTypeId\": 0\n                },\n                {\n                \"type\": \"struct AllStruct\",\n                \"metadataTypeId\": 1,\n                \"components\": [\n                    {\n                    \"name\": \"some_struct\",\n                    \"typeId\": 4\n                    }\n                ]\n                },\n                {\n                \"type\": \"struct CallData\",\n                \"metadataTypeId\": 2,\n                \"components\": [\n                    {\n                    \"name\": \"memory_address\",\n                    \"typeId\": 3\n                    },\n                    {\n                    \"name\": \"num_coins_to_forward\",\n                    \"typeId\": 7\n                    },\n                    {\n                    \"name\": \"asset_id_of_coins_to_forward\",\n                    \"typeId\": 5\n                    },\n                    {\n                    \"name\": \"amount_of_gas_to_forward\",\n                    \"typeId\": 7\n                    }\n                ]\n                },\n                {\n                \"type\": \"struct MemoryAddress\",\n                \"metadataTypeId\": 3,\n                \"components\": [\n                    {\n                    \"name\": \"contract_id\",\n                    \"typeId\": 5\n                    },\n                    {\n                    \"name\": \"function_selector\",\n                    \"typeId\": 7\n                    },\n                    {\n                    \"name\": \"function_data\",\n                    \"typeId\": 7\n                    }\n                ]\n                },\n                {\n                \"type\": \"struct SomeStruct\",\n                \"metadataTypeId\": 4,\n                \"components\": [\n                    {\n                    \"name\": \"field\",\n                    \"typeId\": 6\n                    },\n                    {\n                    \"name\": \"field_2\",\n                    \"typeId\": \"b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903\"\n                    }\n                ]\n                },\n                {\n                \"type\": \"struct std::contract_id::ContractId\",\n                \"metadataTypeId\": 5,\n                \"components\": [\n                    {\n                    \"name\": \"bits\",\n                    \"typeId\": 0\n                    }\n                ]\n                },\n                {\n                \"type\": \"u32\",\n                \"metadataTypeId\": 6\n                },\n                {\n                \"type\": \"u64\",\n                \"metadataTypeId\": 7\n                }\n            ],\n            \"functions\": [\n                {\n                \"inputs\": [\n                    {\n                    \"name\": \"arg\",\n                    \"concreteTypeId\": \"91804f0112892169cddf041007c9f16f95281d45c3f363e544c33dffc8179266\"\n                    }\n                ],\n                \"name\": \"check_struct_integrity\",\n                \"output\": \"b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903\",\n                \"attributes\": [\n                    {\n                    \"name\": \"payable\",\n                    \"arguments\": []\n                    }\n                ]\n                },\n                {\n                \"inputs\": [],\n                \"name\": \"get_struct\",\n                \"output\": \"91804f0112892169cddf041007c9f16f95281d45c3f363e544c33dffc8179266\",\n                \"attributes\": null\n                },\n                {\n                \"inputs\": [\n                    {\n                    \"name\": \"arg1\",\n                    \"concreteTypeId\": \"91804f0112892169cddf041007c9f16f95281d45c3f363e544c33dffc8179266\"\n                    },\n                    {\n                    \"name\": \"arg2\",\n                    \"concreteTypeId\": \"0b7b6a791f80f65fe493c3e0d0283bf8206871180c9b696797ff0098ff63b474\"\n                    }\n                ],\n                \"name\": \"i_am_called_differently\",\n                \"output\": \"2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d\",\n                \"attributes\": [\n                    {\n                    \"name\": \"payable\",\n                    \"arguments\": []\n                    }\n                ]\n                },\n                {\n                \"inputs\": [\n                    {\n                    \"name\": \"call_data\",\n                    \"concreteTypeId\": \"c1b2644ef8de5c5b7a95aaadf3f5cedd40f42286d459bcd051c3cc35fa1ce5ec\"\n                    }\n                ],\n                \"name\": \"nested_struct_with_reserved_keyword_substring\",\n                \"output\": \"c1b2644ef8de5c5b7a95aaadf3f5cedd40f42286d459bcd051c3cc35fa1ce5ec\",\n                \"attributes\": null\n                }\n            ],\n            \"loggedTypes\": [],\n            \"messagesTypes\": [],\n            \"configurables\": []\n        }\"#;\n\n        let decoder = ABIFormatter::from_json_abi(abi)?;\n\n        // when\n        let script_type = ScriptType::detect(&script, &script_data)?;\n\n        // then\n        let ScriptType::ContractCall(call_descriptions) = script_type else {\n            panic!(\"expected a contract call\")\n        };\n\n        assert_eq!(call_descriptions.len(), 2);\n\n        let call_description = &call_descriptions[0];\n\n        let expected_contract_id =\n            \"1e62ecaa5c32f1e51954f46149d5e542472bdba45838199406464af46ab147ed\".parse()?;\n        assert_eq!(call_description.contract_id, expected_contract_id);\n        assert_eq!(call_description.amount, 10);\n        assert_eq!(call_description.asset_id, AssetId::default());\n        assert_eq!(\n            call_description.decode_fn_selector().unwrap(),\n            \"check_struct_integrity\"\n        );\n        assert!(call_description.gas_forwarded.is_none());\n\n        assert_eq!(\n            decoder.decode_fn_args(\n                &call_description.decode_fn_selector().unwrap(),\n                &call_description.encoded_args\n            )?,\n            vec![\"AllStruct { some_struct: SomeStruct { field: 2, field_2: true } }\"]\n        );\n\n        let call_description = &call_descriptions[1];\n\n        assert_eq!(call_description.contract_id, expected_contract_id);\n        assert_eq!(call_description.amount, 20);\n        assert_eq!(call_description.asset_id, AssetId::default());\n        assert_eq!(\n            call_description.decode_fn_selector().unwrap(),\n            \"i_am_called_differently\"\n        );\n        assert!(call_description.gas_forwarded.is_none());\n\n        assert_eq!(\n            decoder.decode_fn_args(\n                &call_description.decode_fn_selector().unwrap(),\n                &call_description.encoded_args\n            )?,\n            vec![\n                \"AllStruct { some_struct: SomeStruct { field: 2, field_2: true } }\",\n                \"MemoryAddress { contract_id: std::contract_id::ContractId { bits: Bits256([30, 98, 236, 170, 92, 50, 241, 229, 25, 84, 244, 97, 73, 213, 229, 66, 71, 43, 219, 164, 88, 56, 25, 148, 6, 70, 74, 244, 106, 177, 71, 237]) }, function_selector: 123, function_data: 456 }\"\n            ]\n        );\n\n        Ok(())\n    }\n}\n"
  }
]