diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml index a547a7b..8661b4d 100644 --- a/.github/actions/setup/action.yml +++ b/.github/actions/setup/action.yml @@ -10,64 +10,74 @@ inputs: cargo-cache-local-key: description: The key to cache local cargo dependencies. Skips local cargo caching if not provided. required: false - clippy: - description: Install Clippy if `true`. Defaults to `false`. - required: false - rustfmt: - description: Install Rustfmt if `true`. Defaults to `false`. + pnpm: + description: Install pnpm if `true`. Defaults to `false`. required: false solana: description: Install Solana if `true`. Defaults to `false`. required: false + toolchain: + description: Rust toolchain to install. Comma-separated string of [`format`, `lint`, `test`]. + required: false runs: using: 'composite' steps: + - name: Set Environment Variables + shell: bash + run: | + source ./vars.env + echo "RUST_TOOLCHAIN_NIGHTLY=$RUST_TOOLCHAIN_NIGHTLY" >> "$GITHUB_ENV" + echo "SOLANA_CLI_VERSION=$SOLANA_CLI_VERSION" >> "$GITHUB_ENV" + - name: Setup pnpm + if: ${{ inputs.pnpm == 'true' }} uses: pnpm/action-setup@v3 - name: Setup Node.js + if: ${{ inputs.pnpm == 'true' }} uses: actions/setup-node@v4 with: node-version: 20 cache: 'pnpm' - name: Install Dependencies + if: ${{ inputs.pnpm == 'true' }} run: pnpm install --frozen-lockfile shell: bash - - name: Set Environment Variables - shell: bash - run: pnpm zx ./scripts/ci/set-env.mjs - - - name: Install Protobuf Compiler (Temporary Workaround for Solana 2.0) - if: ${{ inputs.solana == 'true' || inputs.rustfmt == 'true' || inputs.clippy == 'true' }} - shell: bash - run: | - sudo apt-get update - sudo apt-get install -y protobuf-compiler - - - name: Install Rustfmt - if: ${{ inputs.rustfmt == 'true' }} + - name: Install Rust 'format' Toolchain + if: ${{ contains(inputs.toolchain, 'format') }} uses: dtolnay/rust-toolchain@master with: - toolchain: ${{ env.TOOLCHAIN_FORMAT }} + toolchain: ${{ env.RUST_TOOLCHAIN_NIGHTLY }} components: rustfmt - - name: Install Clippy - if: ${{ inputs.clippy == 'true' }} + - name: Install Rust 'lint' Toolchain + if: ${{ contains(inputs.toolchain, 'lint') }} uses: dtolnay/rust-toolchain@master with: - toolchain: ${{ env.TOOLCHAIN_LINT }} + toolchain: ${{ env.RUST_TOOLCHAIN_NIGHTLY }} components: clippy + - name: Install Rust 'test' Toolchain + if: ${{ contains(inputs.toolchain, 'test') }} + uses: dtolnay/rust-toolchain@master + with: + toolchain: stable + - name: Install Solana if: ${{ inputs.solana == 'true' }} uses: solana-program/actions/install-solana@v1 with: - version: ${{ env.SOLANA_VERSION }} + version: ${{ env.SOLANA_CLI_VERSION }} cache: true + - name: Install 'cargo-hack' + if: ${{ contains(inputs.toolchain, 'lint') }} + shell: bash + run: cargo install cargo-hack + - name: Cache Cargo Dependencies if: ${{ inputs.cargo-cache-key && !inputs.cargo-cache-fallback-key }} uses: actions/cache@v4 diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index ac12c03..179032e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -4,11 +4,10 @@ on: push: branches: [main] pull_request: - branches: [main] jobs: - format_and_lint_programs: - name: Format & Lint Programs + format_and_lint_client_js: + name: Format & Lint Client JS runs-on: ubuntu-latest steps: - name: Git Checkout @@ -17,17 +16,16 @@ jobs: - name: Setup Environment uses: ./.github/actions/setup with: - clippy: true - rustfmt: true + pnpm: true - - name: Format Programs - run: pnpm programs:format + - name: Format Client JS + run: make format-js - - name: Lint Programs - run: pnpm programs:lint + - name: Lint Client JS + run: make lint-js - format_and_lint_client_js: - name: Format & Lint Client JS + format_and_lint_client_rust: + name: Format & Lint Client Rust runs-on: ubuntu-latest steps: - name: Git Checkout @@ -35,15 +33,23 @@ jobs: - name: Setup Environment uses: ./.github/actions/setup + with: + toolchain: format, lint - - name: Format Client JS - run: pnpm clients:js:format + - name: Format + run: make format-clients-rust - - name: Lint Client JS - run: pnpm clients:js:lint + - name: Lint / Clippy + run: make clippy-clients-rust - format_and_lint_client_rust: - name: Format & Lint Client Rust + - name: Lint / Docs + run: make lint-docs-clients-rust + + - name: Lint / Features + run: make lint-features-clients-rust + + format_and_lint_interface: + name: Format & Lint Interface runs-on: ubuntu-latest steps: - name: Git Checkout @@ -52,19 +58,23 @@ jobs: - name: Setup Environment uses: ./.github/actions/setup with: - clippy: true - rustfmt: true + toolchain: format, lint + + - name: Format + run: make format-interface + + - name: Lint / Clippy + run: make clippy-interface - - name: Format Client Rust - run: pnpm clients:rust:format + - name: Lint / Docs + run: make lint-docs-interface - - name: Lint Client Rust - run: pnpm clients:rust:lint + - name: Lint / Features + run: make lint-features-interface - build_programs: - name: Build programs + format_and_lint_program: + name: Format & Lint Program runs-on: ubuntu-latest - needs: format_and_lint_programs steps: - name: Git Checkout uses: actions/checkout@v4 @@ -72,29 +82,39 @@ jobs: - name: Setup Environment uses: ./.github/actions/setup with: - cargo-cache-key: cargo-programs - solana: true + toolchain: format, lint - - name: Build Programs - run: pnpm programs:build + - name: Format + run: make format-program - - name: Upload Program Builds - uses: actions/upload-artifact@v4 - with: - name: program-builds - path: ./target/deploy/*.so - if-no-files-found: error + - name: Lint / Clippy + run: make clippy-program + + - name: Lint / Docs + run: make lint-docs-program - - name: Save Program Builds For Client Jobs - uses: actions/cache/save@v4 + - name: Lint / Features + run: make lint-features-program + + test_interface: + name: Test Interface + runs-on: ubuntu-latest + steps: + - name: Git Checkout + uses: actions/checkout@v4 + + - name: Setup Environment + uses: ./.github/actions/setup with: - path: ./**/*.so - key: ${{ runner.os }}-builds-${{ github.sha }} + toolchain: test + cargo-cache-key: cargo-interface - test_programs: - name: Test Programs + - name: Test Interface + run: make test-interface + + build_program: + name: Build Program runs-on: ubuntu-latest - needs: format_and_lint_programs steps: - name: Git Checkout uses: actions/checkout@v4 @@ -102,17 +122,33 @@ jobs: - name: Setup Environment uses: ./.github/actions/setup with: - cargo-cache-key: cargo-program-tests - cargo-cache-fallback-key: cargo-programs + cargo-cache-key: cargo-program solana: true - - name: Test Programs - run: pnpm programs:test + - name: Build Program + run: make build-program + + test_program: + name: Test Program + runs-on: ubuntu-latest + steps: + - name: Git Checkout + uses: actions/checkout@v4 + + - name: Setup Environment + uses: ./.github/actions/setup + with: + toolchain: test + cargo-cache-key: cargo-program + solana: true + - name: Test Program + run: make test-program + bench_program_compute_units: name: Benchmark Program Compute Units runs-on: ubuntu-latest - needs: build_programs # Cargo Bench won't build the SBPF binary... + needs: build_program # Cargo Bench won't build the SBPF binary... steps: - name: Git Checkout uses: actions/checkout@v4 @@ -121,7 +157,7 @@ jobs: uses: ./.github/actions/setup with: cargo-cache-key: cargo-program-benches - cargo-cache-fallback-key: cargo-programs + cargo-cache-fallback-key: cargo-program solana: true - name: Restore Program Builds @@ -131,7 +167,7 @@ jobs: key: ${{ runner.os }}-builds-${{ github.sha }} - name: Benchmark Compute Units - run: pnpm programs:bench + run: make bench-program-compute-units - name: Check Working Directory run: | @@ -144,7 +180,7 @@ jobs: conformance: name: Conformance Test runs-on: ubuntu-latest - needs: build_programs + needs: build_program steps: - name: Git Checkout uses: actions/checkout@v4 @@ -153,7 +189,7 @@ jobs: uses: ./.github/actions/setup with: cargo-cache-key: cargo-program-conformance - cargo-cache-fallback-key: cargo-programs + cargo-cache-fallback-key: cargo-program solana: true - name: Install System Dependencies @@ -169,37 +205,11 @@ jobs: key: ${{ runner.os }}-builds-${{ github.sha }} - name: Conformance Test - shell: bash - run: pnpm zx ./scripts/ci/conformance.mjs - - ## SKIP: IDL is hand-cranked here for now. - ## - # generate_idls: - # name: Check IDL Generation - # runs-on: ubuntu-latest - # needs: format_and_lint_programs - # steps: - # - name: Git Checkout - # uses: actions/checkout@v4 - - # - name: Setup Environment - # uses: ./.github/actions/setup - # with: - # cargo-cache-key: cargo-programs - # cargo-cache-local-key: cargo-local - - # - name: Generate IDLs - # run: pnpm generate:idls - - # - name: Check Working Directory - # run: | - # git status --porcelain - # test -z "$(git status --porcelain)" + run: make conformance generate_clients: name: Check Client Generation runs-on: ubuntu-latest - needs: format_and_lint_programs steps: - name: Git Checkout uses: actions/checkout@v4 @@ -207,7 +217,8 @@ jobs: - name: Setup Environment uses: ./.github/actions/setup with: - rustfmt: true + pnpm: true + toolchain: format - name: Generate Clients run: pnpm generate:clients @@ -220,7 +231,6 @@ jobs: test_client_js: name: Test Client JS runs-on: ubuntu-latest - needs: build_programs steps: - name: Git Checkout uses: actions/checkout@v4 @@ -228,21 +238,15 @@ jobs: - name: Setup Environment uses: ./.github/actions/setup with: + pnpm: true solana: true - - name: Restore Program Builds - uses: actions/cache/restore@v4 - with: - path: ./**/*.so - key: ${{ runner.os }}-builds-${{ github.sha }} - - name: Test Client JS - run: pnpm clients:js:test + run: make test-js test_client_rust: name: Test Client Rust runs-on: ubuntu-latest - needs: build_programs steps: - name: Git Checkout uses: actions/checkout@v4 @@ -251,13 +255,8 @@ jobs: uses: ./.github/actions/setup with: cargo-cache-key: cargo-rust-client + toolchain: test solana: true - - name: Restore Program Builds - uses: actions/cache/restore@v4 - with: - path: ./**/*.so - key: ${{ runner.os }}-builds-${{ github.sha }} - - name: Test Client Rust - run: pnpm clients:rust:test + run: make test-clients-rust \ No newline at end of file diff --git a/.github/workflows/publish-js-client.yml b/.github/workflows/publish-js-client.yml index d32f29a..7cef8d9 100644 --- a/.github/workflows/publish-js-client.yml +++ b/.github/workflows/publish-js-client.yml @@ -38,20 +38,19 @@ jobs: - name: Setup Environment uses: ./.github/actions/setup with: - cargo-cache-key: cargo-programs solana: true - - name: Format JS Client - run: pnpm clients:js:format + - name: Format + run: make format-js - - name: Lint JS Client - run: pnpm clients:js:lint + - name: Lint + run: make lint-js - - name: Build Programs - run: pnpm programs:build + - name: Build program + run: make build-program - - name: Test JS Client - run: pnpm clients:js:test + - name: Test + run: make test-js publish_js: name: Publish JS client @@ -87,7 +86,7 @@ jobs: - name: Publish JS Client id: publish - run: pnpm clients:js:publish ${{ inputs.level }} ${{ inputs.tag }} + run: ./scripts/publish-js.sh clients/js ${{ inputs.level }} ${{ inputs.tag }} - name: Push Commit and Tag run: git push origin --follow-tags diff --git a/.github/workflows/publish-rust-client.yml b/.github/workflows/publish-rust-crate.yml similarity index 63% rename from .github/workflows/publish-rust-client.yml rename to .github/workflows/publish-rust-crate.yml index c6397f7..5e2dbbc 100644 --- a/.github/workflows/publish-rust-client.yml +++ b/.github/workflows/publish-rust-crate.yml @@ -1,8 +1,17 @@ -name: Publish Rust Client +name: Publish Rust Crate on: workflow_dispatch: inputs: + package_path: + description: Path to directory with package to release + required: true + default: 'clients/rust' + type: choice + options: + - clients/rust + - interface + - program level: description: Level required: true @@ -34,7 +43,7 @@ on: jobs: test_rust: - name: Test Rust client + name: Test Rust Crate runs-on: ubuntu-latest steps: - name: Git Checkout @@ -43,25 +52,34 @@ jobs: - name: Setup Environment uses: ./.github/actions/setup with: - cargo-cache-key: cargo-rust-client + cargo-cache-key: cargo-rust-${{ inputs.package_path }} clippy: true rustfmt: true solana: true + + - name: Convert package_path to required variables + run: | + PACKAGE_PATH="${{ inputs.package_path }}" + RECIPE_SUFFIX="${PACKAGE_PATH//\//-}" + TAG_PREFIX="$(basename "$PACKAGE_PATH")" + + echo "RECIPE_SUFFIX=$RECIPE_SUFFIX" >> $GITHUB_ENV + echo "TAG_PREFIX=$TAG_PREFIX" >> $GITHUB_ENV - - name: Format Rust Client - run: pnpm clients:rust:format + - name: Format + run: make format-${{ env.RECIPE_SUFFIX }} - - name: Lint Rust Client - run: pnpm clients:rust:lint + - name: Lint + run: make clippy-${{ env.RECIPE_SUFFIX }} - - name: Build Programs - run: pnpm programs:build + - name: Build Program + run: make build-program - - name: Test Rust Client - run: pnpm clients:rust:test + - name: Test + run: make test-${{ env.RECIPE_SUFFIX }} publish_rust: - name: Publish Rust Client + name: Publish Rust Crate runs-on: ubuntu-latest needs: test_rust permissions: @@ -73,8 +91,8 @@ jobs: - name: Setup Environment uses: ./.github/actions/setup with: - cargo-cache-key: cargo-publish-rust-client - cargo-cache-fallback-key: cargo-rust-client + cargo-cache-key: cargo-publish-rust-${{ inputs.package_path }} + cargo-cache-fallback-key: cargo-rust-${{ inputs.package_path }} clippy: true rustfmt: true @@ -95,7 +113,7 @@ jobs: git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" git config --global user.name "github-actions[bot]" - - name: Publish Rust Client + - name: Publish Rust Crate id: publish env: CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} @@ -112,14 +130,10 @@ jobs: OPTIONS="" fi - pnpm clients:rust:publish $LEVEL $OPTIONS - - - name: Push Commit and Tag - if: github.event.inputs.dry_run != 'true' - run: git push origin --follow-tags + ./scripts/publish-rust.sh ${{ inputs.package_path }} $LEVEL $OPTIONS - name: Create GitHub release - if: github.event.inputs.create_release == 'true' && github.event.inputs.dry_run != 'true' + if: inputs.create_release == 'true' && inputs.dry_run != 'true' uses: ncipollo/release-action@v1 with: - tag: rust@v${{ steps.publish.outputs.new_version }} + tag: ${{ env.TAG_PREFIX }}@v${{ steps.publish.outputs.new_version }} diff --git a/Cargo.toml b/Cargo.toml index 8dd6f32..a456af8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,15 +13,6 @@ readme = "./README.md" license-file = "./LICENSE" edition = "2021" -[workspace.metadata.cli] -solana = "2.2.0" - -# Specify Rust toolchains for rustfmt, clippy, and build. -# Any unprovided toolchains default to stable. -[workspace.metadata.toolchains] -format = "nightly-2024-11-22" -lint = "nightly-2024-11-22" - [workspace.dependencies] assert_matches = "1.5.0" bincode = "1.3.3" diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..fc095f4 --- /dev/null +++ b/Makefile @@ -0,0 +1,53 @@ +include vars.env + +nightly = +$(subst ",,${RUST_TOOLCHAIN_NIGHTLY}) + +clippy-%: + cargo $(nightly) clippy --manifest-path $(subst -,/,$*)/Cargo.toml + +format-%: + cargo $(nightly) fmt --check --manifest-path $(subst -,/,$*)/Cargo.toml + +format-%-fix: + cargo $(nightly) fmt --manifest-path $(subst -,/,$*)/Cargo.toml + +features-%: + cargo $(nightly) hack check --feature-powerset --all-targets --manifest-path $(subst -,/,$*)/Cargo.toml + +publish-%: + ./scripts/publish-rust.sh $(subst -,/,$*) + +lint-docs-%: + RUSTDOCFLAGS="--cfg docsrs -D warnings" cargo $(nightly) doc --all-features --no-deps --manifest-path $(subst -,/,$*)/Cargo.toml + +lint-features-%: + cargo $(nightly) hack check --feature-powerset --all-targets --manifest-path $(subst -,/,$*)/Cargo.toml + +build-%: + cargo build --manifest-path $(subst -,/,$*)/Cargo.toml + +build-program: + cargo build-sbf --manifest-path program/Cargo.toml --features bpf-entrypoint + +test-%: + cargo $(nightly) test --manifest-path $(subst -,/,$*)/Cargo.toml + +test-program: + cargo test-sbf --manifest-path program/Cargo.toml --features bpf-entrypoint + +bench-program-compute-units: + cargo bench --manifest-path program/Cargo.toml + +conformance: + ./scripts/conformance.sh + +format-js: + cd ./clients/js && pnpm install && pnpm format + +lint-js: + cd ./clients/js && pnpm install && pnpm lint + +test-js: + ./scripts/restart-test-validator.sh + cd ./clients/js && pnpm install && pnpm build && pnpm test + ./scripts/stop-test-validator.sh \ No newline at end of file diff --git a/codama.mjs b/codama.mjs new file mode 100644 index 0000000..03c2c33 --- /dev/null +++ b/codama.mjs @@ -0,0 +1,42 @@ +import path from 'node:path'; +import { config } from 'dotenv'; + +config({ path: path.resolve(process.cwd(), 'vars.env') }); + +const { default: prettierOptions } = await import( + path.resolve('clients', 'js', '.prettierrc.json'), + { with: { type: 'json' } } +); + +export default { + idl: 'program/idl.json', + before: [ + { + from: '@codama/renderers-js', + args: ['clients/js/src/generated', { prettierOptions }], + }, + { + from: '@codama/visitors-core#deleteNodesVisitor', + args: [['[definedTypeNode]configKeys']], + }, + ], + scripts: { + rust: { + from: '@codama/renderers-rust', + args: [ + 'clients/rust/src/generated', + { + anchorTraits: false, + crateFolder: 'clients/rust', + formatCode: true, + linkOverrides: { + definedTypes: { + configKeys: 'hooked', + }, + }, + toolchain: `+${process.env.RUST_TOOLCHAIN_NIGHTLY}`, + }, + ], + }, + }, +}; \ No newline at end of file diff --git a/package.json b/package.json index a048d33..7ff8b67 100644 --- a/package.json +++ b/package.json @@ -1,36 +1,15 @@ { "private": true, "scripts": { - "programs:build": "zx ./scripts/program/build.mjs", - "programs:test": "zx ./scripts/program/test.mjs", - "programs:bench": "zx ./scripts/program/bench.mjs", - "programs:clean": "zx ./scripts/program/clean.mjs", - "programs:format": "zx ./scripts/program/format.mjs", - "programs:lint": "zx ./scripts/program/lint.mjs", - "solana:check": "zx ./scripts/check-solana-version.mjs", - "solana:link": "zx ./scripts/link-solana-version.mjs", "generate": "pnpm generate:clients", - "generate:clients": "zx ./scripts/generate-clients.mjs", - "validator:start": "zx ./scripts/start-validator.mjs", - "validator:restart": "pnpm validator:start --restart", - "validator:stop": "zx ./scripts/stop-validator.mjs", - "clients:js:format": "zx ./scripts/client/format-js.mjs", - "clients:js:lint": "zx ./scripts/client/lint-js.mjs", - "clients:js:publish": "zx ./scripts/client/publish-js.mjs", - "clients:js:test": "zx ./scripts/client/test-js.mjs", - "clients:rust:format": "zx ./scripts/client/format-rust.mjs", - "clients:rust:lint": "zx ./scripts/client/lint-rust.mjs", - "clients:rust:publish": "zx ./scripts/client/publish-rust.mjs", - "clients:rust:test": "zx ./scripts/client/test-rust.mjs", - "template:upgrade": "zx ./scripts/upgrade-template.mjs" + "generate:clients": "codama run --all" }, "devDependencies": { "@codama/renderers-js": "^1.2.8", "@codama/renderers-rust": "^1.0.17", - "@iarna/toml": "^2.2.5", + "@codama/visitors-core": "^1.2.13", "codama": "^1.2.9", - "typescript": "^5.5.2", - "zx": "^7.2.3" + "dotenv": "^16.5.0" }, "engines": { "node": ">=v20.0.0" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 102da5b..8ab7f82 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,34 +14,41 @@ importers: '@codama/renderers-rust': specifier: ^1.0.17 version: 1.0.17(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.5.4) - '@iarna/toml': - specifier: ^2.2.5 - version: 2.2.5 + '@codama/visitors-core': + specifier: ^1.2.13 + version: 1.2.13 codama: specifier: ^1.2.9 version: 1.2.9(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.5.4) - typescript: - specifier: ^5.5.2 - version: 5.5.4 - zx: - specifier: ^7.2.3 - version: 7.2.3 + dotenv: + specifier: ^16.5.0 + version: 16.5.0 packages: '@codama/cli@1.0.8': resolution: {integrity: sha512-ZHVfemR0QkBssKItNplnBGJj0Bnj4VZ8HRHD1PFCiByPLAcJTIQtMxlslCSuboeLoiK2f6vQbRe/5KurJjgn3Q==} + '@codama/errors@1.2.13': + resolution: {integrity: sha512-PWQou0unQw26bqz9Ae1K+Jr6gnZJv7vwsDBL02UauOnPvG/FXlpYJ56IXluvbIYzK4DnvgCvLS1GyBbgTdv62Q==} + hasBin: true + '@codama/errors@1.2.9': resolution: {integrity: sha512-6RKKBBGqUfyotsKOKG3Z39spphwiwu9lOvIhws1r1uefpSgFmpHMgz0X/YLgPnBHRnlcFEZyBaO8z1db8MYPKg==} hasBin: true + '@codama/node-types@1.2.13': + resolution: {integrity: sha512-ADm7E2yjoaWy7iw9et7tT16KuqLaGejjZoZHoEiQTtz4IepCEFB/wZMbzbBtL8c4c76uQkLKPkTNdY8nJYT9mw==} + '@codama/node-types@1.2.9': resolution: {integrity: sha512-tW3uPzldFTv5I5tkW2WZvdXIxc/JT+JIwYERfvtlTwRzleEfPOeC1EDE4LUUUtRx7qRfa3Gga8I2/CWZWvfbJQ==} '@codama/nodes-from-anchor@1.1.9': resolution: {integrity: sha512-K7oTHO2gsuF5DcVPMtMlQFpqH6z+Clu1S9vyHQZN65n9PYCh9byEwU6NgsowJCS0k58AQLEv0bUJmLwltrHsKw==} + '@codama/nodes@1.2.13': + resolution: {integrity: sha512-yf43WbjsFpIdyMiYBC6a8GYXgAmuoShkJSquBSL0Ul5IA+kV65VrnAgdNf5S5r/Q0Og7s4qEqrt7yDdwjVM+hg==} + '@codama/nodes@1.2.9': resolution: {integrity: sha512-qkKNrt+ntgMmprOtqbPHsOKve8mHaov/QIp89fAygCOxfniVFt+JSBnZTgmgYZhTtK60X7sp0kAD7uWDRKS+vg==} @@ -63,31 +70,19 @@ packages: '@codama/validators@1.2.9': resolution: {integrity: sha512-se6irMEE6aWLRaJ0yoHWsrfRpzRojtObYVWpnxVIAoTbL3v/Lg30IRVhU/geIec1f2wbcx6avMaYCReiseEHvw==} + '@codama/visitors-core@1.2.13': + resolution: {integrity: sha512-H1E23fVAoLI8Jkh9wFFZ9I/LnYlXd8PTHdCElKQdl7RFG3vjECKLhePa4v4un0d8pZX+k8L2Z/OZPiavDhhGKw==} + '@codama/visitors-core@1.2.9': resolution: {integrity: sha512-qQwpAl7RjyupMhMuWVHIbSaVhqbiUtGLJsxs7YDlfKUo7kz9+vF4cS96n7HY3mFF+PCtyDzEiFHFu+JYEemHgg==} '@codama/visitors@1.2.9': resolution: {integrity: sha512-hB/CF0q9x4NmAsqlDu0wOsC6yl57TKJs25NS5A0PcBM8dEK1ljUcFUbsxoMAQJhoeWnUhScSsK5qe1W1jxLhzA==} - '@iarna/toml@2.2.5': - resolution: {integrity: sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==} - '@noble/hashes@1.7.1': resolution: {integrity: sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==} engines: {node: ^14.21.3 || >=16} - '@nodelib/fs.scandir@2.1.5': - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} - - '@nodelib/fs.stat@2.0.5': - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} - - '@nodelib/fs.walk@1.2.8': - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} - '@solana/codecs-core@2.0.0-rc.4': resolution: {integrity: sha512-JIrTSps032mSE3wBxW3bXOqWfoy4CMy1CX/XeVCijyh5kLVxZTSDIdRTYdePdL1yzaOZF1Xysvt1DhOUgBdM+A==} engines: {node: '>=20.18.0'} @@ -158,34 +153,12 @@ packages: peerDependencies: typescript: '>=5' - '@types/fs-extra@11.0.4': - resolution: {integrity: sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==} - - '@types/jsonfile@6.1.4': - resolution: {integrity: sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==} - - '@types/minimist@1.2.5': - resolution: {integrity: sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==} - - '@types/node@18.19.42': - resolution: {integrity: sha512-d2ZFc/3lnK2YCYhos8iaNIYu9Vfhr92nHiyJHRltXWjXUBjEE+A4I58Tdbnw4VhggSW+2j5y5gTrLs4biNnubg==} - - '@types/ps-tree@1.1.6': - resolution: {integrity: sha512-PtrlVaOaI44/3pl3cvnlK+GxOM3re2526TJvPvh7W+keHIXdV4TE0ylpPBAcvFQCbGitaTXwL9u+RF7qtVeazQ==} - - '@types/which@3.0.4': - resolution: {integrity: sha512-liyfuo/106JdlgSchJzXEQCVArk0CvevqPote8F8HgWgJ3dRCcTHgJIsLDuee0kxk/mhbInzIZk3QWSZJ8R+2w==} - a-sync-waterfall@1.0.1: resolution: {integrity: sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==} asap@2.0.6: resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} - braces@3.0.3: - resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} - engines: {node: '>=8'} - call-bind-apply-helpers@1.0.2: resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} engines: {node: '>= 0.4'} @@ -198,9 +171,9 @@ packages: resolution: {integrity: sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==} engines: {node: '>= 0.4'} - chalk@5.3.0: - resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} - engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + call-bound@1.0.4: + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} chalk@5.4.1: resolution: {integrity: sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==} @@ -222,25 +195,18 @@ packages: resolution: {integrity: sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==} engines: {node: '>= 6'} - data-uri-to-buffer@4.0.1: - resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} - engines: {node: '>= 12'} - define-data-property@1.1.4: resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} engines: {node: '>= 0.4'} - dir-glob@3.0.1: - resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} - engines: {node: '>=8'} + dotenv@16.5.0: + resolution: {integrity: sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==} + engines: {node: '>=12'} dunder-proto@1.0.1: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} - duplexer@0.1.2: - resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} - es-define-property@1.0.1: resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} engines: {node: '>= 0.4'} @@ -253,45 +219,12 @@ packages: resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} engines: {node: '>= 0.4'} - event-stream@3.3.4: - resolution: {integrity: sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==} - - fast-glob@3.3.2: - resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} - engines: {node: '>=8.6.0'} - fastestsmallesttextencoderdecoder@1.0.22: resolution: {integrity: sha512-Pb8d48e+oIuY4MaM64Cd7OW1gt4nxCHs7/ddPPZ/Ic3sg8yVGM7O9wDvZ7us6ScaUupzM+pfBolwtYhN1IxBIw==} - fastq@1.17.1: - resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} - - fetch-blob@3.2.0: - resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} - engines: {node: ^12.20 || >= 14.13} - - fill-range@7.1.1: - resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} - engines: {node: '>=8'} - - formdata-polyfill@4.0.10: - resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} - engines: {node: '>=12.20.0'} - - from@0.1.7: - resolution: {integrity: sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==} - - fs-extra@11.2.0: - resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==} - engines: {node: '>=14.14'} - function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - fx@35.0.0: - resolution: {integrity: sha512-O07q+Lknrom5RUX/u53tjo2KTTLUnL0K703JbqMYb19ORijfJNvijzFqqYXEjdk25T9R14S6t6wHD8fCWXCM0g==} - hasBin: true - get-intrinsic@1.3.0: resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} engines: {node: '>= 0.4'} @@ -300,21 +233,10 @@ packages: resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} engines: {node: '>= 0.4'} - glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} - - globby@13.2.2: - resolution: {integrity: sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - gopd@1.2.0: resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} engines: {node: '>= 0.4'} - graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - has-property-descriptors@1.0.2: resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} @@ -326,34 +248,16 @@ packages: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} - ignore@5.3.1: - resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} - engines: {node: '>= 4'} - - is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - - is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - - is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - isarray@2.0.5: resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} - isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - json-stable-stringify@1.2.1: resolution: {integrity: sha512-Lp6HbbBgosLmJbjx0pBLbgvx68FaFU1sdkmBuckmhhJ88kL13OA51CDtR2yJB50eCNMH9wRqtQNNiAqQH4YXnA==} engines: {node: '>= 0.4'} - jsonfile@6.1.0: - resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + json-stable-stringify@1.3.0: + resolution: {integrity: sha512-qtYiSSFlwot9XHtF9bD9c7rwKjr+RecWT//ZnPvSmEjpV5mmPOCN4j8UjY5hbjNkOwZ/jQv3J6R1/pL7RwgMsg==} + engines: {node: '>= 0.4'} jsonify@0.0.1: resolution: {integrity: sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==} @@ -362,32 +266,10 @@ packages: resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} engines: {node: '>=6'} - map-stream@0.1.0: - resolution: {integrity: sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==} - math-intrinsics@1.1.0: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} engines: {node: '>= 0.4'} - merge2@1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} - - micromatch@4.0.7: - resolution: {integrity: sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==} - engines: {node: '>=8.6'} - - minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - - node-domexception@1.0.0: - resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} - engines: {node: '>=10.5.0'} - - node-fetch@3.3.1: - resolution: {integrity: sha512-cRVc/kyto/7E5shrWca1Wsea4y6tL9iYJE5FBCius3JQfb/4P4I295PfhgbJQBLTx6lATE4z+wK0rPM4VS2uow==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - nunjucks@3.2.4: resolution: {integrity: sha512-26XRV6BhkgK0VOxfbU5cQI+ICFUtMLixv1noZn1tGU38kQH5A5nmmbk/O45xdyBhD1esk47nKrY0mvQpZIhRjQ==} engines: {node: '>= 6.9.0'} @@ -402,20 +284,9 @@ packages: resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} engines: {node: '>= 0.4'} - path-type@4.0.0: - resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} - engines: {node: '>=8'} - - pause-stream@0.0.11: - resolution: {integrity: sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==} - picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} - picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - prettier@3.5.3: resolution: {integrity: sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==} engines: {node: '>=14'} @@ -425,21 +296,6 @@ packages: resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} engines: {node: '>= 6'} - ps-tree@1.2.0: - resolution: {integrity: sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==} - engines: {node: '>= 0.10'} - hasBin: true - - queue-microtask@1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - - reusify@1.0.4: - resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - - run-parallel@1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - set-function-length@1.2.2: resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} engines: {node: '>= 0.4'} @@ -447,58 +303,11 @@ packages: sisteransi@1.0.5: resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} - slash@4.0.0: - resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==} - engines: {node: '>=12'} - - split@0.3.3: - resolution: {integrity: sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==} - - stream-combiner@0.0.4: - resolution: {integrity: sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==} - - through@2.3.8: - resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} - - to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} - typescript@5.5.4: resolution: {integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==} engines: {node: '>=14.17'} hasBin: true - undici-types@5.26.5: - resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} - - universalify@2.0.1: - resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} - engines: {node: '>= 10.0.0'} - - web-streams-polyfill@3.3.3: - resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} - engines: {node: '>= 8'} - - webpod@0.0.2: - resolution: {integrity: sha512-cSwwQIeg8v4i3p4ajHhwgR7N6VyxAf+KYSSsY6Pd3aETE+xEU4vbitz7qQkB0I321xnhDdgtxuiSfk5r/FVtjg==} - hasBin: true - - which@3.0.1: - resolution: {integrity: sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - hasBin: true - - yaml@2.5.0: - resolution: {integrity: sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw==} - engines: {node: '>= 14'} - hasBin: true - - zx@7.2.3: - resolution: {integrity: sha512-QODu38nLlYXg/B/Gw7ZKiZrvPkEsjPN3LQ5JFXM7h0JvwhEdPNNl+4Ao1y4+o3CLNiDUNcwzQYZ4/Ko7kKzCMA==} - engines: {node: '>= 16.0.0'} - hasBin: true - snapshots: '@codama/cli@1.0.8(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.5.4)': @@ -519,12 +328,20 @@ snapshots: - fastestsmallesttextencoderdecoder - typescript + '@codama/errors@1.2.13': + dependencies: + '@codama/node-types': 1.2.13 + chalk: 5.4.1 + commander: 13.1.0 + '@codama/errors@1.2.9': dependencies: '@codama/node-types': 1.2.9 chalk: 5.4.1 commander: 13.1.0 + '@codama/node-types@1.2.13': {} + '@codama/node-types@1.2.9': {} '@codama/nodes-from-anchor@1.1.9(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.5.4)': @@ -538,6 +355,11 @@ snapshots: - fastestsmallesttextencoderdecoder - typescript + '@codama/nodes@1.2.13': + dependencies: + '@codama/errors': 1.2.13 + '@codama/node-types': 1.2.13 + '@codama/nodes@1.2.9': dependencies: '@codama/errors': 1.2.9 @@ -608,6 +430,12 @@ snapshots: '@codama/nodes': 1.2.9 '@codama/visitors-core': 1.2.9 + '@codama/visitors-core@1.2.13': + dependencies: + '@codama/errors': 1.2.13 + '@codama/nodes': 1.2.13 + json-stable-stringify: 1.3.0 + '@codama/visitors-core@1.2.9': dependencies: '@codama/errors': 1.2.9 @@ -620,22 +448,8 @@ snapshots: '@codama/nodes': 1.2.9 '@codama/visitors-core': 1.2.9 - '@iarna/toml@2.2.5': {} - '@noble/hashes@1.7.1': {} - '@nodelib/fs.scandir@2.1.5': - dependencies: - '@nodelib/fs.stat': 2.0.5 - run-parallel: 1.2.0 - - '@nodelib/fs.stat@2.0.5': {} - - '@nodelib/fs.walk@1.2.8': - dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.17.1 - '@solana/codecs-core@2.0.0-rc.4(typescript@5.5.4)': dependencies: '@solana/errors': 2.0.0-rc.4(typescript@5.5.4) @@ -715,33 +529,10 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@types/fs-extra@11.0.4': - dependencies: - '@types/jsonfile': 6.1.4 - '@types/node': 18.19.42 - - '@types/jsonfile@6.1.4': - dependencies: - '@types/node': 18.19.42 - - '@types/minimist@1.2.5': {} - - '@types/node@18.19.42': - dependencies: - undici-types: 5.26.5 - - '@types/ps-tree@1.1.6': {} - - '@types/which@3.0.4': {} - a-sync-waterfall@1.0.1: {} asap@2.0.6: {} - braces@3.0.3: - dependencies: - fill-range: 7.1.1 - call-bind-apply-helpers@1.0.2: dependencies: es-errors: 1.3.0 @@ -759,7 +550,10 @@ snapshots: call-bind-apply-helpers: 1.0.2 get-intrinsic: 1.3.0 - chalk@5.3.0: {} + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 chalk@5.4.1: {} @@ -781,17 +575,13 @@ snapshots: commander@5.1.0: {} - data-uri-to-buffer@4.0.1: {} - define-data-property@1.1.4: dependencies: es-define-property: 1.0.1 es-errors: 1.3.0 gopd: 1.2.0 - dir-glob@3.0.1: - dependencies: - path-type: 4.0.0 + dotenv@16.5.0: {} dunder-proto@1.0.1: dependencies: @@ -799,8 +589,6 @@ snapshots: es-errors: 1.3.0 gopd: 1.2.0 - duplexer@0.1.2: {} - es-define-property@1.0.1: {} es-errors@1.3.0: {} @@ -809,55 +597,10 @@ snapshots: dependencies: es-errors: 1.3.0 - event-stream@3.3.4: - dependencies: - duplexer: 0.1.2 - from: 0.1.7 - map-stream: 0.1.0 - pause-stream: 0.0.11 - split: 0.3.3 - stream-combiner: 0.0.4 - through: 2.3.8 - - fast-glob@3.3.2: - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.7 - fastestsmallesttextencoderdecoder@1.0.22: {} - fastq@1.17.1: - dependencies: - reusify: 1.0.4 - - fetch-blob@3.2.0: - dependencies: - node-domexception: 1.0.0 - web-streams-polyfill: 3.3.3 - - fill-range@7.1.1: - dependencies: - to-regex-range: 5.0.1 - - formdata-polyfill@4.0.10: - dependencies: - fetch-blob: 3.2.0 - - from@0.1.7: {} - - fs-extra@11.2.0: - dependencies: - graceful-fs: 4.2.11 - jsonfile: 6.1.0 - universalify: 2.0.1 - function-bind@1.1.2: {} - fx@35.0.0: {} - get-intrinsic@1.3.0: dependencies: call-bind-apply-helpers: 1.0.2 @@ -876,22 +619,8 @@ snapshots: dunder-proto: 1.0.1 es-object-atoms: 1.1.1 - glob-parent@5.1.2: - dependencies: - is-glob: 4.0.3 - - globby@13.2.2: - dependencies: - dir-glob: 3.0.1 - fast-glob: 3.3.2 - ignore: 5.3.1 - merge2: 1.4.1 - slash: 4.0.0 - gopd@1.2.0: {} - graceful-fs@4.2.11: {} - has-property-descriptors@1.0.2: dependencies: es-define-property: 1.0.1 @@ -902,20 +631,8 @@ snapshots: dependencies: function-bind: 1.1.2 - ignore@5.3.1: {} - - is-extglob@2.1.1: {} - - is-glob@4.0.3: - dependencies: - is-extglob: 2.1.1 - - is-number@7.0.0: {} - isarray@2.0.5: {} - isexe@2.0.0: {} - json-stable-stringify@1.2.1: dependencies: call-bind: 1.0.8 @@ -924,37 +641,20 @@ snapshots: jsonify: 0.0.1 object-keys: 1.1.1 - jsonfile@6.1.0: + json-stable-stringify@1.3.0: dependencies: - universalify: 2.0.1 - optionalDependencies: - graceful-fs: 4.2.11 + call-bind: 1.0.8 + call-bound: 1.0.4 + isarray: 2.0.5 + jsonify: 0.0.1 + object-keys: 1.1.1 jsonify@0.0.1: {} kleur@3.0.3: {} - map-stream@0.1.0: {} - math-intrinsics@1.1.0: {} - merge2@1.4.1: {} - - micromatch@4.0.7: - dependencies: - braces: 3.0.3 - picomatch: 2.3.1 - - minimist@1.2.8: {} - - node-domexception@1.0.0: {} - - node-fetch@3.3.1: - dependencies: - data-uri-to-buffer: 4.0.1 - fetch-blob: 3.2.0 - formdata-polyfill: 4.0.10 - nunjucks@3.2.4: dependencies: a-sync-waterfall: 1.0.1 @@ -963,16 +663,8 @@ snapshots: object-keys@1.1.1: {} - path-type@4.0.0: {} - - pause-stream@0.0.11: - dependencies: - through: 2.3.8 - picocolors@1.1.1: {} - picomatch@2.3.1: {} - prettier@3.5.3: {} prompts@2.4.2: @@ -980,18 +672,6 @@ snapshots: kleur: 3.0.3 sisteransi: 1.0.5 - ps-tree@1.2.0: - dependencies: - event-stream: 3.3.4 - - queue-microtask@1.2.3: {} - - reusify@1.0.4: {} - - run-parallel@1.2.0: - dependencies: - queue-microtask: 1.2.3 - set-function-length@1.2.2: dependencies: define-data-property: 1.1.4 @@ -1003,52 +683,4 @@ snapshots: sisteransi@1.0.5: {} - slash@4.0.0: {} - - split@0.3.3: - dependencies: - through: 2.3.8 - - stream-combiner@0.0.4: - dependencies: - duplexer: 0.1.2 - - through@2.3.8: {} - - to-regex-range@5.0.1: - dependencies: - is-number: 7.0.0 - typescript@5.5.4: {} - - undici-types@5.26.5: {} - - universalify@2.0.1: {} - - web-streams-polyfill@3.3.3: {} - - webpod@0.0.2: {} - - which@3.0.1: - dependencies: - isexe: 2.0.0 - - yaml@2.5.0: {} - - zx@7.2.3: - dependencies: - '@types/fs-extra': 11.0.4 - '@types/minimist': 1.2.5 - '@types/node': 18.19.42 - '@types/ps-tree': 1.1.6 - '@types/which': 3.0.4 - chalk: 5.3.0 - fs-extra: 11.2.0 - fx: 35.0.0 - globby: 13.2.2 - minimist: 1.2.8 - node-fetch: 3.3.1 - ps-tree: 1.2.0 - webpod: 0.0.2 - which: 3.0.1 - yaml: 2.5.0 diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..fcb78ec --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "1.84.1" diff --git a/scripts/check-solana-version.mjs b/scripts/check-solana-version.mjs deleted file mode 100644 index 28c1d19..0000000 --- a/scripts/check-solana-version.mjs +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env zx -import 'zx/globals'; -import { getInstalledSolanaVersion, getSolanaVersion } from './utils.mjs'; - -const expectedVersion = getSolanaVersion(); -const installedVersion = await getInstalledSolanaVersion(); - -if (!installedVersion) { - echo( - chalk.red('[ ERROR ]'), - `No Solana installation found. Please install Solana ${expectedVersion} before proceeding.` - ); - process.exit(1); -} else if (installedVersion !== expectedVersion) { - echo( - chalk.yellow('[ WARNING ]'), - `The installed Solana version ${installedVersion} does not match the expected version ${expectedVersion}.` - ); -} else { - echo( - chalk.green('[ SUCCESS ]'), - `The expected Solana version ${expectedVersion} is installed.` - ); -} diff --git a/scripts/ci/conformance.mjs b/scripts/ci/conformance.mjs deleted file mode 100644 index b996b6c..0000000 --- a/scripts/ci/conformance.mjs +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env zx - -// Mollusk conformance testing of this Core BPF Config program against the -// version running on mainnet-beta. - -import 'zx/globals'; -import { getProgramId, getProgramSharedObjectPath, workingDirectory } from '../utils.mjs'; - -const programId = getProgramId('program'); -const programBinaryPath = getProgramSharedObjectPath('program'); -const baseBinaryPath = path.join(workingDirectory, 'program', 'fuzz', 'program-mb-3-17-2025.so'); -const molluskFixturesPath = path.join(workingDirectory, 'program', 'fuzz', 'blob'); - -// Test this program against the cloned program for conformance with Mollusk. -let output = await $`mollusk run-test \ - --proto firedancer --ignore-compute-units \ - ${baseBinaryPath} ${programBinaryPath} \ - ${molluskFixturesPath} ${programId}`; - -// The last line of output should exactly match the following: -// [DONE][TEST RESULT]: 0 failures -if (!output.stdout.includes("[DONE][TEST RESULT]: 0 failures")) { - throw new Error(`Error: mismatches detected.`); -} diff --git a/scripts/ci/set-env.mjs b/scripts/ci/set-env.mjs deleted file mode 100644 index 276d37b..0000000 --- a/scripts/ci/set-env.mjs +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env zx -import { getSolanaVersion, getToolchain } from '../utils.mjs'; - -await $`echo "SOLANA_VERSION=${getSolanaVersion()}" >> $GITHUB_ENV`; -await $`echo "TOOLCHAIN_FORMAT=${getToolchain('format')}" >> $GITHUB_ENV`; -await $`echo "TOOLCHAIN_LINT=${getToolchain('lint')}" >> $GITHUB_ENV`; diff --git a/scripts/client/format-js.mjs b/scripts/client/format-js.mjs deleted file mode 100644 index dcfc3d4..0000000 --- a/scripts/client/format-js.mjs +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env zx -import 'zx/globals'; -import { cliArguments, workingDirectory } from '../utils.mjs'; - -// Format the client using Prettier. -cd(path.join(workingDirectory, 'clients', 'js')); -await $`pnpm install`; -await $`pnpm format ${cliArguments()}`; diff --git a/scripts/client/format-rust.mjs b/scripts/client/format-rust.mjs deleted file mode 100644 index 038a832..0000000 --- a/scripts/client/format-rust.mjs +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env zx -import 'zx/globals'; -import { - cliArguments, - getToolchainArgument, - partitionArguments, - popArgument, - workingDirectory, -} from '../utils.mjs'; - -// Configure additional arguments here, e.g.: -// ['--arg1', '--arg2', ...cliArguments()] -const formatArgs = cliArguments(); - -const fix = popArgument(formatArgs, '--fix'); -const [cargoArgs, fmtArgs] = partitionArguments(formatArgs, '--'); -const toolchain = getToolchainArgument('format'); -const manifestPath = path.join( - workingDirectory, - 'clients', - 'rust', - 'Cargo.toml' -); - -// Format the client. -if (fix) { - await $`cargo ${toolchain} fmt --manifest-path ${manifestPath} ${cargoArgs} -- ${fmtArgs}`; -} else { - await $`cargo ${toolchain} fmt --manifest-path ${manifestPath} ${cargoArgs} -- --check ${fmtArgs}`; -} diff --git a/scripts/client/lint-js.mjs b/scripts/client/lint-js.mjs deleted file mode 100644 index f5583e2..0000000 --- a/scripts/client/lint-js.mjs +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env zx -import 'zx/globals'; -import { cliArguments, workingDirectory } from '../utils.mjs'; - -// Check the client using ESLint. -cd(path.join(workingDirectory, 'clients', 'js')); -await $`pnpm install`; -await $`pnpm lint ${cliArguments()}`; diff --git a/scripts/client/lint-rust.mjs b/scripts/client/lint-rust.mjs deleted file mode 100644 index ecce152..0000000 --- a/scripts/client/lint-rust.mjs +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env zx -import 'zx/globals'; -import { - cliArguments, - getToolchainArgument, - popArgument, - workingDirectory, -} from '../utils.mjs'; - -// Configure additional arguments here, e.g.: -// ['--arg1', '--arg2', ...cliArguments()] -const lintArgs = [ - '-Zunstable-options', - '--all-features', - '--', - '--deny=warnings', - ...cliArguments() -]; - -const fix = popArgument(lintArgs, '--fix'); -const toolchain = getToolchainArgument('lint'); -const manifestPath = path.join( - workingDirectory, - 'clients', - 'rust', - 'Cargo.toml' -); - -// Check the client using Clippy. -if (fix) { - await $`cargo ${toolchain} clippy --manifest-path ${manifestPath} --fix ${lintArgs}`; -} else { - await $`cargo ${toolchain} clippy --manifest-path ${manifestPath} ${lintArgs}`; -} diff --git a/scripts/client/publish-js.mjs b/scripts/client/publish-js.mjs deleted file mode 100644 index 51df188..0000000 --- a/scripts/client/publish-js.mjs +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env zx -import 'zx/globals'; -import { cliArguments, workingDirectory } from '../utils.mjs'; - -const [level, tag = 'latest'] = cliArguments(); -if (!level) { - throw new Error('A version level — e.g. "path" — must be provided.'); -} - -// Go to the client directory and install the dependencies. -cd(path.join(workingDirectory, 'clients', 'js')); -await $`pnpm install`; - -// Update the version. -const versionArgs = [ - '--no-git-tag-version', - ...(level.startsWith('pre') ? [`--preid ${tag}`] : []), -]; -let { stdout } = await $`pnpm version ${level} ${versionArgs}`; -const newVersion = stdout.slice(1).trim(); - -// Expose the new version to CI if needed. -if (process.env.CI) { - await $`echo "new_version=${newVersion}" >> $GITHUB_OUTPUT`; -} - -// Publish the package. -// This will also build the package before publishing (see prepublishOnly script). -await $`pnpm publish --no-git-checks --tag ${tag}`; - -// Commit the new version. -await $`git commit -am "Publish JS client v${newVersion}"`; - -// Tag the new version. -await $`git tag -a js@v${newVersion} -m "JS client v${newVersion}"`; diff --git a/scripts/client/publish-rust.mjs b/scripts/client/publish-rust.mjs deleted file mode 100644 index b7a9fa6..0000000 --- a/scripts/client/publish-rust.mjs +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env zx -import 'zx/globals'; -import { cliArguments, getCargo, workingDirectory } from '../utils.mjs'; - -const dryRun = argv['dry-run'] ?? false; -const [level] = cliArguments(); -if (!level) { - throw new Error('A version level — e.g. "path" — must be provided.'); -} - -// Go to the client directory and install the dependencies. -cd(path.join(workingDirectory, 'clients', 'rust')); - -// Publish the new version. -const releaseArgs = dryRun - ? [] - : ['--no-push', '--no-tag', '--no-confirm', '--execute']; -await $`cargo release ${level} ${releaseArgs}`; - -// Stop here if this is a dry run. -if (dryRun) { - process.exit(0); -} - -// Get the new version. -const newVersion = getCargo(path.join('clients', 'rust')).package.version; - -// Expose the new version to CI if needed. -if (process.env.CI) { - await $`echo "new_version=${newVersion}" >> $GITHUB_OUTPUT`; -} - -// Soft reset the last commit so we can create our own commit and tag. -await $`git reset --soft HEAD~1`; - -// Commit the new version. -await $`git commit -am "Publish Rust client v${newVersion}"`; - -// Tag the new version. -await $`git tag -a rust@v${newVersion} -m "Rust client v${newVersion}"`; diff --git a/scripts/client/test-js.mjs b/scripts/client/test-js.mjs deleted file mode 100644 index 652df0e..0000000 --- a/scripts/client/test-js.mjs +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env zx -import 'zx/globals'; -import { cliArguments, workingDirectory } from '../utils.mjs'; - -// Start the local validator, or restart it if it is already running. -await $`pnpm validator:restart`; - -// Build the client and run the tests. -cd(path.join(workingDirectory, 'clients', 'js')); -await $`pnpm install`; -await $`pnpm build`; -await $`pnpm test ${cliArguments()}`; diff --git a/scripts/client/test-rust.mjs b/scripts/client/test-rust.mjs deleted file mode 100644 index 699acb1..0000000 --- a/scripts/client/test-rust.mjs +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env zx -import 'zx/globals'; -import { cliArguments, workingDirectory } from '../utils.mjs'; - -// Configure additional arguments here, e.g.: -// ['--arg1', '--arg2', ...cliArguments()] -const testArgs = cliArguments(); - -const hasSolfmt = await which('solfmt', { nothrow: true }); -const sbfOutDir = path.join(workingDirectory, 'target', 'deploy'); - -// Run the tests. -cd(path.join(workingDirectory, 'clients', 'rust')); -if (hasSolfmt) { - await $`SBF_OUT_DIR=${sbfOutDir} cargo test --features "test-sbf" ${testArgs} 2>&1 | solfmt`; -} else { - await $`SBF_OUT_DIR=${sbfOutDir} cargo test --features "test-sbf" ${testArgs}`; -} diff --git a/scripts/conformance.sh b/scripts/conformance.sh new file mode 100755 index 0000000..8f5cb7e --- /dev/null +++ b/scripts/conformance.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash + +# Mollusk conformance testing of this Core BPF Config program against the +# version running on mainnet-beta. + +set -euo pipefail + +WORKDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" + +PROGRAM_ID="Config1111111111111111111111111111111111111" +PROGRAM_BINARY_PATH="$WORKDIR/target/deploy/solana_config_program.so" +BASE_BINARY_PATH="$WORKDIR/program/fuzz/program-mb-3-17-2025.so" +MOLLUSK_FIXTURES_PATH="$WORKDIR/program/fuzz/blob" + +# Test this program against the cloned program for conformance with Mollusk. +OUTPUT=$(mollusk run-test \ + --proto firedancer --ignore-compute-units \ + "$BASE_BINARY_PATH" "$PROGRAM_BINARY_PATH" \ + "$MOLLUSK_FIXTURES_PATH" "$PROGRAM_ID") + +# The last line of output should exactly match the following: +# [DONE][TEST RESULT]: 0 failures +if ! grep -q "\[DONE\]\[TEST RESULT\]: 0 failures" <<< "$OUTPUT"; then + echo "Error: mismatches detected." + exit 1 +fi + +echo "$OUTPUT" +echo "Conformance test passed." \ No newline at end of file diff --git a/scripts/generate-clients.mjs b/scripts/generate-clients.mjs deleted file mode 100644 index 0acc8d9..0000000 --- a/scripts/generate-clients.mjs +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env zx -import 'zx/globals'; -import { createFromRoot, deleteNodesVisitor } from 'codama'; -import { renderVisitor as renderJavaScriptVisitor } from '@codama/renderers-js'; -import { renderVisitor as renderRustVisitor } from '@codama/renderers-rust'; -import { getToolchainArgument, workingDirectory } from './utils.mjs'; - -// Instanciate Codama. -const codama = createFromRoot( - require(path.join(workingDirectory, 'program', 'idl.json')) -); - -// Render JavaScript. -const jsClient = path.join(__dirname, '..', 'clients', 'js'); -codama.accept( - renderJavaScriptVisitor(path.join(jsClient, 'src', 'generated'), { - prettier: require(path.join(jsClient, '.prettierrc.json')), - }) -); - -// FIXME: Currently, the Rust renderer fails to generate a `ShortVec` because -// it requires extra traits such as `BorshSerialize` that are not implemented -// on the `ShortVec` type. To work around this issue, we remove the `configKeys` -// type from Rust code generation and use a hooked type for it instead. -codama.update(deleteNodesVisitor(['[definedTypeNode]configKeys'])); - -// Render Rust. -const rustClient = path.join(__dirname, '..', 'clients', 'rust'); -codama.accept( - renderRustVisitor(path.join(rustClient, 'src', 'generated'), { - anchorTraits: false, - formatCode: true, - crateFolder: rustClient, - toolchain: getToolchainArgument('format'), - - // FIXME: The second part of the workaround for the `ShortVec` issue mentioned above. - linkOverrides: { - definedTypes: { configKeys: 'hooked' }, - }, - }) -); diff --git a/scripts/generate-idls.mjs b/scripts/generate-idls.mjs deleted file mode 100644 index faf2db8..0000000 --- a/scripts/generate-idls.mjs +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env zx -import 'zx/globals'; -import { generateIdl } from '@metaplex-foundation/shank-js'; -import { getCargo, getProgramFolders } from './utils.mjs'; - -const binaryInstallDir = path.join(__dirname, '..', '.cargo'); - -getProgramFolders().forEach((folder) => { - const cargo = getCargo(folder); - const isShank = Object.keys(cargo.dependencies).includes('shank'); - const programDir = path.join(__dirname, '..', folder); - - generateIdl({ - generator: isShank ? 'shank' : 'anchor', - programName: cargo.package.name.replace(/-/g, '_'), - programId: cargo.package.metadata.solana['program-id'], - idlDir: programDir, - idlName: 'idl', - programDir, - binaryInstallDir, - }); -}); diff --git a/scripts/link-solana-version.mjs b/scripts/link-solana-version.mjs deleted file mode 100644 index f92ae45..0000000 --- a/scripts/link-solana-version.mjs +++ /dev/null @@ -1,74 +0,0 @@ -#!/usr/bin/env zx -import 'zx/globals'; -import { getInstalledSolanaVersion, getSolanaVersion } from './utils.mjs'; - -const expectedVersion = getSolanaVersion(); -const installedVersion = await getInstalledSolanaVersion(); - -const installPath = path.join( - os.homedir(), - '.local', - 'share', - 'solana', - 'install' -); -const releasePath = path.join( - installPath, - 'releases', - expectedVersion, - 'solana-release' -); -const activeReleasePath = path.join(installPath, 'active_release'); -const hasRelease = await fs.exists(releasePath); - -if (!installedVersion) { - echo( - chalk.red('[ ERROR ]'), - `No Solana installation found. Solana ${expectedVersion} is required for this project.` - ); - await askToInstallSolana(expectedVersion); -} else if (installedVersion === expectedVersion) { - echo( - chalk.green('[ SUCCESS ]'), - `The expected Solana version ${expectedVersion} is installed.` - ); -} else if (hasRelease) { - await $`rm -f "${activeReleasePath}"`; - await $`ln -s "${releasePath}" "${activeReleasePath}"`; - echo( - chalk.green('[ SUCCESS ]'), - `Successfully switched from Solana version ${installedVersion} to ${expectedVersion} to match the project's requirements.` - ); -} else { - echo( - chalk.yellow('[ WARNING ]'), - `Cannot switch from Solana version ${installedVersion} to ${expectedVersion} because it is not installed.` - ); - await askToInstallSolana(expectedVersion); -} - -async function askToInstallSolana(version) { - const installRelease = await question('Should we install it now? [y/N] '); - if (installRelease === 'y') { - await installSolana(version); - echo( - chalk.green('[ SUCCESS ]'), - `Successfully installed Solana version ${version}.` - ); - } else { - process.exit(1); - } -} - -async function installSolana(version) { - echo(`Installing Solana ${version}...`); - const cutoff = '1.18.19'; - const isBeforeCutoff = - (await $`[[ "$(printf '%s\n' "${cutoff}" "${version}" | sort -V | head -n1)" = "${version}" ]] && [[ "${cutoff}" != "${version}" ]]`.quiet() - .exitCode) == 0; - if (isBeforeCutoff) { - await $`sh -c "$(curl -sSfL https://release.solana.com/v${version}/install)"`; - } else { - await $`sh -c "$(curl -sSfL https://release.anza.xyz/v${version}/install)"`; - } -} diff --git a/scripts/program/bench.mjs b/scripts/program/bench.mjs deleted file mode 100644 index 79d7d35..0000000 --- a/scripts/program/bench.mjs +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env zx -import 'zx/globals'; -import { - cliArguments, - getProgramFolders, - workingDirectory, -} from '../utils.mjs'; - -// Save external programs binaries to the output directory. -import './dump.mjs'; - -// Configure additional arguments here, e.g.: -// ['--arg1', '--arg2', ...cliArguments()] -const benchArgs = [ - '--features', - 'bpf-entrypoint', - ...cliArguments(), -]; - -const hasSolfmt = await which('solfmt', { nothrow: true }); - -// Test the programs. -await Promise.all( - getProgramFolders().map(async (folder) => { - const manifestPath = path.join(workingDirectory, folder, 'Cargo.toml'); - - if (hasSolfmt) { - await $`RUST_LOG=error cargo bench --manifest-path ${manifestPath} ${benchArgs} 2>&1 | solfmt`; - } else { - await $`RUST_LOG=error cargo bench --manifest-path ${manifestPath} ${benchArgs}`; - } - }) -); diff --git a/scripts/program/build.mjs b/scripts/program/build.mjs deleted file mode 100644 index 17cd5ab..0000000 --- a/scripts/program/build.mjs +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env zx -import 'zx/globals'; -import { - cliArguments, - getProgramFolders, - workingDirectory, -} from '../utils.mjs'; - -// Save external programs binaries to the output directory. -import './dump.mjs'; - -// Configure additional arguments here, e.g.: -// ['--arg1', '--arg2', ...cliArguments()] -const buildArgs = [ - '--features', - 'bpf-entrypoint', - ...cliArguments(), -]; - -// Build the programs. -for (const folder of getProgramFolders()) { - const manifestPath = path.join(workingDirectory, folder, 'Cargo.toml'); - - await $`cargo-build-sbf --manifest-path ${manifestPath} ${buildArgs}`; -} diff --git a/scripts/program/clean.mjs b/scripts/program/clean.mjs deleted file mode 100644 index b761a37..0000000 --- a/scripts/program/clean.mjs +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env zx -import 'zx/globals'; -import { getExternalProgramOutputDir } from '../utils.mjs'; - -// Remove the programs output directories. -const externalProgramOutput = getExternalProgramOutputDir(); -await $`rm -rf ${externalProgramOutput}`; - -// Remove the target directory. -await $`rm -rf target`; diff --git a/scripts/program/dump.mjs b/scripts/program/dump.mjs deleted file mode 100644 index 7e7db12..0000000 --- a/scripts/program/dump.mjs +++ /dev/null @@ -1,105 +0,0 @@ -#!/usr/bin/env zx -import 'zx/globals'; -import { - getExternalAccountAddresses, - getExternalProgramAddresses, - getExternalProgramOutputDir, -} from '../utils.mjs'; - -// Get input from environment variables. -const rpc = process.env.RPC ?? 'https://api.mainnet-beta.solana.com'; -const outputDir = getExternalProgramOutputDir(); -await dump(); - -/** Dump external programs binaries and accounts if needed. */ -async function dump() { - // Ensure we have some external accounts to dump. - const programs = getExternalProgramAddresses(); - const accounts = getExternalAccountAddresses(); - const external = [ - ...programs.map((program) => [program, 'so']), - ...accounts.map((account) => [account, 'json']), - ]; - - if (external.length === 0) return; - echo(`Dumping external accounts to '${outputDir}':`); - - // Create the output directory if needed. - $`mkdir -p ${outputDir}`.quiet(); - - // Copy the binaries from the chain or warn if they are different. - await Promise.all( - external.map(async ([address, extension]) => { - const binary = `${address}.${extension}`; - const hasBinary = await fs.exists(`${outputDir}/${binary}`); - - if (!hasBinary) { - await copyFromChain(address, extension); - echo(`Wrote account data to ${outputDir}/${binary}`); - return; - } - - let sha = 'sha256sum'; - let options = []; - let hasShaChecksum = await which('sha256sum', { nothrow: true }); - - // We might not have sha256sum on some systems, so we try shasum as well. - if (!hasShaChecksum) { - hasShaChecksum = await which('shasum', { nothrow: true }); - - if (hasShaChecksum) { - sha = 'shasum'; - options = ['-a', '256']; - } - } - - if (hasShaChecksum) { - try { - await copyFromChain(address, extension, 'onchain-'); - const [onChainHash, localHash] = await Promise.all([ - $`${sha} ${options} -b ${outputDir}/onchain-${binary} | cut -d ' ' -f 1`.quiet(), - $`${sha} ${options} -b ${outputDir}/${binary} | cut -d ' ' -f 1`.quiet(), - ]); - - if (onChainHash.toString() !== localHash.toString()) { - echo( - chalk.yellow('[ WARNING ]'), - `on-chain and local binaries are different for '${address}'` - ); - } else { - echo( - chalk.green('[ SKIPPED ]'), - `on-chain and local binaries are the same for '${address}'` - ); - } - - await $`rm ${outputDir}/onchain-${binary}`.quiet(); - } catch (error) { - echo( - chalk.yellow('[ WARNING ]'), - `skipped check for '${address}' (error copying data from '${rpc}')` - ); - } - } else { - echo( - chalk.yellow('[ WARNING ]'), - `skipped check for '${address}' (missing 'sha256sum' command)` - ); - } - }) - ); -} - -/** Helper function to copy external programs or accounts binaries from the chain. */ -async function copyFromChain(address, extension, prefix = '') { - const binary = `${prefix}${address}.${extension}`; - switch (extension) { - case 'json': - return $`solana account -u ${rpc} ${address} -o ${outputDir}/${binary} --output json >/dev/null`.quiet(); - case 'so': - return $`solana program dump -u ${rpc} ${address} ${outputDir}/${binary} >/dev/null`.quiet(); - default: - echo(chalk.red(`[ ERROR ] unknown account type for '${binary}'`)); - await $`exit 1`; - } -} diff --git a/scripts/program/format.mjs b/scripts/program/format.mjs deleted file mode 100644 index c73ddd4..0000000 --- a/scripts/program/format.mjs +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env zx -import 'zx/globals'; -import { - cliArguments, - getProgramFolders, - getToolchainArgument, - partitionArguments, - popArgument, - workingDirectory, -} from '../utils.mjs'; - -// Configure additional arguments here, e.g.: -// ['--arg1', '--arg2', ...cliArguments()] -const formatArgs = cliArguments(); - -const fix = popArgument(formatArgs, '--fix'); -const [cargoArgs, fmtArgs] = partitionArguments(formatArgs, '--'); -const toolchain = getToolchainArgument('format'); - -// Format the programs. -for (const folder of getProgramFolders()) { - const manifestPath = path.join(workingDirectory, folder, 'Cargo.toml'); - - if (fix) { - await $`cargo ${toolchain} fmt --manifest-path ${manifestPath} ${cargoArgs} -- ${fmtArgs}`; - } else { - await $`cargo ${toolchain} fmt --manifest-path ${manifestPath} ${cargoArgs} -- --check ${fmtArgs}`; - } -} diff --git a/scripts/program/lint.mjs b/scripts/program/lint.mjs deleted file mode 100644 index 0bdd306..0000000 --- a/scripts/program/lint.mjs +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env zx -import 'zx/globals'; -import { - cliArguments, - getProgramFolders, - getToolchainArgument, - popArgument, - workingDirectory, -} from '../utils.mjs'; - -// Configure additional arguments here, e.g.: -// ['--arg1', '--arg2', ...cliArguments()] -const lintArgs = [ - '-Zunstable-options', - '--all-targets', - '--all-features', - '--', - '--deny=warnings', - '--deny=clippy::arithmetic_side_effects', - ...cliArguments() -]; - -const fix = popArgument(lintArgs, '--fix'); -const toolchain = getToolchainArgument('lint'); - -// Lint the programs using clippy. -for (const folder of getProgramFolders()) { - const manifestPath = path.join(workingDirectory, folder, 'Cargo.toml'); - - if (fix) { - await $`cargo ${toolchain} clippy --manifest-path ${manifestPath} --fix ${lintArgs}`; - } else { - await $`cargo ${toolchain} clippy --manifest-path ${manifestPath} ${lintArgs}`; - } -} diff --git a/scripts/program/test.mjs b/scripts/program/test.mjs deleted file mode 100644 index 5e99774..0000000 --- a/scripts/program/test.mjs +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env zx -import 'zx/globals'; -import { - cliArguments, - getProgramFolders, - workingDirectory, -} from '../utils.mjs'; - -// Save external programs binaries to the output directory. -import './dump.mjs'; - -// Configure additional arguments here, e.g.: -// ['--arg1', '--arg2', ...cliArguments()] -const testArgs = [ - '--features', - 'bpf-entrypoint', - ...cliArguments(), -]; - -const hasSolfmt = await which('solfmt', { nothrow: true }); - -// Test the programs. -for (const folder of getProgramFolders()) { - const manifestPath = path.join(workingDirectory, folder, 'Cargo.toml'); - - if (hasSolfmt) { - await $`RUST_LOG=error cargo test-sbf --manifest-path ${manifestPath} ${testArgs} 2>&1 | solfmt`; - } else { - await $`RUST_LOG=error cargo test-sbf --manifest-path ${manifestPath} ${testArgs}`; - } -} diff --git a/scripts/publish-js.sh b/scripts/publish-js.sh new file mode 100755 index 0000000..1e6c712 --- /dev/null +++ b/scripts/publish-js.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash + +set -euo pipefail + +library_path="${1:-}" +level="${2:-}" +tag="${3:-latest}" +dry_run="${DRY_RUN:-false}" + +if [[ -z "$library_path" || -z "$level" ]]; then + echo "Usage: $0 [tag]" + echo "Example: $0 clients/js patch beta" + exit 1 +fi + +cd "$library_path" +pnpm install + +# Build version args +version_args=(--no-git-tag-version) +if [[ "$level" == pre* ]]; then + version_args+=(--preid "$tag") +fi + +# Bump version and capture new version +new_version=$(pnpm version "$level" "${version_args[@]}" | tail -n1 | sed 's/^v//;s/\r$//') + +# CI output +if [[ -n "${CI:-}" ]]; then + echo "new_version=${new_version}" >> "$GITHUB_OUTPUT" +fi + +# Publish package +pnpm publish --no-git-checks --tag "$tag" + +# Git commit and tag +git commit -am "Publish JS client v${new_version}" +git tag -a "js@v${new_version}" -m "JS client v${new_version}" \ No newline at end of file diff --git a/scripts/publish-rust.sh b/scripts/publish-rust.sh new file mode 100755 index 0000000..5fca83e --- /dev/null +++ b/scripts/publish-rust.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash + +set -euo pipefail + +library_path="${1:-}" +level="${2:-}" +dry_run="${DRY_RUN:-false}" + +if [[ -z "$library_path" || -z "$level" ]]; then + echo "Usage: $0 " + echo "Example: $0 clients/rust patch" + exit 1 +fi + +cd "$library_path" + +# Extract crate name using cargo metadata +metadata=$(cargo metadata --no-deps --format-version 1) +crate_name=$(echo "$metadata" | jq -r '.packages[0].name') + +# Run cargo-release +if [[ "$dry_run" != "true" ]]; then + cargo release "$level" --tag-name "${crate_name}@v{{version}}" --no-confirm --execute --dependent-version fix +else + cargo release "$level" + exit 0 +fi + +# CI output +if [[ -n "${CI:-}" ]]; then + metadata=$(cargo metadata --no-deps --format-version 1) + new_version=$(echo "$metadata" | jq -r '.packages[0].version') + echo "new_version=${new_version}" >> "$GITHUB_OUTPUT" +fi diff --git a/scripts/restart-test-validator.sh b/scripts/restart-test-validator.sh new file mode 100755 index 0000000..8357eee --- /dev/null +++ b/scripts/restart-test-validator.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash + +PORT=8899 +LOG_FILE="./test-ledger/validator.log" + +PID=$(lsof -t -i:$PORT) + +if [ -n "$PID" ]; then + echo "Detected test validator running on PID $PID. Restarting..." + kill "$PID" + sleep 1 +fi + +echo "Starting Solana test validator..." +solana-test-validator > /dev/null 2>&1 & +VALIDATOR_PID=$! + +# Wait for test validator to move past slot 0. +echo -n "Waiting for validator to stabilize" +for i in {1..8}; do + if ! kill -0 "$VALIDATOR_PID" 2>/dev/null; then + echo -e "\nTest validator exited early." + exit 1 + fi + + SLOT=$(solana slot -ul 2>/dev/null) + if [[ "$SLOT" =~ ^[0-9]+$ ]] && [ "$SLOT" -gt 0 ]; then + echo -e "\nTest validator is ready. Slot: $SLOT" + exit 0 + fi + + echo -n "." + sleep 1 +done + +echo -e "\nTimed out waiting for test validator to stabilize." +exit 1 \ No newline at end of file diff --git a/scripts/start-validator.mjs b/scripts/start-validator.mjs deleted file mode 100644 index 1adbcab..0000000 --- a/scripts/start-validator.mjs +++ /dev/null @@ -1,125 +0,0 @@ -#!/usr/bin/env zx -import { spawn } from 'node:child_process'; -import fs from 'node:fs'; -import 'zx/globals'; -import { - getCargo, - getExternalAccountAddresses, - getExternalProgramAddresses, - getExternalProgramOutputDir, - getProgramFolders, -} from './utils.mjs'; - -// Check Solana version. -await $`pnpm solana:check`; - -// Options and arguments. -const restart = argv['restart']; - -// Keep the validator running when not using the restart flag. -const isValidatorRunning = (await $`lsof -t -i:8899`.quiet().exitCode) === 0; -if (!restart && isValidatorRunning) { - echo(chalk.yellow('Local validator is already running.')); - process.exit(); -} - -// Initial message. -const verb = isValidatorRunning ? 'Restarting' : 'Starting'; - -// Get programs and accounts. -const programs = [...getPrograms(), ...getExternalPrograms()]; -const programPluralized = programs.length === 1 ? 'program' : 'programs'; -const accounts = [...getExternalAccounts()]; -const accountsPluralized = accounts.length === 1 ? 'account' : 'accounts'; - -echo( - `${verb} local validator with ${programs.length} custom ${programPluralized}` + - (accounts.length > 0 - ? ` and ${accounts.length} external ${accountsPluralized}...` - : `...`) -); - -// Kill the validator if it's already running. -if (isValidatorRunning) { - await $`pkill -f solana-test-validator`.quiet(); - await sleep(1000); -} - -// Global validator arguments. -const args = [/* Reset ledger */ '-r']; - -// Load programs. -programs.forEach(({ programId, deployPath }) => { - args.push(/* Load BPF program */ '--bpf-program', programId, deployPath); -}); - -// Load accounts. -accounts.forEach(({ account, deployPath }) => { - args.push(/* Load account */ '--account', account, deployPath); -}); - -// Start the validator in detached mode. -const cliLogs = path.join(os.tmpdir(), 'validator-cli.log'); -fs.writeFileSync(cliLogs, '', () => {}); -const out = fs.openSync(cliLogs, 'a'); -const err = fs.openSync(cliLogs, 'a'); -const validator = spawn('solana-test-validator', args, { - detached: true, - stdio: ['ignore', out, err], -}); -validator.unref(); - -// Wait for the validator to stabilize. -const waitForValidator = spinner( - 'Waiting for local validator to stabilize...', - () => - new Promise((resolve, reject) => { - setInterval(() => { - const logs = fs.readFileSync(cliLogs, 'utf8'); - if (validator.exitCode !== null) { - reject(logs); - } else if (logs.includes('Confirmed Slot: 1')) { - resolve(); - } - }, 1000); - }) -); - -try { - await waitForValidator; - echo(chalk.green('Local validator is up and running!')); -} catch (error) { - echo(error); - echo(chalk.red('Could not start local validator.')); -} finally { - fs.rmSync(cliLogs); - process.exit(); -} - -function getPrograms() { - const binaryDir = path.join(__dirname, '..', 'target', 'deploy'); - return getProgramFolders().map((folder) => { - const cargo = getCargo(folder); - const name = cargo.package.name.replace(/-/g, '_'); - return { - programId: cargo.package.metadata.solana['program-id'], - deployPath: path.join(binaryDir, `${name}.so`), - }; - }); -} - -function getExternalPrograms() { - const binaryDir = getExternalProgramOutputDir(); - return getExternalProgramAddresses().map((address) => ({ - programId: address, - deployPath: path.join(binaryDir, `${address}.so`), - })); -} - -function getExternalAccounts() { - const binaryDir = getExternalProgramOutputDir(); - return getExternalAccountAddresses().map((address) => ({ - account: address, - deployPath: path.join(binaryDir, `${address}.json`), - })); -} diff --git a/scripts/stop-test-validator.sh b/scripts/stop-test-validator.sh new file mode 100755 index 0000000..c0d6762 --- /dev/null +++ b/scripts/stop-test-validator.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +if lsof -t -i:8899 > /dev/null; then + echo "Stopping test validator..." + pkill -f solana-test-validator + sleep 1 + echo "Test validator terminated." +else + echo "Test validator is not running." +fi \ No newline at end of file diff --git a/scripts/stop-validator.mjs b/scripts/stop-validator.mjs deleted file mode 100644 index ebbff8d..0000000 --- a/scripts/stop-validator.mjs +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env zx -import 'zx/globals'; - -const isValidatorRunning = (await $`lsof -t -i:8899`.quiet().exitCode) === 0; - -if (isValidatorRunning) { - // Kill the validator if it's already running. - await $`pkill -f solana-test-validator`.quiet(); - await sleep(1000); - echo(chalk.green('Local validator terminated!')); -} else { - echo(chalk.yellow('Local validator is not running.')); -} diff --git a/scripts/upgrade-template.mjs b/scripts/upgrade-template.mjs deleted file mode 100644 index 2d1833c..0000000 --- a/scripts/upgrade-template.mjs +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/env zx -import "zx/globals"; -import { getCargo } from "./utils.mjs"; - -// Arguments to pass to the `create-solana-program` command. -const rustClientCargo = getCargo(path.join("clients", "rust")); -const jsClientPkg = require( - path.join(__dirname, "..", "clients", "js", "package.json") -); -const templateArgs = [ - "config", - "--address", - "Config1111111111111111111111111111111111111", - "--org", - "solana-program", - "--rust-client-crate-name", - rustClientCargo.package.name, - "--js-client-package-name", - jsClientPkg.name, - "--default", - "--force", -]; - -// File and folder patterns that should not be overwritten by the template upgrade. -const unchangedGlobs = [ - "clients/**/src/**", - "clients/**/src/*", - "program/**/*", - "program/*", - "scripts/generate-clients.mjs", - "scripts/generate-idls.mjs", - "Cargo.lock", - "**/pnpm-lock.yaml", - "pnpm-lock.yaml", -]; - -// Prevent CLI arguments from being escaped. -$.quote = (command) => command; - -// Re-generate the repo from the parent directory. -cd(".."); -await $`pnpm create solana-program@latest ${templateArgs}`; - -// Go back inside the updated repo. -cd("config"); - -// Restore files and folders that should not be overwritten. -await $`git add --all`; -for (const glob of unchangedGlobs) { - await $`git restore --worktree --staged "${glob}"`; -} - -// Re-install dependencies. -await $`pnpm install`; \ No newline at end of file diff --git a/scripts/utils.mjs b/scripts/utils.mjs deleted file mode 100644 index 77bba9a..0000000 --- a/scripts/utils.mjs +++ /dev/null @@ -1,147 +0,0 @@ -import 'zx/globals'; -import { parse as parseToml } from '@iarna/toml'; - -process.env.FORCE_COLOR = 3; -process.env.CARGO_TERM_COLOR = 'always'; - -export const workingDirectory = (await $`pwd`.quiet()).toString().trim(); - -export function getAllProgramIdls() { - return getAllProgramFolders().map((folder) => - path.join(workingDirectory, folder, 'idl.json') - ); -} - -export function getExternalProgramOutputDir() { - const config = getCargoMetadata()?.solana?.['external-programs-output']; - return path.join(workingDirectory, config ?? 'target/deploy'); -} - -export function getExternalProgramAddresses() { - const addresses = getProgramFolders().flatMap( - (folder) => getCargoMetadata(folder)?.solana?.['program-dependencies'] ?? [] - ); - return Array.from(new Set(addresses)); -} - -export function getExternalAccountAddresses() { - const addresses = getProgramFolders().flatMap( - (folder) => getCargoMetadata(folder)?.solana?.['account-dependencies'] ?? [] - ); - return Array.from(new Set(addresses)); -} - -let didWarnAboutMissingPrograms = false; -export function getProgramFolders() { - let programs; - - if (process.env.PROGRAMS) { - try { - programs = JSON.parse(process.env.PROGRAMS); - } catch (error) { - programs = process.env.PROGRAMS.split(/\s+/); - } - } else { - programs = getAllProgramFolders(); - } - - const filteredPrograms = programs.filter((program) => - fs.existsSync(path.join(workingDirectory, program)) - ); - - if ( - filteredPrograms.length !== programs.length && - !didWarnAboutMissingPrograms - ) { - didWarnAboutMissingPrograms = true; - programs - .filter((program) => !filteredPrograms.includes(program)) - .forEach((program) => { - echo(chalk.yellow(`Program not found: ${workingDirectory}/${program}`)); - }); - } - - return filteredPrograms; -} - -export function getAllProgramFolders() { - return getCargo().workspace.members.filter((member) => - (getCargo(member).lib?.['crate-type'] ?? []).includes('cdylib') - ); -} - -export function getProgramId(folder) { - return getCargoMetadata(folder)?.solana?.['program-id']; -} - -export function getProgramName(folder) { - return getCargo(folder).package?.name; -} - -export function getProgramSharedObjectName(folder) { - return `${getProgramName(folder).replace(/-/g, '_')}.so`; -} - -export function getProgramSharedObjectPath(folder) { - return path.join( - workingDirectory, - 'target', - 'deploy', - getProgramSharedObjectName(folder), - ); -} - -export function getCargo(folder) { - return parseToml( - fs.readFileSync( - path.join(workingDirectory, folder ? folder : '.', 'Cargo.toml'), - 'utf8' - ) - ); -} - -export function getCargoMetadata(folder) { - const cargo = getCargo(folder); - return folder ? cargo?.package?.metadata : cargo?.workspace?.metadata; -} - -export function getSolanaVersion() { - return getCargoMetadata()?.cli?.solana; -} - -export function getToolchain(operation) { - return getCargoMetadata()?.toolchains?.[operation]; -} - -export function getToolchainArgument(operation) { - const channel = getToolchain(operation); - return channel ? `+${channel}` : ''; -} - -export function cliArguments() { - return process.argv.slice(3); -} - -export function popArgument(args, arg) { - const index = args.indexOf(arg); - if (index >= 0) { - args.splice(index, 1); - } - return index >= 0; -} - -export function partitionArguments(args, delimiter) { - const index = args.indexOf(delimiter); - return index >= 0 - ? [args.slice(0, index), args.slice(index + 1)] - : [args, []]; -} - -export async function getInstalledSolanaVersion() { - try { - const { stdout } = await $`solana --version`.quiet(); - return stdout.match(/(\d+\.\d+\.\d+)/)?.[1]; - } catch (error) { - return ''; - } -} diff --git a/vars.env b/vars.env new file mode 100644 index 0000000..d375dea --- /dev/null +++ b/vars.env @@ -0,0 +1,2 @@ +RUST_TOOLCHAIN_NIGHTLY="nightly-2024-11-22" +SOLANA_CLI_VERSION="2.2.0" \ No newline at end of file