diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml deleted file mode 100644 index 57a094c..0000000 --- a/.github/actions/setup/action.yml +++ /dev/null @@ -1,103 +0,0 @@ -name: Setup environment - -inputs: - cargo-cache-key: - description: The key to cache cargo dependencies. Skips cargo caching if not provided. - required: false - cargo-cache-fallback-key: - description: The fallback key to use when caching cargo dependencies. Default to not using a fallback key. - required: false - 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`. - required: false - solana: - description: Install Solana if `true`. Defaults to `false`. - required: false - -runs: - using: 'composite' - steps: - - name: Setup pnpm - uses: pnpm/action-setup@v3 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: 24 - cache: 'pnpm' - - - name: Install Dependencies - run: pnpm install --frozen-lockfile - shell: bash - - - name: Set Environment Variables - shell: bash - run: pnpm zx ./scripts/ci/set-env.mjs - - - name: Install Rustfmt - if: ${{ inputs.rustfmt == 'true' }} - uses: dtolnay/rust-toolchain@master - with: - toolchain: ${{ env.TOOLCHAIN_FORMAT }} - components: rustfmt - - - name: Install Clippy - if: ${{ inputs.clippy == 'true' }} - uses: dtolnay/rust-toolchain@master - with: - toolchain: ${{ env.TOOLCHAIN_LINT }} - components: clippy - - - name: Install Solana - if: ${{ inputs.solana == 'true' }} - uses: solana-program/actions/install-solana@v1 - with: - version: ${{ env.SOLANA_VERSION }} - cache: true - - - name: Cache Cargo Dependencies - if: ${{ inputs.cargo-cache-key && !inputs.cargo-cache-fallback-key }} - uses: actions/cache@v4 - with: - path: | - ~/.cargo/bin/ - ~/.cargo/registry/index/ - ~/.cargo/registry/cache/ - ~/.cargo/git/db/ - target/ - key: ${{ runner.os }}-${{ inputs.cargo-cache-key }}-${{ hashFiles('**/Cargo.lock') }} - restore-keys: ${{ runner.os }}-${{ inputs.cargo-cache-key }} - - - name: Cache Cargo Dependencies With Fallback - if: ${{ inputs.cargo-cache-key && inputs.cargo-cache-fallback-key }} - uses: actions/cache@v4 - with: - path: | - ~/.cargo/bin/ - ~/.cargo/registry/index/ - ~/.cargo/registry/cache/ - ~/.cargo/git/db/ - target/ - key: ${{ runner.os }}-${{ inputs.cargo-cache-key }}-${{ hashFiles('**/Cargo.lock') }} - restore-keys: | - ${{ runner.os }}-${{ inputs.cargo-cache-key }} - ${{ runner.os }}-${{ inputs.cargo-cache-fallback-key }}-${{ hashFiles('**/Cargo.lock') }} - ${{ runner.os }}-${{ inputs.cargo-cache-fallback-key }} - - - name: Cache Local Cargo Dependencies - if: ${{ inputs.cargo-cache-local-key }} - uses: actions/cache@v4 - with: - path: | - .cargo/bin/ - .cargo/registry/index/ - .cargo/registry/cache/ - .cargo/git/db/ - key: ${{ runner.os }}-${{ inputs.cargo-cache-local-key }}-${{ hashFiles('**/Cargo.lock') }} - restore-keys: ${{ runner.os }}-${{ inputs.cargo-cache-local-key }} diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c40b848..826bb0b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -5,194 +5,45 @@ on: branches: [main] pull_request: -jobs: - audit_rust: - name: Audit Rust - runs-on: ubuntu-latest - steps: - - name: Git Checkout - uses: actions/checkout@v4 - - - name: Setup Environment - uses: ./.github/actions/setup - with: - cargo-cache-key: cargo-audit - - - name: Install cargo-audit - uses: taiki-e/install-action@v2 - with: - tool: cargo-audit - - - name: Run cargo-audit - run: pnpm rust:audit - - spellcheck_rust: - name: Spellcheck Rust - runs-on: ubuntu-latest - steps: - - name: Git Checkout - uses: actions/checkout@v4 - - - name: Setup Environment - uses: ./.github/actions/setup - with: - cargo-cache-key: cargo-spellcheck - - - name: Install cargo-spellcheck - uses: taiki-e/install-action@v2 - with: - tool: cargo-spellcheck - - - name: Run cargo-spellcheck - run: pnpm rust:spellcheck - - format_and_lint_programs: - name: Format & Lint Programs - runs-on: ubuntu-latest - steps: - - name: Git Checkout - uses: actions/checkout@v4 - - - name: Setup Environment - uses: ./.github/actions/setup - with: - clippy: true - rustfmt: true - - - name: Format Programs - run: pnpm programs:format - - - name: Lint Programs - run: pnpm programs:lint +env: + JS_PACKAGES: "['clients-js']" + RUST_PACKAGES: "['clients-rust', 'program']" + SBPF_PROGRAM_PACKAGES: "['program']" - format_and_lint_client_js: - name: Format & Lint Client JS - runs-on: ubuntu-latest - steps: - - name: Git Checkout - uses: actions/checkout@v4 - - - name: Setup Environment - uses: ./.github/actions/setup - - - name: Format Client JS - run: pnpm clients:js:format - - - name: Lint Client JS - run: pnpm clients:js:lint - - format_and_lint_client_rust: - name: Format & Lint Client Rust - runs-on: ubuntu-latest - steps: - - name: Git Checkout - uses: actions/checkout@v4 - - - name: Setup Environment - uses: ./.github/actions/setup - with: - clippy: true - rustfmt: true - - - name: Format Client Rust - run: pnpm clients:rust:format - - - name: Lint Client Rust - run: pnpm clients:rust:lint - - build_programs: - name: Build programs - runs-on: ubuntu-latest - steps: - - name: Git Checkout - uses: actions/checkout@v4 - - - name: Setup Environment - uses: ./.github/actions/setup - with: - cargo-cache-key: cargo-programs - solana: true - - - name: Build Programs - run: pnpm programs:build - - - name: Upload Program Builds - uses: actions/upload-artifact@v4 - with: - name: program-builds - path: ./target/deploy/*.so - if-no-files-found: error - - - name: Save Client Artifacts - uses: actions/cache/save@v4 - with: - path: | - ./**/*.so - ./target/deploy/*.json - key: ${{ runner.os }}-builds-${{ github.sha }} - - test_programs: - name: Test Programs - runs-on: ubuntu-latest - needs: build_programs - steps: - - name: Git Checkout - uses: actions/checkout@v4 - - - name: Setup Environment - uses: ./.github/actions/setup - with: - cargo-cache-key: cargo-program-tests - cargo-cache-fallback-key: cargo-programs - solana: true - - - name: Restore Program Builds - uses: actions/cache/restore@v4 - with: - path: ./**/*.so - key: ${{ runner.os }}-builds-${{ github.sha }} - - - name: Test Programs - run: RUST_LOG=error pnpm programs:test - - generate_clients: - name: Check Client Generation +jobs: + set_env: + name: Set variables to be used in strategy definitions in reusable workflow runs-on: ubuntu-latest + outputs: + JS_PACKAGES: ${{ steps.compute.outputs.JS_PACKAGES }} + SBPF_PROGRAM_PACKAGES: ${{ steps.compute.outputs.SBPF_PROGRAM_PACKAGES }} + RUST_PACKAGES: ${{ steps.compute.outputs.RUST_PACKAGES }} + RUST_TOOLCHAIN_NIGHTLY: ${{ steps.compute.outputs.RUST_TOOLCHAIN_NIGHTLY }} + SOLANA_CLI_VERSION: ${{ steps.compute.outputs.SOLANA_CLI_VERSION }} steps: - name: Git Checkout uses: actions/checkout@v4 - name: Setup Environment - uses: ./.github/actions/setup - with: - rustfmt: true - - - name: Generate Clients - run: pnpm generate:clients + uses: solana-program/actions/setup-ubuntu@main - - name: Check Working Directory + - name: Compute variables + id: compute + shell: bash run: | - git status --porcelain - test -z "$(git status --porcelain)" - - test_client_js: - name: Test Client JS - runs-on: ubuntu-latest - needs: build_programs - steps: - - name: Git Checkout - uses: actions/checkout@v4 - - - name: Setup Environment - uses: ./.github/actions/setup - - - name: Restore Client Artifacts - uses: actions/cache/restore@v4 - with: - path: | - ./**/*.so - ./target/deploy/*.json - key: ${{ runner.os }}-builds-${{ github.sha }} - - - name: Test Client JS - run: pnpm clients:js:test + echo "JS_PACKAGES=${{ env.JS_PACKAGES }}" >> $GITHUB_OUTPUT + echo "SBPF_PROGRAM_PACKAGES=${{ env.SBPF_PROGRAM_PACKAGES }}" >> $GITHUB_OUTPUT + echo "RUST_PACKAGES=${{ env.RUST_PACKAGES }}" >> $GITHUB_OUTPUT + echo "RUST_TOOLCHAIN_NIGHTLY=$(make rust-toolchain-nightly)" >> "$GITHUB_OUTPUT" + echo "SOLANA_CLI_VERSION=$(make solana-cli-version)" >> "$GITHUB_OUTPUT" + + main: + needs: set_env + uses: solana-program/actions/.github/workflows/main.yml@main + with: + js-packages: ${{ needs.set_env.outputs.JS_PACKAGES }} + sbpf-program-packages: ${{ needs.set_env.outputs.SBPF_PROGRAM_PACKAGES }} + rust-packages: ${{ needs.set_env.outputs.RUST_PACKAGES }} + rustfmt-toolchain: ${{ needs.set_env.outputs.RUST_TOOLCHAIN_NIGHTLY }} + clippy-toolchain: ${{ needs.set_env.outputs.RUST_TOOLCHAIN_NIGHTLY }} + solana-cli-version: ${{ needs.set_env.outputs.SOLANA_CLI_VERSION }} diff --git a/.github/workflows/publish-js-client.yml b/.github/workflows/publish-js-client.yml deleted file mode 100644 index 605d093..0000000 --- a/.github/workflows/publish-js-client.yml +++ /dev/null @@ -1,101 +0,0 @@ -name: Publish JS Client - -on: - workflow_dispatch: - inputs: - level: - description: Version level - required: true - default: patch - type: choice - options: - - patch - - minor - - major - - prerelease - - prepatch - - preminor - - premajor - tag: - description: NPM Tag (and preid for pre-releases) - required: true - type: string - default: latest - create_release: - description: Create a GitHub release - required: true - type: boolean - default: true - -jobs: - test_js: - name: Test JS client - runs-on: ubuntu-latest - steps: - - name: Git Checkout - uses: actions/checkout@v4 - - - 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: Lint JS Client - run: pnpm clients:js:lint - - - name: Build Programs - run: pnpm programs:build - - - name: Test JS Client - run: pnpm clients:js:test - - publish_js: - name: Publish JS client - runs-on: ubuntu-latest - needs: test_js - permissions: - contents: write - steps: - - name: Git Checkout - uses: actions/checkout@v4 - with: - token: ${{ secrets.ANZA_TEAM_PAT }} - - - name: Setup Environment - uses: ./.github/actions/setup - - - name: Ensure SOLANA_PROGRAM_NPM_TOKEN variable is set - env: - token: ${{ secrets.SOLANA_PROGRAM_NPM_TOKEN }} - if: ${{ env.token == '' }} - run: | - echo "The SOLANA_PROGRAM_NPM_TOKEN secret variable is not set" - echo "Go to \"Settings\" -> \"Secrets and variables\" -> \"Actions\" -> \"New repository secret\"." - exit 1 - - - name: NPM Authentication - run: pnpm config set '//registry.npmjs.org/:_authToken' "${NODE_AUTH_TOKEN}" - env: - NODE_AUTH_TOKEN: ${{ secrets.SOLANA_PROGRAM_NPM_TOKEN }} - - - name: Set Git Author - run: | - git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" - git config --global user.name "github-actions[bot]" - - - name: Publish JS Client - id: publish - run: pnpm clients:js:publish ${{ inputs.level }} ${{ inputs.tag }} - - - name: Push Commit and Tag - run: git push origin --follow-tags - - - name: Create GitHub release - if: github.event.inputs.create_release == 'true' - uses: ncipollo/release-action@v1 - with: - tag: js@v${{ steps.publish.outputs.new_version }} diff --git a/.github/workflows/publish-js.yml b/.github/workflows/publish-js.yml new file mode 100644 index 0000000..f677564 --- /dev/null +++ b/.github/workflows/publish-js.yml @@ -0,0 +1,67 @@ +name: Publish JS + +on: + workflow_dispatch: + inputs: + package-path: + description: Path to directory with package to release + required: true + default: 'clients/js' + type: choice + options: + - clients/js + level: + description: Version level + required: true + default: patch + type: choice + options: + - patch + - minor + - major + - prerelease + - prepatch + - preminor + - premajor + tag: + description: NPM Tag (and preid for pre-releases) + required: true + type: string + default: latest + create-release: + description: Create a GitHub release + required: true + type: boolean + default: true + +jobs: + set_env: + name: Set variables to be used in strategy definitions + runs-on: ubuntu-latest + outputs: + SOLANA_CLI_VERSION: ${{ steps.compute.outputs.SOLANA_CLI_VERSION }} + TARGET: ${{ steps.compute.outputs.TARGET }} + steps: + - name: Git Checkout + uses: actions/checkout@v4 + + - name: Compute variables + id: compute + shell: bash + run: | + echo "SOLANA_CLI_VERSION=$(make solana-cli-version)" >> "$GITHUB_OUTPUT" + TARGET=$(echo ${{ inputs.package-path }} | sed 's#/#-#') + echo "TARGET=$TARGET" >> "$GITHUB_OUTPUT" + + main: + needs: set_env + uses: solana-program/actions/.github/workflows/publish-js.yml@main + with: + sbpf-program-packages: "program" + solana-cli-version: ${{ needs.set_env.outputs.SOLANA_CLI_VERSION }} + target: ${{ needs.set_env.outputs.TARGET }} + package-path: ${{ inputs['package-path'] }} + level: ${{ inputs.level }} + tag: ${{ inputs.tag }} + create-release: ${{ inputs['create-release'] }} + secrets: inherit diff --git a/.github/workflows/publish-rust-client.yml b/.github/workflows/publish-rust-client.yml deleted file mode 100644 index 2968406..0000000 --- a/.github/workflows/publish-rust-client.yml +++ /dev/null @@ -1,127 +0,0 @@ -name: Publish Rust Client - -on: - workflow_dispatch: - inputs: - level: - description: Level - required: true - default: patch - type: choice - options: - - patch - - minor - - major - - rc - - beta - - alpha - - release - - version - version: - description: Version - required: false - type: string - dry_run: - description: Dry run - required: true - default: true - type: boolean - create_release: - description: Create a GitHub release - required: true - type: boolean - default: true - -jobs: - test_rust: - name: Test Rust client - runs-on: ubuntu-latest - steps: - - name: Git Checkout - uses: actions/checkout@v4 - - - name: Setup Environment - uses: ./.github/actions/setup - with: - cargo-cache-key: cargo-rust-client - clippy: true - rustfmt: true - solana: true - - - name: Format Rust Client - run: pnpm clients:rust:format - - - name: Lint Rust Client - run: pnpm clients:rust:lint - - - name: Build Programs - run: pnpm programs:build - - - name: Test Rust Client - run: pnpm clients:rust:test - - publish_rust: - name: Publish Rust Client - runs-on: ubuntu-latest - needs: test_rust - permissions: - contents: write - steps: - - name: Git Checkout - uses: actions/checkout@v4 - with: - token: ${{ secrets.ANZA_TEAM_PAT }} - - - name: Setup Environment - uses: ./.github/actions/setup - with: - cargo-cache-key: cargo-publish-rust-client - cargo-cache-fallback-key: cargo-rust-client - clippy: true - rustfmt: true - - - name: Install Cargo Release - run: which cargo-release || cargo install cargo-release - - - name: Ensure CARGO_REGISTRY_TOKEN variable is set - env: - token: ${{ secrets.CARGO_REGISTRY_TOKEN }} - if: ${{ env.token == '' }} - run: | - echo "The CARGO_REGISTRY_TOKEN secret variable is not set" - echo "Go to \"Settings\" -> \"Secrets and variables\" -> \"Actions\" -> \"New repository secret\"." - exit 1 - - - name: Set Git Author - run: | - 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 - id: publish - env: - CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} - run: | - if [ "${{ inputs.level }}" == "version" ]; then - LEVEL=${{ inputs.version }} - else - LEVEL=${{ inputs.level }} - fi - - if [ "${{ inputs.dry_run }}" == "true" ]; then - OPTIONS="--dry-run" - else - 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 - - - name: Create GitHub release - if: github.event.inputs.create_release == 'true' && github.event.inputs.dry_run != 'true' - uses: ncipollo/release-action@v1 - with: - tag: rust@v${{ steps.publish.outputs.new_version }} diff --git a/.github/workflows/publish-rust.yml b/.github/workflows/publish-rust.yml new file mode 100644 index 0000000..0906c41 --- /dev/null +++ b/.github/workflows/publish-rust.yml @@ -0,0 +1,77 @@ +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 + level: + description: Level + required: true + default: patch + type: choice + options: + - patch + - minor + - major + - rc + - beta + - alpha + - release + - version + version: + description: Version (used with level "version") + required: false + type: string + dry-run: + description: Dry run + required: true + default: true + type: boolean + create-release: + description: Create a GitHub release + required: true + type: boolean + default: true + +jobs: + set_env: + name: Set variables to be used in strategy definitions + runs-on: ubuntu-latest + outputs: + RUST_TOOLCHAIN_NIGHTLY: ${{ steps.compute.outputs.RUST_TOOLCHAIN_NIGHTLY }} + SOLANA_CLI_VERSION: ${{ steps.compute.outputs.SOLANA_CLI_VERSION }} + TARGET: ${{ steps.compute.outputs.TARGET }} + steps: + - name: Git Checkout + uses: actions/checkout@v4 + + - name: Compute variables + id: compute + shell: bash + run: | + echo "RUST_TOOLCHAIN_NIGHTLY=$(make rust-toolchain-nightly)" >> "$GITHUB_OUTPUT" + echo "SOLANA_CLI_VERSION=$(make solana-cli-version)" >> "$GITHUB_OUTPUT" + TARGET=$(echo ${{ inputs['package-path'] }} | sed 's#/#-#') + echo "TARGET=$TARGET" >> "$GITHUB_OUTPUT" + + main: + needs: set_env + uses: solana-program/actions/.github/workflows/publish-rust.yml@main + with: + sbpf-program-packages: "program" + solana-cli-version: ${{ needs.set_env.outputs.SOLANA_CLI_VERSION }} + clippy-toolchain: ${{ needs.set_env.outputs.RUST_TOOLCHAIN_NIGHTLY }} + rustfmt-toolchain: ${{ needs.set_env.outputs.RUST_TOOLCHAIN_NIGHTLY }} + target: ${{ needs.set_env.outputs.TARGET }} + package-path: ${{ inputs['package-path'] }} + level: ${{ inputs.level }} + version: ${{ inputs.version }} + create-release: ${{ inputs['create-release'] }} + dry-run: ${{ inputs['dry-run'] }} + secrets: inherit diff --git a/Cargo.toml b/Cargo.toml index 662a7dd..6130308 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,9 +5,5 @@ members = ["program", "clients/rust"] [workspace.metadata.cli] solana = "3.1.14" -[workspace.metadata.toolchains] -format = "nightly-2026-01-22" -lint = "nightly-2026-01-22" - [workspace.metadata.spellcheck] config = "scripts/spellcheck.toml" diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..c8fe346 --- /dev/null +++ b/Makefile @@ -0,0 +1,102 @@ +RUST_TOOLCHAIN_NIGHTLY = nightly-2026-01-22 +SOLANA_CLI_VERSION = $(shell toml get ./Cargo.toml workspace.metadata.cli.solana) + +nightly = +${RUST_TOOLCHAIN_NIGHTLY} + +# This is a bit tricky -- findstring returns the found string, so we're looking +# for "directory-", returning that, and replacing "-" with "/" to change the +# first "-" to a "/". But if it isn't found, we replace "" with "", which works +# in the case where there is no subdirectory. +pattern-dir = $(firstword $(subst -, ,$1)) +find-pattern-dir = $(findstring $(call pattern-dir,$1)-,$1) +make-path = $(subst $(call find-pattern-dir,$1),$(subst -,/,$(call find-pattern-dir,$1)),$1) + +rust-toolchain-nightly: + @echo ${RUST_TOOLCHAIN_NIGHTLY} + +solana-cli-version: + @echo ${SOLANA_CLI_VERSION} + +cargo-nightly: + cargo $(nightly) $(ARGS) + +audit: + cargo audit \ + --ignore RUSTSEC-2022-0093 \ + --ignore RUSTSEC-2024-0344 \ + --ignore RUSTSEC-2024-0376 \ + --ignore RUSTSEC-2026-0009 \ + --ignore RUSTSEC-2026-0037 \ + --ignore RUSTSEC-2026-0049 \ + --ignore RUSTSEC-2026-0098 \ + --ignore RUSTSEC-2026-0099 \ + --ignore RUSTSEC-2026-0104 \ + $(ARGS) + +spellcheck: + cargo spellcheck --code 1 $(ARGS) + +clippy-%: + cargo $(nightly) clippy --manifest-path $(call make-path,$*)/Cargo.toml \ + --all-targets \ + --all-features \ + -- \ + --deny=warnings \ + --deny=clippy::arithmetic_side_effects $(ARGS) + +format-check-js-%: + cd $(call make-path,$*) && pnpm install && pnpm format $(ARGS) + +format-check-%: + cargo $(nightly) fmt --check --manifest-path $(call make-path,$*)/Cargo.toml $(ARGS) + +powerset-%: + cargo $(nightly) hack check --feature-powerset --all-targets --manifest-path $(call make-path,$*)/Cargo.toml $(ARGS) + +format-rust: + cargo $(nightly) fmt --all $(ARGS) + +build-sbf-%: + cargo build-sbf --manifest-path $(call make-path,$*)/Cargo.toml $(ARGS) + +build-doc-%: + RUSTDOCFLAGS="--cfg docsrs -D warnings" cargo $(nightly) doc --all-features --no-deps --manifest-path $(call make-path,$*)/Cargo.toml $(ARGS) + +test-doc-%: + cargo $(nightly) test --doc --all-features --manifest-path $(call make-path,$*)/Cargo.toml $(ARGS) + +# The JS client uses LiteSVM in-process, so we don't need to start a local +# validator. Programs are picked up from ./target/deploy via the LiteSVM +# plugin in test/_setup.ts. +test-js-%: + cd $(call make-path,$*) && pnpm install && pnpm build && pnpm test $(ARGS) + +test-%: + SBF_OUT_DIR=$(PWD)/target/deploy cargo test --manifest-path $(call make-path,$*)/Cargo.toml $(ARGS) + +lint-js-%: + cd $(call make-path,$*) && pnpm install && pnpm lint $(ARGS) + +generate-clients: + pnpm codama run --all $(ARGS) + +# Helpers for publishing +tag-name = $(lastword $(subst /, ,$(call make-path,$1))) +preid-arg = $(subst pre,--preid $2,$(findstring pre,$1)) +package-version = $(subst ",,$(shell jq -r '.version' $(call make-path,$1)/package.json)) +crate-version = $(subst ",,$(shell toml get $(call make-path,$1)/Cargo.toml package.version)) + +git-tag-js-%: + @echo "$(call tag-name,$*)@v$(call package-version,$*)" + +publish-js-%: + cd "$(call make-path,$*)" && pnpm install && pnpm version $(LEVEL) --no-git-tag-version $(call preid-arg,$(LEVEL),$(TAG)) && pnpm publish --no-git-checks --tag $(TAG) + +git-tag-rust-%: + @echo "$(call tag-name,$*)@v$(call crate-version,$*)" + +publish-rust-dry-run-%: + cd "$(call make-path,$*)" && cargo release $(LEVEL) --tag-name "$(call tag-name,$*)@v{{version}}" + +publish-rust-%: + cd "$(call make-path,$*)" && cargo release $(LEVEL) --tag-name "$(call tag-name,$*)@v{{version}}" --execute --no-confirm --dependent-version fix diff --git a/README.md b/README.md index 135078c..1c1df64 100644 --- a/README.md +++ b/README.md @@ -269,16 +269,10 @@ Like this you can for example have multiple programs point to the same metadata ## Building -To build the program locally, first install the required packages using: +To build the program locally, run: ```sh -pnpm install -``` - -and then run: - -```sh -pnpm programs:build +make build-sbf-program ``` ## Testing @@ -288,13 +282,13 @@ The repository includes two types of tests: program tests and JS client tests. To run the program tests: ```sh -pnpm programs:test +make test-program ``` To run the JS tests: ```sh -pnpm clients:js:test +make test-js-clients-js ``` ## License diff --git a/clients/js/README.md b/clients/js/README.md index af85f88..41323f6 100644 --- a/clients/js/README.md +++ b/clients/js/README.md @@ -7,7 +7,7 @@ A generated JavaScript library for the Program Metadata program. To build and test your JavaScript client from the root of the repository, you may use the following command. ```sh -pnpm clients:js:test +make test-js-clients-js ``` This will build the program and run the tests for your JavaScript client. Tests run in-memory via [LiteSVM](https://github.com/LiteSVM/litesvm) — no local validator required. @@ -18,7 +18,7 @@ Alternatively, you can go into the client directory and run the tests directly. ```sh # Build your programs so the compiled `.so` file is available for LiteSVM. -pnpm programs:build +make build-sbf-program # Go into the client directory and run the tests. cd clients/js diff --git a/clients/rust/README.md b/clients/rust/README.md index 07fe2a6..951aab8 100644 --- a/clients/rust/README.md +++ b/clients/rust/README.md @@ -7,7 +7,7 @@ A generated Rust library for the Program Metadata program. To build and test your Rust client from the root of the repository, you may use the following command. ```sh -pnpm clients:js:test +make test-clients-rust ``` -This will start a new local validator, if one is not already running, and run the tests for your Rust client. +This will run the tests for your Rust client against the program built into `target/deploy` (run `make build-sbf-program` first). diff --git a/package.json b/package.json index 9cff82b..7f382fd 100644 --- a/package.json +++ b/package.json @@ -1,34 +1,10 @@ { "private": true, - "scripts": { - "programs:build": "zx ./scripts/rust/build-sbf.mjs program", - "programs:format": "zx ./scripts/rust/format.mjs program", - "programs:lint": "zx ./scripts/rust/lint.mjs program", - "programs:test": "zx ./scripts/rust/test.mjs program", - "solana:check": "zx ./scripts/check-solana-version.mjs", - "solana:link": "zx ./scripts/link-solana-version.mjs", - "generate": "pnpm generate:clients", - "generate:clients": "codama run --all", - "clients:js:format": "zx ./scripts/js/format.mjs", - "clients:js:lint": "zx ./scripts/js/lint.mjs", - "clients:js:publish": "zx ./scripts/js/publish.mjs", - "clients:js:test": "zx ./scripts/js/test.mjs", - "clients:rust:format": "zx ./scripts/rust/format.mjs clients/rust", - "clients:rust:lint": "zx ./scripts/rust/lint.mjs clients/rust", - "clients:rust:test": "zx ./scripts/rust/test.mjs clients/rust", - "template:upgrade": "zx ./scripts/upgrade-template.mjs", - "rust:spellcheck": "cargo spellcheck --code 1", - "rust:audit": "zx ./scripts/rust/audit.mjs", - "rust:publish": "zx ./scripts/rust/publish.mjs", - "rust:semver": "cargo semver-checks" - }, "devDependencies": { "@codama/renderers-js": "^2.2.0", "@codama/renderers-rust": "^3.1.0", - "@iarna/toml": "^2.2.5", "codama": "^1.6.0", - "typescript": "^5.5.2", - "zx": "^7.2.3" + "typescript": "^5.9.3" }, "engines": { "node": ">=v20.0.0" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 25b0c15..30a1edf 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,22 +10,16 @@ importers: devDependencies: '@codama/renderers-js': specifier: ^2.2.0 - version: 2.2.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.7.3) + version: 2.2.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) '@codama/renderers-rust': specifier: ^3.1.0 - version: 3.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.7.3) - '@iarna/toml': - specifier: ^2.2.5 - version: 2.2.5 + version: 3.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) codama: specifier: ^1.6.0 version: 1.6.0 typescript: - specifier: ^5.5.2 - version: 5.7.3 - zx: - specifier: ^7.2.3 - version: 7.2.3 + specifier: ^5.9.3 + version: 5.9.3 packages: @@ -79,18 +73,6 @@ packages: '@iarna/toml@2.2.5': resolution: {integrity: sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==} - '@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@6.0.0': resolution: {integrity: sha512-QAXMupK1nPaIeZgeLTwvC15zeMSbjgupHpcSRoAtcjEs1po4UVPSk7H+IAReRoK2ah2HXHARP3ktzY9x5LY2qQ==} engines: {node: '>=20.18.0'} @@ -131,34 +113,12 @@ packages: typescript: optional: true - '@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.70': - resolution: {integrity: sha512-RE+K0+KZoEpDUbGGctnGdkrLFwi1eYKTlIHNl2Um98mUkGsm1u2Ff6Ltd0e8DktTtC98uy7rSj+hO8t/QuLoVQ==} - - '@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'} @@ -171,10 +131,6 @@ packages: resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} engines: {node: '>= 0.4'} - chalk@5.4.1: - resolution: {integrity: sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==} - engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} - chalk@5.6.2: resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} @@ -191,25 +147,14 @@ 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'} - 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'} @@ -222,45 +167,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.3: - resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} - engines: {node: '>=8.6.0'} - fastestsmallesttextencoderdecoder@1.0.22: resolution: {integrity: sha512-Pb8d48e+oIuY4MaM64Cd7OW1gt4nxCHs7/ddPPZ/Ic3sg8yVGM7O9wDvZ7us6ScaUupzM+pfBolwtYhN1IxBIw==} - fastq@1.18.0: - resolution: {integrity: sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==} - - 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'} @@ -269,21 +181,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==} @@ -295,35 +196,13 @@ packages: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} - ignore@5.3.2: - resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} - 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.3.0: resolution: {integrity: sha512-qtYiSSFlwot9XHtF9bD9c7rwKjr+RecWT//ZnPvSmEjpV5mmPOCN4j8UjY5hbjNkOwZ/jQv3J6R1/pL7RwgMsg==} engines: {node: '>= 0.4'} - jsonfile@6.1.0: - resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} - jsonify@0.0.1: resolution: {integrity: sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==} @@ -331,32 +210,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.8: - resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} - 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'} @@ -371,20 +228,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.8.1: resolution: {integrity: sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==} engines: {node: '>=14'} @@ -394,21 +240,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==} - semver@7.7.3: resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} engines: {node: '>=10'} @@ -421,58 +252,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.7.3: - resolution: {integrity: sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==} + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} 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.7.0: - resolution: {integrity: sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==} - 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.5.1': @@ -516,27 +300,27 @@ snapshots: '@codama/nodes': 1.5.0 '@codama/visitors-core': 1.5.0 - '@codama/renderers-js@2.2.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.7.3)': + '@codama/renderers-js@2.2.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': dependencies: '@codama/errors': 1.5.0 '@codama/nodes': 1.5.0 '@codama/renderers-core': 1.3.5 '@codama/visitors-core': 1.5.0 - '@solana/codecs-strings': 6.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.7.3) + '@solana/codecs-strings': 6.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) prettier: 3.8.1 semver: 7.7.3 transitivePeerDependencies: - fastestsmallesttextencoderdecoder - typescript - '@codama/renderers-rust@3.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.7.3)': + '@codama/renderers-rust@3.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': dependencies: '@codama/errors': 1.5.0 '@codama/nodes': 1.5.0 '@codama/renderers-core': 1.3.5 '@codama/visitors-core': 1.5.0 '@iarna/toml': 2.2.5 - '@solana/codecs-strings': 6.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.7.3) + '@solana/codecs-strings': 6.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) nunjucks: 3.2.4 semver: 7.7.3 transitivePeerDependencies: @@ -570,74 +354,39 @@ snapshots: '@iarna/toml@2.2.5': {} - '@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': + '@solana/codecs-core@6.0.0(typescript@5.9.3)': dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.18.0 - - '@solana/codecs-core@6.0.0(typescript@5.7.3)': - dependencies: - '@solana/errors': 6.0.0(typescript@5.7.3) + '@solana/errors': 6.0.0(typescript@5.9.3) optionalDependencies: - typescript: 5.7.3 + typescript: 5.9.3 - '@solana/codecs-numbers@6.0.0(typescript@5.7.3)': + '@solana/codecs-numbers@6.0.0(typescript@5.9.3)': dependencies: - '@solana/codecs-core': 6.0.0(typescript@5.7.3) - '@solana/errors': 6.0.0(typescript@5.7.3) + '@solana/codecs-core': 6.0.0(typescript@5.9.3) + '@solana/errors': 6.0.0(typescript@5.9.3) optionalDependencies: - typescript: 5.7.3 + typescript: 5.9.3 - '@solana/codecs-strings@6.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.7.3)': + '@solana/codecs-strings@6.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': dependencies: - '@solana/codecs-core': 6.0.0(typescript@5.7.3) - '@solana/codecs-numbers': 6.0.0(typescript@5.7.3) - '@solana/errors': 6.0.0(typescript@5.7.3) + '@solana/codecs-core': 6.0.0(typescript@5.9.3) + '@solana/codecs-numbers': 6.0.0(typescript@5.9.3) + '@solana/errors': 6.0.0(typescript@5.9.3) optionalDependencies: fastestsmallesttextencoderdecoder: 1.0.22 - typescript: 5.7.3 + typescript: 5.9.3 - '@solana/errors@6.0.0(typescript@5.7.3)': + '@solana/errors@6.0.0(typescript@5.9.3)': dependencies: chalk: 5.6.2 commander: 14.0.3 optionalDependencies: - typescript: 5.7.3 - - '@types/fs-extra@11.0.4': - dependencies: - '@types/jsonfile': 6.1.4 - '@types/node': 18.19.70 - - '@types/jsonfile@6.1.4': - dependencies: - '@types/node': 18.19.70 - - '@types/minimist@1.2.5': {} - - '@types/node@18.19.70': - dependencies: - undici-types: 5.26.5 - - '@types/ps-tree@1.1.6': {} - - '@types/which@3.0.4': {} + typescript: 5.9.3 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 @@ -655,8 +404,6 @@ snapshots: call-bind-apply-helpers: 1.0.2 get-intrinsic: 1.3.0 - chalk@5.4.1: {} - chalk@5.6.2: {} codama@1.6.0: @@ -671,26 +418,18 @@ 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 - dunder-proto@1.0.1: dependencies: call-bind-apply-helpers: 1.0.2 es-errors: 1.3.0 gopd: 1.2.0 - duplexer@0.1.2: {} - es-define-property@1.0.1: {} es-errors@1.3.0: {} @@ -699,56 +438,11 @@ 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.3: - 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.8 - fastestsmallesttextencoderdecoder@1.0.22: optional: true - fastq@1.18.0: - 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 @@ -767,22 +461,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.3 - ignore: 5.3.2 - 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 @@ -793,20 +473,8 @@ snapshots: dependencies: function-bind: 1.1.2 - ignore@5.3.2: {} - - 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.3.0: dependencies: call-bind: 1.0.8 @@ -815,37 +483,12 @@ snapshots: jsonify: 0.0.1 object-keys: 1.1.1 - jsonfile@6.1.0: - dependencies: - universalify: 2.0.1 - optionalDependencies: - graceful-fs: 4.2.11 - 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.8: - 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 @@ -854,16 +497,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.8.1: {} prompts@2.4.2: @@ -871,18 +506,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 - semver@7.7.3: {} set-function-length@1.2.2: @@ -896,52 +519,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.7.3: {} - - 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.7.0: {} - - zx@7.2.3: - dependencies: - '@types/fs-extra': 11.0.4 - '@types/minimist': 1.2.5 - '@types/node': 18.19.70 - '@types/ps-tree': 1.1.6 - '@types/which': 3.0.4 - chalk: 5.4.1 - 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.7.0 + typescript@5.9.3: {} 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/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/cliff.toml b/scripts/cliff.toml new file mode 100644 index 0000000..62578ee --- /dev/null +++ b/scripts/cliff.toml @@ -0,0 +1,58 @@ +# git-cliff configuration file +# https://git-cliff.org/docs/configuration +# +# Lines starting with "#" are comments. +# Configuration options are organized into tables and keys. +# See documentation for more information on available options. + +[changelog] +header = """ +## What's new +""" +# template for the changelog body +# https://tera.netlify.app/docs +body = """ +{% for group, commits in commits | group_by(attribute="group") %}\ + {% for commit in commits %} + - {{ commit.message | upper_first | split(pat="\n") | first | trim }}\ + {% if commit.remote.username %} by @{{ commit.remote.username }}{%- endif %}\ + {% endfor %}\ +{% endfor %} +""" +# remove the leading and trailing whitespace from the template +trim = true +footer = """ +""" +postprocessors = [ ] +[git] +# parse the commits based on https://www.conventionalcommits.org +conventional_commits = true +# filter out the commits that are not conventional +filter_unconventional = false +# process each line of a commit as an individual commit +split_commits = false +# regex for preprocessing the commit messages +commit_preprocessors = [] +# regex for parsing and grouping commits +commit_parsers = [ + { message = "^build\\(deps\\)", skip = true }, + { message = "^build\\(deps-dev\\)", skip = true }, + { message = "^ci", skip = true }, + { body = ".*", group = "Changes" }, +] +# protect breaking changes from being skipped due to matching a skipping commit_parser +protect_breaking_commits = false +# filter out the commits that are not matched by commit parsers +filter_commits = false +# glob pattern for matching git tags +tag_pattern = "v[0-9]*" +# regex for skipping tags +skip_tags = "" +# regex for ignoring tags +ignore_tags = "" +# sort the tags topologically +topo_order = false +# sort the commits inside sections by oldest/newest order +sort_commits = "newest" +# limit the number of commits included in the changelog. +# limit_commits = 42 diff --git a/scripts/js/format.mjs b/scripts/js/format.mjs deleted file mode 100644 index 1adb72a..0000000 --- a/scripts/js/format.mjs +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env zx -import 'zx/globals'; -import { cliArguments, workingDirectory } from '../utils.mjs'; - -// Format the client using Oxfmt. -cd(path.join(workingDirectory, 'clients', 'js')); -await $`pnpm install`; -await $`pnpm format ${cliArguments()}`; diff --git a/scripts/js/lint.mjs b/scripts/js/lint.mjs deleted file mode 100644 index 2ed6e98..0000000 --- a/scripts/js/lint.mjs +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env zx -import 'zx/globals'; -import { cliArguments, workingDirectory } from '../utils.mjs'; - -// Check the client using Oxlint. -cd(path.join(workingDirectory, 'clients', 'js')); -await $`pnpm install`; -await $`pnpm lint ${cliArguments()}`; diff --git a/scripts/js/publish.mjs b/scripts/js/publish.mjs deleted file mode 100644 index 51df188..0000000 --- a/scripts/js/publish.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/js/test.mjs b/scripts/js/test.mjs deleted file mode 100644 index 12e1ca9..0000000 --- a/scripts/js/test.mjs +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env zx -import 'zx/globals'; -import { cliArguments, workingDirectory } from '../utils.mjs'; - -// 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/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/rust/audit.mjs b/scripts/rust/audit.mjs deleted file mode 100644 index d517a4d..0000000 --- a/scripts/rust/audit.mjs +++ /dev/null @@ -1,117 +0,0 @@ -#!/usr/bin/env zx -import 'zx/globals'; - -const advisories = [ - // ed25519-dalek: Double Public Key Signing Function Oracle Attack - // - // Remove once repo upgrades to ed25519-dalek v2 - 'RUSTSEC-2022-0093', - - // curve25519-dalek - // - // Remove once repo upgrades to curve25519-dalek v4 - 'RUSTSEC-2024-0344', - - // Crate: tonic - // Version: 0.9.2 - // Title: Remotely exploitable Denial of Service in Tonic - // Date: 2024-10-01 - // ID: RUSTSEC-2024-0376 - // URL: https://rustsec.org/advisories/RUSTSEC-2024-0376 - // Solution: Upgrade to >=0.12.3 - 'RUSTSEC-2024-0376', - - // Remove the ignores below once the dependencies are updated to versions - // that have the vulnerabilities fixed. - - // Crate: quinn-proto - // Version: 0.11.12 - // Title: Denial of service in Quinn endpoints - // Date: 2026-03-09 - // ID: RUSTSEC-2026-0037 - // URL: https://rustsec.org/advisories/RUSTSEC-2026-0037 - // Severity: 8.7 (high) - // Solution: Upgrade to >=0.11.14 - 'RUSTSEC-2026-0037', - - //Crate: rustls-webpki - // Version: 0.101.7 - // Title: Reachable panic in certificate revocation list parsing - // Date: 2026-04-22 - // ID: RUSTSEC-2026-0104 - // URL: https://rustsec.org/advisories/RUSTSEC-2026-0104 - // Solution: Upgrade to >=0.103.13, <0.104.0-alpha.1 OR >=0.104.0-alpha.7 - 'RUSTSEC-2026-0104', - - // Crate: rustls-webpki - // Version: 0.101.7 - // Title: Name constraints for URI names were incorrectly accepted - // Date: 2026-04-14 - // ID: RUSTSEC-2026-0098 - // URL: https://rustsec.org/advisories/RUSTSEC-2026-0098 - // Solution: Upgrade to >=0.103.12, <0.104.0-alpha.1 OR >=0.104.0-alpha.6 - 'RUSTSEC-2026-0098', - - // Crate: rustls-webpki - // Version: 0.101.7 - // Title: Name constraints were accepted for certificates asserting a wildcard name - // Date: 2026-04-14 - // ID: RUSTSEC-2026-0099 - // URL: https://rustsec.org/advisories/RUSTSEC-2026-0099 - // Solution: Upgrade to >=0.103.12, <0.104.0-alpha.1 OR >=0.104.0-alpha.6 - 'RUSTSEC-2026-0099', - - // Crate: rustls-webpki - // Version: 0.103.4 - // Title: Reachable panic in certificate revocation list parsing - // Date: 2026-04-22 - // ID: RUSTSEC-2026-0104 - // URL: https://rustsec.org/advisories/RUSTSEC-2026-0104 - // Solution: Upgrade to >=0.103.13, <0.104.0-alpha.1 OR >=0.104.0-alpha.7 - 'RUSTSEC-2026-0104', - - // Crate: rustls-webpki - // Version: 0.103.4 - // Title: CRLs not considered authoritative by Distribution Point due to faulty matching logic - // Date: 2026-03-20 - // ID: RUSTSEC-2026-0049 - // URL: https://rustsec.org/advisories/RUSTSEC-2026-0049 - // Solution: Upgrade to >=0.103.10 - 'RUSTSEC-2026-0049', - - // Crate: rustls-webpki - // Version: 0.103.4 - // Title: Name constraints for URI names were incorrectly accepted - // Date: 2026-04-14 - // ID: RUSTSEC-2026-0098 - // URL: https://rustsec.org/advisories/RUSTSEC-2026-0098 - // Solution: Upgrade to >=0.103.12, <0.104.0-alpha.1 OR >=0.104.0-alpha.6 - 'RUSTSEC-2026-0098', - - // Crate: rustls-webpki - // Version: 0.103.4 - // Title: Name constraints were accepted for certificates asserting a wildcard name - // Date: 2026-04-14 - // ID: RUSTSEC-2026-0099 - // URL: https://rustsec.org/advisories/RUSTSEC-2026-0099 - // Solution: Upgrade to >=0.103.12, <0.104.0-alpha.1 OR >=0.104.0-alpha.6 - 'RUSTSEC-2026-0099', - - // Crate: time - // Version: 0.3.41 - // Title: Denial of Service via Stack Exhaustion - // Date: 2026-02-05 - // ID: RUSTSEC-2026-0009 - // URL: https://rustsec.org/advisories/RUSTSEC-2026-0009 - // Severity: 6.8 (medium) - // Solution: Upgrade to >=0.3.47 - 'RUSTSEC-2026-0009' -]; -const ignores = [] -advisories.forEach(x => { - ignores.push('--ignore'); - ignores.push(x); -}); - -// Check Solana version. -await $`cargo audit ${ignores}`; diff --git a/scripts/rust/build-sbf.mjs b/scripts/rust/build-sbf.mjs deleted file mode 100644 index cb2cbda..0000000 --- a/scripts/rust/build-sbf.mjs +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env zx -import 'zx/globals'; -import { cliArguments, workingDirectory } from '../utils.mjs'; - -const [folder, ...args] = cliArguments(); -const manifestPath = path.join(workingDirectory, folder, 'Cargo.toml'); -await $`cargo-build-sbf --manifest-path ${manifestPath} ${args}`; - diff --git a/scripts/rust/format.mjs b/scripts/rust/format.mjs deleted file mode 100644 index de9518e..0000000 --- a/scripts/rust/format.mjs +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env zx -import 'zx/globals'; -import { - cliArguments, - getToolchainArgument, - partitionArguments, - popArgument, - workingDirectory, -} from '../utils.mjs'; - -const [folder, ...formatArgs] = cliArguments(); - -const fix = popArgument(formatArgs, '--fix'); -const [cargoArgs, fmtArgs] = partitionArguments(formatArgs, '--'); -const toolchain = getToolchainArgument('format'); - -const manifestPath = path.join(workingDirectory, folder, '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/rust/lint.mjs b/scripts/rust/lint.mjs deleted file mode 100644 index ef4e232..0000000 --- a/scripts/rust/lint.mjs +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env zx -import 'zx/globals'; -import { - cliArguments, - getToolchainArgument, - popArgument, - workingDirectory, -} from '../utils.mjs'; - -const [folder, ...args] = cliArguments(); - -// Configure additional arguments here, e.g.: -// ['--arg1', '--arg2', ...cliArguments()] -const lintArgs = [ - '-Zunstable-options', - '--all-targets', - '--all-features', - '--no-deps', - '--', - '--deny=warnings', - '--deny=clippy::arithmetic_side_effects', - ...args, -]; - -const fix = popArgument(lintArgs, '--fix'); -const toolchain = getToolchainArgument('lint'); -const manifestPath = path.join(workingDirectory, folder, '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/rust/publish.mjs b/scripts/rust/publish.mjs deleted file mode 100644 index 28bd91b..0000000 --- a/scripts/rust/publish.mjs +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env zx -import 'zx/globals'; -import { cliArguments, getCargo, workingDirectory } from '../utils.mjs'; - -const dryRun = argv['dry-run'] ?? false; -const [folder, level] = cliArguments(); -if (!folder) { - throw new Error('A path to a directory with a Rust package — e.g. "clients/cli" — must be provided.'); -} -if (!level) { - throw new Error('A version level — e.g. "patch" — must be provided.'); -} - -cd(path.join(workingDirectory, folder)); - -const packageToml = getCargo(folder).package; -const oldVersion = packageToml.version; -const packageName = packageToml.name; -const tagName = path.basename(folder); - -// Publish the new version, commit the repo change, tag it, and push it all. -const releaseArgs = dryRun - ? [] - : ['--tag-name', `${tagName}@v{{version}}`, '--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(folder).package.version; -const newGitTag = `${tagName}@v${newVersion}`; -const oldGitTag = `${tagName}@v${oldVersion}`; - -// Expose the new version to CI if needed. -if (process.env.CI) { - await $`echo "new_git_tag=${newGitTag}" >> $GITHUB_OUTPUT`; - await $`echo "old_git_tag=${oldGitTag}" >> $GITHUB_OUTPUT`; -} diff --git a/scripts/rust/test.mjs b/scripts/rust/test.mjs deleted file mode 100644 index 19da099..0000000 --- a/scripts/rust/test.mjs +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env zx -import 'zx/globals'; -import { cliArguments, workingDirectory } from '../utils.mjs'; - -const [folder, ...args] = cliArguments(); -const sbfOutDir = path.join(workingDirectory, 'target', 'deploy'); -const manifestPath = path.join(workingDirectory, folder, 'Cargo.toml'); -await $`SBF_OUT_DIR=${sbfOutDir} cargo test --manifest-path ${manifestPath} ${args}`; diff --git a/scripts/upgrade-template.mjs b/scripts/upgrade-template.mjs deleted file mode 100644 index b2acb7c..0000000 --- a/scripts/upgrade-template.mjs +++ /dev/null @@ -1,58 +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 = [ - 'program-metadata', - '--address', - 'ProgM6JCCvbYkfKqJYHePx4xxSUSqJp7rh8Lyv7nk7S', - '--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/*', - 'clients/js/test/*', - 'clients/rust/tests/*', - 'program/**/*', - 'program/*', - 'scripts/generate-clients.mjs', - 'scripts/generate-idls.mjs', - 'scripts/upgrade-template.mjs', - 'scripts/program/*', - '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('token'); - -// 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`; diff --git a/scripts/utils.mjs b/scripts/utils.mjs deleted file mode 100644 index aebe5d5..0000000 --- a/scripts/utils.mjs +++ /dev/null @@ -1,129 +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') && - // Exclude the pinocchio-token-program crate. - getCargo(member).package?.name !== 'pinocchio-token-program' - ); -} - -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 ''; - } -}