Переглянути джерело

Overhaul CI with Makefile (#51)

* scripts: replace simple jobs with cargo-make

* scripts: replace js test job with cargo-make

* scripts: bashify publish scripts

* scripts: drop everything unused

* move all aliases to `Makefile.toml`

* ci: make pnpm install optional

* Use a Makefile

* Spell pnpm correctly, parallelize more

* Remove dev.env file

* Revert "Remove dev.env file"

This reverts commit 63407693a6eeb2ed8539ecdc13a636fe2b894a30.

* Use / rename vars file

* shebang

* cli version name

* cargo release dry run

* restart-test-validator.sh

---------

Co-authored-by: Jon C <me@jonc.dev>
Joe C 6 місяців тому
батько
коміт
960949f720

+ 20 - 11
.github/actions/setup/action.yml

@@ -10,64 +10,73 @@ inputs:
   cargo-cache-local-key:
     description: The key to cache local cargo dependencies. Skips local cargo caching if not provided.
     required: false
-  toolchain:
-    description: Rust toolchain to install. Comma-separated string of [`build`, `format`, `lint`, `test`].
+  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 [`build`, `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 tsx ./scripts/ci/set-env.mts
-
     - name: Install Rust 'build' Toolchain
       if: ${{ contains(inputs.toolchain, 'build') }}
       uses: dtolnay/rust-toolchain@master
       with:
-        toolchain: ${{ env.TOOLCHAIN_BUILD }}
+        toolchain: ${{ env.RUST_TOOLCHAIN_NIGHTLY }}
 
     - 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 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: ${{ env.TOOLCHAIN_TEST }}
+        toolchain: ${{ env.RUST_TOOLCHAIN_NIGHTLY }}
 
     - 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'

+ 18 - 18
.github/workflows/main.yml

@@ -15,12 +15,14 @@ jobs:
 
       - name: Setup Environment
         uses: ./.github/actions/setup
+        with:
+          pnpm: true
 
       - name: Format Client JS
-        run: pnpm js:format
+        run: make format-js
 
       - name: Lint Client JS
-        run: pnpm js:lint
+        run: make lint-js
 
   format_and_lint_client_rust:
     name: Format & Lint Client Rust
@@ -35,16 +37,16 @@ jobs:
           toolchain: format, lint
 
       - name: Format
-        run: pnpm rust:format
+        run: make format-clients-rust
 
       - name: Lint / Clippy
-        run: pnpm rust:lint:clippy
+        run: make clippy-clients-rust
 
       - name: Lint / Docs
-        run: pnpm rust:lint:docs
+        run: make lint-docs-clients-rust
 
       - name: Lint / Features
-        run: pnpm rust:lint:features
+        run: make lint-features-clients-rust
 
   format_and_lint_interface:
     name: Format & Lint Interface
@@ -59,21 +61,20 @@ jobs:
           toolchain: format, lint
 
       - name: Format
-        run: pnpm interface:format
+        run: make format-interface
 
       - name: Lint / Clippy
-        run: pnpm interface:lint:clippy
+        run: make clippy-interface
 
       - name: Lint / Docs
-        run: pnpm interface:lint:docs
+        run: make lint-docs-interface
 
       - name: Lint / Features
-        run: pnpm interface:lint:features
+        run: make lint-features-interface
 
   wasm_interface:
     name: Build Interface in WASM
     runs-on: ubuntu-latest
-    needs: format_and_lint_interface
     steps:
       - name: Git Checkout
         uses: actions/checkout@v4
@@ -90,12 +91,11 @@ jobs:
           tool: wasm-pack
 
       - name: Build Interface with wasm-pack
-        run: pnpm interface:wasm
+        run: make build-wasm-interface
 
   test_interface:
     name: Test Interface
     runs-on: ubuntu-latest
-    needs: format_and_lint_interface
     steps:
       - name: Git Checkout
         uses: actions/checkout@v4
@@ -108,7 +108,7 @@ jobs:
           solana: true
 
       - name: Test Interface
-        run: pnpm interface:test
+        run: make test-interface
 
   generate_clients:
     name: Check Client Generation
@@ -120,6 +120,7 @@ jobs:
       - name: Setup Environment
         uses: ./.github/actions/setup
         with:
+          pnpm: true
           toolchain: format
 
       - name: Generate Clients
@@ -133,7 +134,6 @@ jobs:
   test_client_js:
     name: Test Client JS
     runs-on: ubuntu-latest
-    needs: [format_and_lint_client_js]
     steps:
       - name: Git Checkout
         uses: actions/checkout@v4
@@ -141,15 +141,15 @@ jobs:
       - name: Setup Environment
         uses: ./.github/actions/setup
         with:
+          pnpm: true
           solana: true
 
       - name: Test Client JS
-        run: pnpm js:test
+        run: make test-js
 
   test_client_rust:
     name: Test Client Rust
     runs-on: ubuntu-latest
-    needs: [format_and_lint_client_rust]
     steps:
       - name: Git Checkout
         uses: actions/checkout@v4
@@ -162,4 +162,4 @@ jobs:
           solana: true
 
       - name: Test Client Rust
-        run: pnpm rust:test
+        run: make test-clients-rust

+ 4 - 4
.github/workflows/publish-js-client.yml

@@ -41,13 +41,13 @@ jobs:
           solana: true
 
       - name: Format
-        run: pnpm js:format
+        run: make format-js
 
       - name: Lint
-        run: pnpm js:lint
+        run: make lint-js
 
       - name: Test
-        run: pnpm js:test
+        run: make test-js
 
   publish_js:
     name: Publish JS client
@@ -83,7 +83,7 @@ jobs:
 
       - name: Publish JS Client
         id: publish
-        run: pnpm 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

+ 4 - 4
.github/workflows/publish-rust-client.yml

@@ -49,13 +49,13 @@ jobs:
           solana: true
 
       - name: Format
-        run: pnpm rust:format
+        run: make format-clients-rust
 
       - name: Lint
-        run: pnpm rust:lint
+        run: make clippy-clients-rust
 
       - name: Test
-        run: pnpm rust:test
+        run: make test-clients-rust
 
   publish_rust:
     name: Publish Rust Client
@@ -109,7 +109,7 @@ jobs:
             OPTIONS=""
           fi
 
-          pnpm rust:publish $LEVEL $OPTIONS
+          ./scripts/publish-rust.sh clients/rust $LEVEL $OPTIONS
 
       - name: Push Commit and Tag
         if: github.event.inputs.dry_run != 'true'

+ 0 - 8
Cargo.toml

@@ -27,11 +27,3 @@ solana-program = { version = "2.2.1", default-features = false }
 solana-program-entrypoint = "2.2.1"
 solana-program-error = "2.2.1"
 solana-pubkey = { version = "2.2.1", default-features = false }
-
-[workspace.metadata.cli]
-solana = "2.2.0"
-
-[workspace.metadata.toolchains]
-format = "nightly-2024-11-22"
-lint = "nightly-2024-11-22"
-test = "nightly-2024-11-22"

+ 41 - 0
Makefile

@@ -0,0 +1,41 @@
+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 -,/,$*)
+
+build-wasm-interface:
+	wasm-pack build --target nodejs --dev ./interface --features bincode
+
+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
+
+test-%:
+	cargo $(nightly) test --manifest-path $(subst -,/,$*)/Cargo.toml
+
+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

+ 2 - 31
package.json

@@ -1,42 +1,13 @@
 {
   "private": true,
   "scripts": {
-    "solana:check": "tsx ./scripts/helpers/check-solana-version.mts",
-    "solana:link": "tsx ./scripts/helpers/link-solana-version.mts",
     "generate": "pnpm generate:clients",
-    "generate:clients": "codama run --all",
-    "validator:start": "tsx ./scripts/helpers/start-validator.mts",
-    "validator:restart": "pnpm validator:start --restart",
-    "validator:stop": "tsx ./scripts/helpers/stop-validator.mts",
-    "js:format": "tsx ./scripts/js.mts format clients/js",
-    "js:lint": "tsx ./scripts/js.mts lint clients/js",
-    "js:publish": "tsx ./scripts/js.mts publish clients/js",
-    "js:test": "tsx ./scripts/js.mts test clients/js",
-    "rust:format": "tsx ./scripts/rust.mts format clients/rust",
-    "rust:lint": "tsx ./scripts/rust.mts lint clients/rust",
-    "rust:lint:clippy": "tsx ./scripts/rust.mts lint-clippy clients/rust",
-    "rust:lint:docs": "tsx ./scripts/rust.mts lint-docs clients/rust",
-    "rust:lint:features": "tsx ./scripts/rust.mts lint-features clients/rust",
-    "rust:publish": "tsx ./scripts/rust.mts publish clients/rust",
-    "rust:test": "tsx ./scripts/rust.mts test clients/rust",
-    "interface:format": "tsx ./scripts/rust.mts format interface",
-    "interface:lint": "tsx ./scripts/rust.mts lint interface",
-    "interface:lint:clippy": "tsx ./scripts/rust.mts lint-clippy interface",
-    "interface:lint:docs": "tsx ./scripts/rust.mts lint-docs interface",
-    "interface:lint:features": "tsx ./scripts/rust.mts lint-features interface",
-    "interface:publish": "tsx ./scripts/rust.mts publish interface",
-    "interface:test": "tsx ./scripts/rust.mts test interface",
-    "interface:wasm": "tsx ./scripts/rust.mts wasm interface",
-    "template:upgrade": "tsx ./scripts/helpers/upgrade-template.ts"
+    "generate:clients": "codama run --all"
   },
   "devDependencies": {
     "@codama/renderers-js": "^1.2.7",
     "@codama/renderers-rust": "^1.0.16",
-    "@iarna/toml": "^2.2.5",
-    "codama": "^1.2.8",
-    "tsx": "^4.19.2",
-    "typescript": "^5.5.2",
-    "zx": "^7.2.3"
+    "codama": "^1.2.8"
   },
   "engines": {
     "node": ">=v20.0.0"

+ 0 - 710
pnpm-lock.yaml

@@ -14,21 +14,9 @@ importers:
       '@codama/renderers-rust':
         specifier: ^1.0.16
         version: 1.0.16(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.7.3)
-      '@iarna/toml':
-        specifier: ^2.2.5
-        version: 2.2.5
       codama:
         specifier: ^1.2.8
         version: 1.2.8(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.7.3)
-      tsx:
-        specifier: ^4.19.2
-        version: 4.19.2
-      typescript:
-        specifier: ^5.5.2
-        version: 5.7.3
-      zx:
-        specifier: ^7.2.3
-        version: 7.2.3
 
 packages:
 
@@ -72,169 +60,10 @@ packages:
   '@codama/visitors@1.2.8':
     resolution: {integrity: sha512-LbcTyzTUEJfGRbCTuQIAVR9X5bLdZ1oD7GAuw5kxaq63+H6JHAbigaKwaq9uvr/OXMT4U/2GcWgKfX1oGKXg/g==}
 
-  '@esbuild/aix-ppc64@0.23.1':
-    resolution: {integrity: sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==}
-    engines: {node: '>=18'}
-    cpu: [ppc64]
-    os: [aix]
-
-  '@esbuild/android-arm64@0.23.1':
-    resolution: {integrity: sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==}
-    engines: {node: '>=18'}
-    cpu: [arm64]
-    os: [android]
-
-  '@esbuild/android-arm@0.23.1':
-    resolution: {integrity: sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==}
-    engines: {node: '>=18'}
-    cpu: [arm]
-    os: [android]
-
-  '@esbuild/android-x64@0.23.1':
-    resolution: {integrity: sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==}
-    engines: {node: '>=18'}
-    cpu: [x64]
-    os: [android]
-
-  '@esbuild/darwin-arm64@0.23.1':
-    resolution: {integrity: sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==}
-    engines: {node: '>=18'}
-    cpu: [arm64]
-    os: [darwin]
-
-  '@esbuild/darwin-x64@0.23.1':
-    resolution: {integrity: sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==}
-    engines: {node: '>=18'}
-    cpu: [x64]
-    os: [darwin]
-
-  '@esbuild/freebsd-arm64@0.23.1':
-    resolution: {integrity: sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==}
-    engines: {node: '>=18'}
-    cpu: [arm64]
-    os: [freebsd]
-
-  '@esbuild/freebsd-x64@0.23.1':
-    resolution: {integrity: sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==}
-    engines: {node: '>=18'}
-    cpu: [x64]
-    os: [freebsd]
-
-  '@esbuild/linux-arm64@0.23.1':
-    resolution: {integrity: sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==}
-    engines: {node: '>=18'}
-    cpu: [arm64]
-    os: [linux]
-
-  '@esbuild/linux-arm@0.23.1':
-    resolution: {integrity: sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==}
-    engines: {node: '>=18'}
-    cpu: [arm]
-    os: [linux]
-
-  '@esbuild/linux-ia32@0.23.1':
-    resolution: {integrity: sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==}
-    engines: {node: '>=18'}
-    cpu: [ia32]
-    os: [linux]
-
-  '@esbuild/linux-loong64@0.23.1':
-    resolution: {integrity: sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==}
-    engines: {node: '>=18'}
-    cpu: [loong64]
-    os: [linux]
-
-  '@esbuild/linux-mips64el@0.23.1':
-    resolution: {integrity: sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==}
-    engines: {node: '>=18'}
-    cpu: [mips64el]
-    os: [linux]
-
-  '@esbuild/linux-ppc64@0.23.1':
-    resolution: {integrity: sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==}
-    engines: {node: '>=18'}
-    cpu: [ppc64]
-    os: [linux]
-
-  '@esbuild/linux-riscv64@0.23.1':
-    resolution: {integrity: sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==}
-    engines: {node: '>=18'}
-    cpu: [riscv64]
-    os: [linux]
-
-  '@esbuild/linux-s390x@0.23.1':
-    resolution: {integrity: sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==}
-    engines: {node: '>=18'}
-    cpu: [s390x]
-    os: [linux]
-
-  '@esbuild/linux-x64@0.23.1':
-    resolution: {integrity: sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==}
-    engines: {node: '>=18'}
-    cpu: [x64]
-    os: [linux]
-
-  '@esbuild/netbsd-x64@0.23.1':
-    resolution: {integrity: sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==}
-    engines: {node: '>=18'}
-    cpu: [x64]
-    os: [netbsd]
-
-  '@esbuild/openbsd-arm64@0.23.1':
-    resolution: {integrity: sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==}
-    engines: {node: '>=18'}
-    cpu: [arm64]
-    os: [openbsd]
-
-  '@esbuild/openbsd-x64@0.23.1':
-    resolution: {integrity: sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==}
-    engines: {node: '>=18'}
-    cpu: [x64]
-    os: [openbsd]
-
-  '@esbuild/sunos-x64@0.23.1':
-    resolution: {integrity: sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==}
-    engines: {node: '>=18'}
-    cpu: [x64]
-    os: [sunos]
-
-  '@esbuild/win32-arm64@0.23.1':
-    resolution: {integrity: sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==}
-    engines: {node: '>=18'}
-    cpu: [arm64]
-    os: [win32]
-
-  '@esbuild/win32-ia32@0.23.1':
-    resolution: {integrity: sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==}
-    engines: {node: '>=18'}
-    cpu: [ia32]
-    os: [win32]
-
-  '@esbuild/win32-x64@0.23.1':
-    resolution: {integrity: sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==}
-    engines: {node: '>=18'}
-    cpu: [x64]
-    os: [win32]
-
-  '@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':
     resolution: {integrity: sha512-qCG+3hDU5Pm8V6joJjR4j4Zv9md1z0RaecniNDIkEglnxmOUODnmPLWbtOjnDylfItyuZeDihK8hkewdj8cUtw==}
     engines: {node: '>=20.18.0'}
@@ -305,34 +134,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.74':
-    resolution: {integrity: sha512-HMwEkkifei3L605gFdV+/UwtpxP6JSzM+xFk2Ia6DNFSwSVBRh9qp5Tgf4lNFOMfPVuU0WnkcWpXZpgn5ufO4A==}
-
-  '@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.1:
     resolution: {integrity: sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==}
     engines: {node: '>= 0.4'}
@@ -365,25 +172,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'}
@@ -396,55 +192,12 @@ packages:
     resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==}
     engines: {node: '>= 0.4'}
 
-  esbuild@0.23.1:
-    resolution: {integrity: sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==}
-    engines: {node: '>=18'}
-    hasBin: true
-
-  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.19.0:
-    resolution: {integrity: sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA==}
-
-  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.3.0:
-    resolution: {integrity: sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==}
-    engines: {node: '>=14.14'}
-
-  fsevents@2.3.3:
-    resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
-    engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
-    os: [darwin]
-
   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.2.7:
     resolution: {integrity: sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==}
     engines: {node: '>= 0.4'}
@@ -453,24 +206,10 @@ packages:
     resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==}
     engines: {node: '>= 0.4'}
 
-  get-tsconfig@4.10.0:
-    resolution: {integrity: sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==}
-
-  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==}
 
@@ -482,35 +221,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.2.1:
     resolution: {integrity: sha512-Lp6HbbBgosLmJbjx0pBLbgvx68FaFU1sdkmBuckmhhJ88kL13OA51CDtR2yJB50eCNMH9wRqtQNNiAqQH4YXnA==}
     engines: {node: '>= 0.4'}
 
-  jsonfile@6.1.0:
-    resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==}
-
   jsonify@0.0.1:
     resolution: {integrity: sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==}
 
@@ -518,32 +235,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'}
@@ -558,20 +253,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.2:
     resolution: {integrity: sha512-lc6npv5PH7hVqozBR7lkBNOGXV9vMwROAPlumdBkX0wTbbzPu/U1hk5yL8p2pt4Xoc+2mkT8t/sow2YrV/M5qg==}
     engines: {node: '>=14'}
@@ -581,24 +265,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==}
-
-  resolve-pkg-maps@1.0.0:
-    resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==}
-
-  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'}
@@ -606,63 +272,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'}
-
-  tsx@4.19.2:
-    resolution: {integrity: sha512-pOUl6Vo2LUq/bSa8S5q7b91cgNSjctn9ugq/+Mvow99qW6x/UZYwzxy/3NmqoT66eHYfCVvFvACC58UBPFf28g==}
-    engines: {node: '>=18.0.0'}
-    hasBin: true
-
   typescript@5.7.3:
     resolution: {integrity: sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==}
     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.0.7(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.7.3)':
@@ -784,94 +398,8 @@ snapshots:
       '@codama/nodes': 1.2.8
       '@codama/visitors-core': 1.2.8
 
-  '@esbuild/aix-ppc64@0.23.1':
-    optional: true
-
-  '@esbuild/android-arm64@0.23.1':
-    optional: true
-
-  '@esbuild/android-arm@0.23.1':
-    optional: true
-
-  '@esbuild/android-x64@0.23.1':
-    optional: true
-
-  '@esbuild/darwin-arm64@0.23.1':
-    optional: true
-
-  '@esbuild/darwin-x64@0.23.1':
-    optional: true
-
-  '@esbuild/freebsd-arm64@0.23.1':
-    optional: true
-
-  '@esbuild/freebsd-x64@0.23.1':
-    optional: true
-
-  '@esbuild/linux-arm64@0.23.1':
-    optional: true
-
-  '@esbuild/linux-arm@0.23.1':
-    optional: true
-
-  '@esbuild/linux-ia32@0.23.1':
-    optional: true
-
-  '@esbuild/linux-loong64@0.23.1':
-    optional: true
-
-  '@esbuild/linux-mips64el@0.23.1':
-    optional: true
-
-  '@esbuild/linux-ppc64@0.23.1':
-    optional: true
-
-  '@esbuild/linux-riscv64@0.23.1':
-    optional: true
-
-  '@esbuild/linux-s390x@0.23.1':
-    optional: true
-
-  '@esbuild/linux-x64@0.23.1':
-    optional: true
-
-  '@esbuild/netbsd-x64@0.23.1':
-    optional: true
-
-  '@esbuild/openbsd-arm64@0.23.1':
-    optional: true
-
-  '@esbuild/openbsd-x64@0.23.1':
-    optional: true
-
-  '@esbuild/sunos-x64@0.23.1':
-    optional: true
-
-  '@esbuild/win32-arm64@0.23.1':
-    optional: true
-
-  '@esbuild/win32-ia32@0.23.1':
-    optional: true
-
-  '@esbuild/win32-x64@0.23.1':
-    optional: true
-
-  '@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.19.0
-
   '@solana/codecs-core@2.0.0(typescript@5.7.3)':
     dependencies:
       '@solana/errors': 2.0.0(typescript@5.7.3)
@@ -951,33 +479,10 @@ snapshots:
     transitivePeerDependencies:
       - fastestsmallesttextencoderdecoder
 
-  '@types/fs-extra@11.0.4':
-    dependencies:
-      '@types/jsonfile': 6.1.4
-      '@types/node': 18.19.74
-
-  '@types/jsonfile@6.1.4':
-    dependencies:
-      '@types/node': 18.19.74
-
-  '@types/minimist@1.2.5': {}
-
-  '@types/node@18.19.74':
-    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.1:
     dependencies:
       es-errors: 1.3.0
@@ -1015,26 +520,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.1
       es-errors: 1.3.0
       gopd: 1.2.0
 
-  duplexer@0.1.2: {}
-
   es-define-property@1.0.1: {}
 
   es-errors@1.3.0: {}
@@ -1043,85 +540,10 @@ snapshots:
     dependencies:
       es-errors: 1.3.0
 
-  esbuild@0.23.1:
-    optionalDependencies:
-      '@esbuild/aix-ppc64': 0.23.1
-      '@esbuild/android-arm': 0.23.1
-      '@esbuild/android-arm64': 0.23.1
-      '@esbuild/android-x64': 0.23.1
-      '@esbuild/darwin-arm64': 0.23.1
-      '@esbuild/darwin-x64': 0.23.1
-      '@esbuild/freebsd-arm64': 0.23.1
-      '@esbuild/freebsd-x64': 0.23.1
-      '@esbuild/linux-arm': 0.23.1
-      '@esbuild/linux-arm64': 0.23.1
-      '@esbuild/linux-ia32': 0.23.1
-      '@esbuild/linux-loong64': 0.23.1
-      '@esbuild/linux-mips64el': 0.23.1
-      '@esbuild/linux-ppc64': 0.23.1
-      '@esbuild/linux-riscv64': 0.23.1
-      '@esbuild/linux-s390x': 0.23.1
-      '@esbuild/linux-x64': 0.23.1
-      '@esbuild/netbsd-x64': 0.23.1
-      '@esbuild/openbsd-arm64': 0.23.1
-      '@esbuild/openbsd-x64': 0.23.1
-      '@esbuild/sunos-x64': 0.23.1
-      '@esbuild/win32-arm64': 0.23.1
-      '@esbuild/win32-ia32': 0.23.1
-      '@esbuild/win32-x64': 0.23.1
-
-  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: {}
 
-  fastq@1.19.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.3.0:
-    dependencies:
-      graceful-fs: 4.2.11
-      jsonfile: 6.1.0
-      universalify: 2.0.1
-
-  fsevents@2.3.3:
-    optional: true
-
   function-bind@1.1.2: {}
 
-  fx@35.0.0: {}
-
   get-intrinsic@1.2.7:
     dependencies:
       call-bind-apply-helpers: 1.0.1
@@ -1140,26 +562,8 @@ snapshots:
       dunder-proto: 1.0.1
       es-object-atoms: 1.1.1
 
-  get-tsconfig@4.10.0:
-    dependencies:
-      resolve-pkg-maps: 1.0.0
-
-  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
@@ -1170,20 +574,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.2.1:
     dependencies:
       call-bind: 1.0.8
@@ -1192,37 +584,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
@@ -1231,16 +598,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.2: {}
 
   prompts@2.4.2:
@@ -1248,20 +607,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: {}
-
-  resolve-pkg-maps@1.0.0: {}
-
-  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
@@ -1273,59 +618,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
-
-  tsx@4.19.2:
-    dependencies:
-      esbuild: 0.23.1
-      get-tsconfig: 4.10.0
-    optionalDependencies:
-      fsevents: 2.3.3
-
   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.74
-      '@types/ps-tree': 1.1.6
-      '@types/which': 3.0.4
-      chalk: 5.4.1
-      fs-extra: 11.3.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

+ 0 - 8
scripts/ci/set-env.mts

@@ -1,8 +0,0 @@
-#!/usr/bin/env zx
-import { getSolanaVersion, getToolchain } from '../helpers/utils.mts';
-
-await $`echo "SOLANA_VERSION=${getSolanaVersion()}" >> $GITHUB_ENV`;
-await $`echo "TOOLCHAIN_BUILD=${getToolchain('build')}" >> $GITHUB_ENV`;
-await $`echo "TOOLCHAIN_FORMAT=${getToolchain('format')}" >> $GITHUB_ENV`;
-await $`echo "TOOLCHAIN_LINT=${getToolchain('lint')}" >> $GITHUB_ENV`;
-await $`echo "TOOLCHAIN_TEST=${getToolchain('test')}" >> $GITHUB_ENV`;

+ 0 - 24
scripts/helpers/check-solana-version.mts

@@ -1,24 +0,0 @@
-#!/usr/bin/env zx
-import 'zx/globals';
-import { getInstalledSolanaVersion, getSolanaVersion } from './utils.mts';
-
-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.`
-  );
-}

+ 0 - 74
scripts/helpers/link-solana-version.mts

@@ -1,74 +0,0 @@
-#!/usr/bin/env zx
-import 'zx/globals';
-import { getInstalledSolanaVersion, getSolanaVersion } from './utils.mts';
-
-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)"`;
-  }
-}

+ 0 - 126
scripts/helpers/start-validator.mts

@@ -1,126 +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,
-  workingDirectory,
-} from './utils.mts';
-
-// 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(void 0);
-        }
-      }, 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(workingDirectory, '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`),
-  }));
-}

+ 0 - 13
scripts/helpers/stop-validator.mts

@@ -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.'));
-}

+ 0 - 58
scripts/helpers/upgrade-template.mts

@@ -1,58 +0,0 @@
-#!/usr/bin/env zx
-import 'zx/globals';
-import { getCargo, workingDirectory } from './utils.mts';
-
-// Arguments to pass to the `create-solana-program` command.
-const rustClientCargo = getCargo(path.join('clients', 'rust'));
-const jsClientPkg = require(
-  path.join(workingDirectory, 'clients', 'js', 'package.json')
-);
-const templateArgs = [
-  'system',
-  '--address',
-  '11111111111111111111111111111111',
-  '--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('system');
-
-// 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`;

+ 0 - 164
scripts/helpers/utils.mts

@@ -1,164 +0,0 @@
-import 'zx/globals';
-import { JsonMap, 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(): string[] {
-  return getAllProgramFolders().map((folder) =>
-    path.join(workingDirectory, folder, 'idl.json')
-  );
-}
-
-export function getExternalProgramOutputDir(): string {
-  const config = getCargoMetadata()?.solana?.['external-programs-output'];
-  return path.join(workingDirectory, config ?? 'target/deploy');
-}
-
-export function getExternalProgramAddresses(): string[] {
-  const addresses = getProgramFolders().flatMap(
-    (folder) => getCargoMetadata(folder)?.solana?.['program-dependencies'] ?? []
-  );
-  return Array.from(new Set(addresses));
-}
-
-export function getExternalAccountAddresses(): string[] {
-  const addresses = getProgramFolders().flatMap(
-    (folder) => getCargoMetadata(folder)?.solana?.['account-dependencies'] ?? []
-  );
-  return Array.from(new Set(addresses));
-}
-
-let didWarnAboutMissingPrograms = false;
-export function getProgramFolders(): string[] {
-  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(): string[] {
-  return getCargo().workspace['members'].filter(
-    (member) => getCargo(member).package['metadata']?.['solana']?.['program-id']
-  );
-}
-
-export function getCargo(folder?: string): JsonMap {
-  return parseToml(
-    fs.readFileSync(
-      path.join(workingDirectory, folder ? folder : '.', 'Cargo.toml'),
-      'utf8'
-    )
-  );
-}
-
-export function getCargoMetadata(folder?: string) {
-  const cargo = getCargo(folder);
-  return folder ? cargo?.package?.['metadata'] : cargo?.workspace?.['metadata'];
-}
-
-export function getSolanaVersion(): string {
-  return getCargoMetadata()?.cli?.solana;
-}
-
-export function getToolchain(operation): string {
-  return getCargoMetadata()?.toolchains?.[operation];
-}
-
-export function getToolchainArgument(operation): string {
-  const channel = getToolchain(operation);
-  return channel ? `+${channel}` : '';
-}
-
-export function cliArguments(): string[] {
-  return process.argv.slice(2);
-}
-
-export function popArgument(args: string[], arg: string) {
-  const index = args.indexOf(arg);
-  if (index >= 0) {
-    args.splice(index, 1);
-  }
-  return index >= 0;
-}
-
-export function partitionArguments(
-  args: string[],
-  delimiter: string,
-  defaultArgs?: string[]
-): [string[], string[]] {
-  const index = args.indexOf(delimiter);
-  const [providedCargoArgs, providedCommandArgs] =
-    index >= 0 ? [args.slice(0, index), args.slice(index + 1)] : [args, []];
-
-  if (defaultArgs) {
-    const [defaultCargoArgs, defaultCommandArgs] = partitionArguments(
-      defaultArgs,
-      delimiter
-    );
-    return [
-      [...defaultCargoArgs, ...providedCargoArgs],
-      [...defaultCommandArgs, ...providedCommandArgs],
-    ];
-  }
-  return [providedCargoArgs, providedCommandArgs];
-}
-
-export async function getInstalledSolanaVersion(): Promise<string | undefined> {
-  try {
-    const { stdout } = await $`solana --version`.quiet();
-    return stdout.match(/(\d+\.\d+\.\d+)/)?.[1];
-  } catch (error) {
-    return '';
-  }
-}
-
-export function parseCliArguments(): {
-  command: string;
-  libraryPath: string;
-  args: string[];
-} {
-  const command = process.argv[2];
-  const args = process.argv.slice(3);
-
-  // Extract the relative crate directory from the command-line arguments. This
-  // is the only required argument.
-  const relativePath = args.shift();
-
-  if (!relativePath) {
-    throw new Error('Missing relative manifest path');
-  }
-
-  return {
-    command,
-    libraryPath: path.join(workingDirectory, relativePath),
-    args,
-  };
-}

+ 0 - 99
scripts/js.mts

@@ -1,99 +0,0 @@
-#!/usr/bin/env zx
-
-// Script for working with JavaScript projects.
-
-import 'zx/globals';
-import {
-    parseCliArguments,
-    partitionArguments,
-} from './helpers/utils.mts';
-
-enum Command {
-    Format = 'format',
-    Lint = 'lint',
-    Test = 'test',
-    Publish = 'publish',
-}
-
-const { command, libraryPath, args } = parseCliArguments();
-
-async function pnpm(
-    command: string,
-    build = false,
-) {
-    const [pnpmArgs, commandArgs] = partitionArguments(args, '--');
-    cd(libraryPath);
-    await $`pnpm install`;
-    if (build) {
-        await $`pnpm build`;
-    }
-    await $`pnpm ${command} ${pnpmArgs} -- ${commandArgs}`;
-}
-
-async function format() {
-    return pnpm('format');
-}
-
-async function lint() {
-    return pnpm('lint');
-}
-
-async function test() {
-    // Start the local validator, or restart it if it is already running.
-    await $`pnpm validator:restart`;
-
-    // Build the client and run the tests.
-    return pnpm('test', true);
-}
-
-async function publish() {
-    const [level, tag = 'latest'] = args;
-    if (!level) {
-      throw new Error('A version level — e.g. "path" — must be provided.');
-    }
-
-    // Go to the directory and install the dependencies.
-    cd(libraryPath);
-    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}"`;
-}
-
-
-switch (command) {
-    case Command.Format:
-        await format();
-        break;
-    case Command.Lint:
-        await lint();
-        break;
-    case Command.Test:
-        await test();
-        break;
-    case Command.Publish:
-        await publish();
-        break;
-    default:
-        throw new Error(`Unknown command: ${command}`);
-}

+ 38 - 0
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 <library_path> <version-level> [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}"

+ 38 - 0
scripts/publish-rust.sh

@@ -0,0 +1,38 @@
+#!/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 <library_path> <version-level>"
+    echo "Example: $0 clients/rust patch"
+    exit 1
+fi
+
+cd "$library_path"
+
+# Run cargo-release
+if [[ "$dry_run" != "true" ]]; then
+    cargo release "$level" --no-push --no-tag --no-confirm --execute
+else
+    cargo release "$level"
+    exit 0
+fi
+
+# Extract crate name and version using cargo metadata
+metadata=$(cargo metadata --no-deps --format-version 1)
+crate_name=$(echo "$metadata" | jq -r '.packages[0].name')
+new_version=$(echo "$metadata" | jq -r '.packages[0].version')
+
+# CI output
+if [[ -n "${CI:-}" ]]; then
+    echo "new_version=${new_version}" >> "$GITHUB_OUTPUT"
+fi
+
+# Rebuild commit and tag
+git reset --soft HEAD~1
+git commit -am "Publish ${crate_name} v${new_version}"
+git tag -a "${crate_name}@v${new_version}" -m "${crate_name} v${new_version}"

+ 37 - 0
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

+ 0 - 155
scripts/rust.mts

@@ -1,155 +0,0 @@
-#!/usr/bin/env zx
-
-// Script for working with Rust projects.
-
-import 'zx/globals';
-import {
-    getCargo,
-    getToolchainArgument,
-    parseCliArguments,
-    partitionArguments,
-    popArgument,
-    workingDirectory,
-} from './helpers/utils.mts';
-
-enum Command {
-    Format = 'format',
-    LintClippy = 'lint-clippy',
-    LintDocs = 'lint-docs',
-    LintFeatures = 'lint-features',
-    Lint = 'lint',
-    Test = 'test',
-    Wasm = 'wasm',
-    Publish = 'publish',
-}
-
-const { command, libraryPath, args } = parseCliArguments();
-const manifestPath = path.join(libraryPath, 'Cargo.toml');
-
-async function cargo(
-    toolchain: string,
-    command: string | string[],
-    defaultArgs?: string[],
-    variables?: [string, string][],
-) {
-    const [cargoArgs, commandArgs] = partitionArguments(args, '--', defaultArgs);
-    variables?.forEach(([k, v]) => $.env[k] = v);
-    await $`cargo ${toolchain} ${command} --manifest-path ${manifestPath} ${cargoArgs} -- ${commandArgs}`;
-}
-
-async function format() {
-    return cargo(
-        getToolchainArgument('format'),
-        'fmt',
-        popArgument(args, '--fix') ? [] : ['--', '--check'],
-    );
-}
-
-async function lintClippy() {
-    return cargo(
-        getToolchainArgument('lint'),
-        'clippy',
-        popArgument(args, '--fix') ? ['--fix'] : [],
-    );
-}
-
-async function lintDocs() {
-    return cargo(
-        getToolchainArgument('lint'),
-        'doc',
-        ['--all-features', '--no-deps'],
-        [['RUSTDOCFLAGS', '--cfg docsrs -D warnings']],
-    );
-}
-
-async function lintFeatures() {
-    return cargo(
-        getToolchainArgument('lint'),
-        ['hack', 'check'],
-        ['--feature-powerset', '--all-targets'],
-    );
-}
-
-async function test() {
-    return cargo(
-        getToolchainArgument('test'),
-        'test',
-        ['--all-features'],
-        [['SBF_OUT_DIR', path.join(workingDirectory, 'target', 'deploy')]]
-    );
-}
-
-async function wasm() {
-    await $`wasm-pack build --target nodejs --dev ${path.dirname(manifestPath)} --features bincode ${args}`;
-}
-
-async function publish() {
-    const dryRun = argv['dry-run'] ?? false;
-    const [level] = args;
-    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.dirname(manifestPath));
-
-    // 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 crate information.
-    const toml = getCargo(path.dirname(manifestPath));
-    const crateName = toml.package['name'];
-    const newVersion = toml.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 ${crateName} v${newVersion}"`;
-    
-    // Tag the new version.
-    await $`git tag -a ${crateName}@v${newVersion} -m "${crateName} v${newVersion}"`;
-}
-
-
-switch (command) {
-    case Command.Format:
-        await format();
-        break;
-    case Command.LintClippy:
-        await lintClippy();
-        break;
-    case Command.LintDocs:
-        await lintDocs();
-        break;
-    case Command.LintFeatures:
-        await lintFeatures();
-        break;
-    case Command.Lint:
-        await Promise.all([lintClippy(), lintDocs(), lintFeatures()]);
-        break;
-    case Command.Test:
-        await test();
-        break;
-    case Command.Wasm:
-        await wasm();
-        break;
-    case Command.Publish:
-        await publish();
-        break;
-    default:
-        throw new Error(`Unknown command: ${command}`);
-}

+ 10 - 0
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

+ 2 - 0
vars.env

@@ -0,0 +1,2 @@
+RUST_TOOLCHAIN_NIGHTLY="nightly-2024-11-22"
+SOLANA_CLI_VERSION="2.2.0"