From 256542cf6b8390b8f14422ef3ec7da4b25a227a6 Mon Sep 17 00:00:00 2001 From: Jinglun Date: Mon, 25 May 2026 16:23:08 -0700 Subject: [PATCH] chore: add repo guard for Rust/Anchor Adds .github/workflows/repo-guard.yml + scripts/repo-guard.ts that runs on every PR and locks down the toolchain, dependency, and CI surface to match origin/develop. Policy lives in .github/repo-guard.toml. Checks: - Cargo.lock freshness (`cargo metadata --locked`) - not bypassable - Root + sdk yarn.lock freshness (`yarn install --frozen-lockfile`) - not bypassable - Every program Cargo.toml dep uses `=x.y.z`, a `path = ..` workspace ref, or a git dep with a 40-char `rev` - anchor-lang / anchor-spl pinned to the same version across every program - `solana-program` crate pin in launchpads matches the value in Cargo.lock (currently =1.17.14, distinct from any CLI version) - Anchor.toml [toolchain].solana_version locked (currently 1.17.34, for local `anchor test` install only) - Per-workflow `solana-cli-version` locked. The split is intentional: 1.17.31 in anchor-test + generate-verifiable-builds (matches the `ellipsislabs/solana:` Docker image solana-verify uses to reproduce deployed .so bytes) 1.17.16 in deploy-buffer + verify-build (RPC tooling only, no compile) reusable-build.yaml reads from Cargo.lock via extract-versions, not in the map - Every third-party GitHub Action SHA-pinned to a value in [actions.sha_allowlist]. actions/* (GitHub-owned) exempt - Crates.io / npm minimum age (14d), scoped to PR-introduced changes - Sensitive-diff heuristics (review-assist): declare_id! changes, #[error_code] enum edits, hardcoded base58, unsafe blocks. Surfaces via PR comment + ::warning:: annotations. CODEOWNERS is the actual merge gate Compliance changes folded into this PR (so the guard passes on day one): - .github/CODEOWNERS routes program lib.rs, error.rs, manifests, and .github/ to @metanallok - Every Cargo.toml dep spec rewritten to `=x.y.z` (was `0.29.0` / `^0.29.0`) - Every yarn package.json dep rewritten to exact versions, both yarn.lock files refreshed - Third-party actions SHA-pinned with the tag preserved in a trailing comment for human readability - Every workflow given an explicit `permissions:` block (default `contents: read`, `contents: write` only on generate-verifiable-builds which commits .so artifacts) No Solana version normalization: every CLI version in workflows / Anchor.toml stays where it was on develop. The guard locks them in place. Bypass: - `emergency-override` label on a PR degrades guard findings (exact-pin, age, action-pinning, toolchain-version) from error to warning. Lockfile freshness is never bypassed. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/CODEOWNERS | 51 + .../solana/program-upgrade/action.yaml | 4 +- .../solana/write-idl-buffer/action.yaml | 6 +- .../solana/write-program-buffer/action.yaml | 4 +- .github/repo-guard.toml | 97 ++ .github/workflows/anchor-test.yaml | 5 +- .github/workflows/deploy-buffer.yaml | 7 +- .github/workflows/deploy-programs.yaml | 3 + .../workflows/generate-verifiable-builds.yaml | 45 +- .github/workflows/repo-guard.yml | 183 +++ .github/workflows/reusable-build.yaml | 15 +- .github/workflows/verify-build.yaml | 5 +- package.json | 85 +- programs/bid_wall/Cargo.toml | 6 +- programs/conditional_vault/Cargo.toml | 6 +- programs/damm_v2_cpi/Cargo.toml | 2 +- programs/futarchy/Cargo.toml | 6 +- programs/liquidation/Cargo.toml | 6 +- programs/mint_governor/Cargo.toml | 6 +- programs/performance_package_v2/Cargo.toml | 6 +- .../Cargo.toml | 6 +- programs/v06_launchpad/Cargo.toml | 6 +- programs/v07_launchpad/Cargo.toml | 6 +- programs/v08_launchpad/Cargo.toml | 6 +- scripts/repo-guard.ts | 1395 +++++++++++++++++ sdk/package.json | 64 +- sdk/yarn.lock | 62 +- yarn.lock | 212 +-- 28 files changed, 2026 insertions(+), 279 deletions(-) create mode 100644 .github/CODEOWNERS create mode 100644 .github/repo-guard.toml create mode 100644 .github/workflows/repo-guard.yml create mode 100644 scripts/repo-guard.ts diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 000000000..4912eb346 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,51 @@ +# Code owners for the futarchy programs repo. +# +# Threat model covered here: +# - On-chain program IDs (declare_id! sites) +# - Error code enums (Anchor assigns codes by variant position; reordering or +# inserting in the middle silently breaks deployed clients - see CLAUDE.md) +# - Anchor / Cargo build configuration (toolchain, deps, workspace layout) +# - Mainnet deploy and verification workflows +# - The repo-guard itself (config, script, workflow) - so it cannot be +# disabled without a security signoff + +# Program entry points (declare_id!) +/programs/bid_wall/src/lib.rs @metanallok +/programs/conditional_vault/src/lib.rs @metanallok +/programs/damm_v2_cpi/src/lib.rs @metanallok +/programs/futarchy/src/lib.rs @metanallok +/programs/liquidation/src/lib.rs @metanallok +/programs/mint_governor/src/lib.rs @metanallok +/programs/performance_package_v2/src/lib.rs @metanallok +/programs/price_based_performance_package/src/lib.rs @metanallok +/programs/v06_launchpad/src/lib.rs @metanallok +/programs/v07_launchpad/src/lib.rs @metanallok +/programs/v08_launchpad/src/lib.rs @metanallok + +# Error enums - position-sensitive, breaks deployed clients if reordered +/programs/bid_wall/src/error.rs @metanallok +/programs/conditional_vault/src/error.rs @metanallok +/programs/futarchy/src/error.rs @metanallok +/programs/liquidation/src/error.rs @metanallok +/programs/mint_governor/src/error.rs @metanallok +/programs/performance_package_v2/src/error.rs @metanallok +/programs/price_based_performance_package/src/error.rs @metanallok +/programs/v06_launchpad/src/error.rs @metanallok +/programs/v07_launchpad/src/error.rs @metanallok +/programs/v08_launchpad/src/error.rs @metanallok + +# Build configuration - toolchain, workspace layout, every program manifest +/Anchor.toml @metanallok +/Cargo.toml @metanallok +/Cargo.lock @metanallok +/programs/*/Cargo.toml @metanallok + +# CI / deploy workflows and the actions they call +/.github/ @metanallok +/.github/workflows/ @metanallok +/.github/actions/ @metanallok + +# The repo-guard itself - changes here must be reviewed +/.github/repo-guard.toml @metanallok +/.github/workflows/repo-guard.yml @metanallok +/scripts/repo-guard.ts @metanallok diff --git a/.github/actions/solana/program-upgrade/action.yaml b/.github/actions/solana/program-upgrade/action.yaml index e174adf37..e0da4b1e8 100644 --- a/.github/actions/solana/program-upgrade/action.yaml +++ b/.github/actions/solana/program-upgrade/action.yaml @@ -44,7 +44,7 @@ runs: - name: Deploy new program if: steps.check-program.outputs.exists == 'false' - uses: nick-fields/retry@v2 + uses: nick-fields/retry@14672906e672a08bd6eeb15720e9ed3ce869cdd4 # v2 with: timeout_minutes: 10 max_attempts: 3 @@ -58,7 +58,7 @@ runs: - name: Upgrade existing program if: steps.check-program.outputs.exists == 'true' - uses: nick-fields/retry@v2 + uses: nick-fields/retry@14672906e672a08bd6eeb15720e9ed3ce869cdd4 # v2 with: timeout_minutes: 10 max_attempts: 3 diff --git a/.github/actions/solana/write-idl-buffer/action.yaml b/.github/actions/solana/write-idl-buffer/action.yaml index 3e0f73d45..1e328007e 100644 --- a/.github/actions/solana/write-idl-buffer/action.yaml +++ b/.github/actions/solana/write-idl-buffer/action.yaml @@ -44,7 +44,7 @@ runs: - name: Write IDL buffer id: write-buffer if: steps.check-idl.outputs.exists == 'true' - uses: nick-fields/retry@v2 + uses: nick-fields/retry@14672906e672a08bd6eeb15720e9ed3ce869cdd4 # v2 with: timeout_minutes: 5 max_attempts: 3 @@ -74,7 +74,7 @@ runs: - name: Set Buffer Authority if: steps.write-buffer.outputs.buffer != '' - uses: nick-fields/retry@v2 + uses: nick-fields/retry@14672906e672a08bd6eeb15720e9ed3ce869cdd4 # v2 with: timeout_minutes: 5 max_attempts: 3 @@ -89,7 +89,7 @@ runs: - name: Set Program IDL Authority if: steps.write-buffer.outputs.buffer != '' - uses: nick-fields/retry@v2 + uses: nick-fields/retry@14672906e672a08bd6eeb15720e9ed3ce869cdd4 # v2 with: timeout_minutes: 5 max_attempts: 3 diff --git a/.github/actions/solana/write-program-buffer/action.yaml b/.github/actions/solana/write-program-buffer/action.yaml index 63ded0d3e..e09fcb109 100644 --- a/.github/actions/solana/write-program-buffer/action.yaml +++ b/.github/actions/solana/write-program-buffer/action.yaml @@ -57,7 +57,7 @@ runs: - name: Write program buffer id: write-buffer - uses: nick-fields/retry@v2 + uses: nick-fields/retry@14672906e672a08bd6eeb15720e9ed3ce869cdd4 # v2 with: timeout_minutes: 60 max_attempts: 3 @@ -94,7 +94,7 @@ runs: # If the deploy fails you can also close the buffer with the multisig using the cli command squad-closebuffer - name: Transfer buffer authority if: steps.check-program.outputs.exists == 'true' - uses: nick-fields/retry@v2 + uses: nick-fields/retry@14672906e672a08bd6eeb15720e9ed3ce869cdd4 # v2 with: timeout_minutes: 10 max_attempts: 50 diff --git a/.github/repo-guard.toml b/.github/repo-guard.toml new file mode 100644 index 000000000..c7533fff6 --- /dev/null +++ b/.github/repo-guard.toml @@ -0,0 +1,97 @@ +# Single source of truth for repo-guard policy. See scripts/repo-guard.ts and +# .github/workflows/repo-guard.yml for the checks that consume this file. +# +# Editing this file requires CODEOWNERS review. + +[toolchain] +# Anchor CLI version. Consistent across every workflow. +anchor_version = "0.29.0" + +# Solana CLI declared in Anchor.toml `[toolchain] solana_version`. Local-dev +# only: anchor test on a developer machine auto-installs this version. CI +# workflows pass their own solana-cli-version explicitly and ignore Anchor.toml. +local_dev_solana_version = "1.17.34" + +# Per-workflow Solana CLI versions. The split is intentional: +# +# 1.17.31 - build/test workflows that compile programs locally. This is the +# newest tag published as `ellipsislabs/solana:` on Docker +# Hub, which is what solana-verify uses to reproduce the deployed +# .so files. Changing this version changes the bytes that +# solana-verify expects, breaking verification of deployed +# programs unless they are rebuilt. +# +# 1.17.16 - CLI tooling workflows. These do not compile - they only invoke +# `solana program write-buffer` / `solana-verify --remote`, which +# talk to the cluster RPC. The version mostly does not matter; +# 1.17.16 is what the repo has used and there is no reason to +# move it. +# +# `reusable-build.yaml` is intentionally not in this map: it reads versions +# from Cargo.lock via `solana-developers/github-actions/extract-versions`, +# so the version is dynamic and stays in sync with the workspace. +[toolchain.workflow_solana_cli] +".github/workflows/anchor-test.yaml" = "1.17.31" +".github/workflows/generate-verifiable-builds.yaml" = "1.17.31" +".github/workflows/deploy-buffer.yaml" = "1.17.16" +".github/workflows/verify-build.yaml" = "1.17.16" + +[cargo] +# Every program's Cargo.toml must pin external deps with `=x.y.z`. Loose +# specs (^, ~, ranges, "*") fail. + +# anchor-lang and anchor-spl must be the version declared below across +# every program manifest. Cross-program divergence (program A pins =0.29.0 +# but program B pins =0.29.1) fails. +anchor_lang_version = "0.29.0" +anchor_spl_version = "0.29.0" + +# `solana-program` crate version. Distinct from any of the CLI versions +# above - this is the Solana primitives library that program binaries link +# against, and Cargo.lock is built around it. Currently pinned by the three +# launchpads (v06/v07/v08). The guard fails if any program pins a different +# version. Cargo.lock freshness independently catches drift between this +# pin and the resolved tree. +solana_program_version = "1.17.14" + +# Minimum age in days for a newly pinned crate version. The check is scoped +# to crates whose version differs from the PR base, so unrelated bumps that +# already landed do not re-trip the gate for the full window. +package_min_age_days = 14 + +[actions] +# Third-party GitHub Actions must be SHA-pinned. GitHub-owned actions (the +# `actions/*` namespace) may stay tag-pinned. The allowlist below maps +# action repos to the commit SHA we trust; the guard fails if a workflow +# references a SHA not in this list (or a non-SHA ref for a third-party +# action). +# +# To add a new third-party action: look up the SHA for the desired tag, +# add it here in a PR that also bumps the workflow reference. CODEOWNERS +# review is required. +[actions.sha_allowlist] +"metadaoproject/anchor-test" = ["876dde6990e0a3d22e1cf1c702b4e4c64aa47d15"] # v2.3 +"metadaoproject/anchor-verifiable-build" = ["6d8fc1999ea4b7ff701e8b166903b398741e1c50"] # v0.4 +"metadaoproject/setup-anchor" = ["7d1e9699eb18c33ba5f32f6a9952f0e90515996a"] # v3.2 +"nick-fields/retry" = [ + "ce71cc2ab81d554ebbe88c79ab5975992d79ba08", # v3 + "14672906e672a08bd6eeb15720e9ed3ce869cdd4", # v2 +] +"solana-developers/github-actions" = ["860d4e7d3afc9f180f3c5016593a1e86e77eede4"] # v0.2.5 +"solana-developers/squads-program-action" = ["5bb4fd81d1ec273b5ca002bb268afbc7dd11f24b"] # v0.3.0 +"EndBug/add-and-commit" = ["a94899bca583c204427a224a7af87c02f9b325d5"] # v9.1.4 +"peter-evans/find-comment" = ["3eae4d37986fb5a8592848f6a574fdf654e61f9e"] # v3 +"peter-evans/create-or-update-comment" = ["71345be0265236311c031f5c7866368bd1eff043"] # v4 + +[sensitive_diff] +# Files where any change should be surfaced for security review even if no +# heuristic matches. CODEOWNERS is the real merge gate; this is the +# review-assist signal in the PR comment + GitHub annotations. +files = [ + "Anchor.toml", + "Cargo.toml", + "Cargo.lock", + ".github/repo-guard.toml", + ".github/workflows/repo-guard.yml", + "scripts/repo-guard.ts", +] diff --git a/.github/workflows/anchor-test.yaml b/.github/workflows/anchor-test.yaml index 9dfdd6f92..5c10b7132 100644 --- a/.github/workflows/anchor-test.yaml +++ b/.github/workflows/anchor-test.yaml @@ -7,6 +7,9 @@ on: pull_request: workflow_dispatch: +permissions: + contents: read + env: HUSKY: 0 @@ -34,7 +37,7 @@ jobs: cd sdk yarn build - - uses: metadaoproject/anchor-test@v2.3 + - uses: metadaoproject/anchor-test@876dde6990e0a3d22e1cf1c702b4e4c64aa47d15 # v2.3 with: anchor-version: '0.29.0' solana-cli-version: '1.17.31' diff --git a/.github/workflows/deploy-buffer.yaml b/.github/workflows/deploy-buffer.yaml index b4833e11e..b98f43d1c 100644 --- a/.github/workflows/deploy-buffer.yaml +++ b/.github/workflows/deploy-buffer.yaml @@ -1,5 +1,8 @@ name: Deploy Buffer +permissions: + contents: read + env: HUSKY: 0 @@ -25,7 +28,7 @@ jobs: runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 - - uses: metadaoproject/setup-anchor@v3.2 + - uses: metadaoproject/setup-anchor@7d1e9699eb18c33ba5f32f6a9952f0e90515996a # v3.2 with: solana-cli-version: '1.17.16' anchor-version: '0.29.0' @@ -36,7 +39,7 @@ jobs: - run: solana-keygen new -s -o buffer-keypair --no-bip39-passphrase shell: bash - name: Deploy Buffer - uses: nick-fields/retry@v3 + uses: nick-fields/retry@ce71cc2ab81d554ebbe88c79ab5975992d79ba08 # v3 with: timeout_minutes: 30 max_attempts: 10 diff --git a/.github/workflows/deploy-programs.yaml b/.github/workflows/deploy-programs.yaml index 4d99d78cc..782380a08 100644 --- a/.github/workflows/deploy-programs.yaml +++ b/.github/workflows/deploy-programs.yaml @@ -24,6 +24,9 @@ on: default: "300000" type: string +permissions: + contents: read + jobs: conditional-vault-v4: if: inputs.program == 'conditional_vault_v4' diff --git a/.github/workflows/generate-verifiable-builds.yaml b/.github/workflows/generate-verifiable-builds.yaml index d7bbb7172..ddc882775 100644 --- a/.github/workflows/generate-verifiable-builds.yaml +++ b/.github/workflows/generate-verifiable-builds.yaml @@ -6,6 +6,11 @@ on: - production - develop +# Jobs commit the verifiable-build .so files back to the branch via +# EndBug/add-and-commit, so they need write access to repository contents. +permissions: + contents: write + env: HUSKY: 0 @@ -14,7 +19,7 @@ jobs: runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 - - uses: metadaoproject/anchor-verifiable-build@v0.4 + - uses: metadaoproject/anchor-verifiable-build@6d8fc1999ea4b7ff701e8b166903b398741e1c50 # v0.4 with: program: futarchy anchor-version: '0.29.0' @@ -23,7 +28,7 @@ jobs: - run: 'git pull --rebase' - run: cp target/deploy/futarchy.so ./verifiable-builds - name: Commit verifiable build back to mainline - uses: EndBug/add-and-commit@v9.1.4 + uses: EndBug/add-and-commit@a94899bca583c204427a224a7af87c02f9b325d5 # v9.1.4 with: default_author: github_actions message: 'Update futarchy verifiable build' @@ -31,7 +36,7 @@ jobs: runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 - - uses: metadaoproject/anchor-verifiable-build@v0.4 + - uses: metadaoproject/anchor-verifiable-build@6d8fc1999ea4b7ff701e8b166903b398741e1c50 # v0.4 with: program: conditional_vault anchor-version: '0.29.0' @@ -40,7 +45,7 @@ jobs: - run: 'git pull --rebase' - run: cp target/deploy/conditional_vault.so ./verifiable-builds - name: Commit verifiable build back to mainline - uses: EndBug/add-and-commit@v9.1.4 + uses: EndBug/add-and-commit@a94899bca583c204427a224a7af87c02f9b325d5 # v9.1.4 with: default_author: github_actions message: 'Update conditional_vault verifiable build' @@ -48,7 +53,7 @@ jobs: runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 - - uses: metadaoproject/anchor-verifiable-build@v0.4 + - uses: metadaoproject/anchor-verifiable-build@6d8fc1999ea4b7ff701e8b166903b398741e1c50 # v0.4 with: program: launchpad anchor-version: '0.29.0' @@ -57,7 +62,7 @@ jobs: - run: 'git pull --rebase' - run: cp target/deploy/launchpad.so ./verifiable-builds - name: Commit verifiable build back to mainline - uses: EndBug/add-and-commit@v9.1.4 + uses: EndBug/add-and-commit@a94899bca583c204427a224a7af87c02f9b325d5 # v9.1.4 with: default_author: github_actions message: 'Update launchpad_v6 verifiable build' @@ -65,7 +70,7 @@ jobs: runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 - - uses: metadaoproject/anchor-verifiable-build@v0.4 + - uses: metadaoproject/anchor-verifiable-build@6d8fc1999ea4b7ff701e8b166903b398741e1c50 # v0.4 with: program: price_based_performance_package anchor-version: '0.29.0' @@ -74,7 +79,7 @@ jobs: - run: 'git pull --rebase' - run: cp target/deploy/price_based_performance_package.so ./verifiable-builds - name: Commit verifiable build back to mainline - uses: EndBug/add-and-commit@v9.1.4 + uses: EndBug/add-and-commit@a94899bca583c204427a224a7af87c02f9b325d5 # v9.1.4 with: default_author: github_actions message: 'Update price_based_performance_package verifiable build' @@ -82,7 +87,7 @@ jobs: runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 - - uses: metadaoproject/anchor-verifiable-build@v0.4 + - uses: metadaoproject/anchor-verifiable-build@6d8fc1999ea4b7ff701e8b166903b398741e1c50 # v0.4 with: program: launchpad_v7 anchor-version: '0.29.0' @@ -91,7 +96,7 @@ jobs: - run: 'git pull --rebase' - run: cp target/deploy/launchpad_v7.so ./verifiable-builds - name: Commit verifiable build back to mainline - uses: EndBug/add-and-commit@v9.1.4 + uses: EndBug/add-and-commit@a94899bca583c204427a224a7af87c02f9b325d5 # v9.1.4 with: default_author: github_actions message: 'Update launchpad_v7 verifiable build' @@ -99,7 +104,7 @@ jobs: runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 - - uses: metadaoproject/anchor-verifiable-build@v0.4 + - uses: metadaoproject/anchor-verifiable-build@6d8fc1999ea4b7ff701e8b166903b398741e1c50 # v0.4 with: program: bid_wall anchor-version: '0.29.0' @@ -108,7 +113,7 @@ jobs: - run: 'git pull --rebase' - run: cp target/deploy/bid_wall.so ./verifiable-builds - name: Commit verifiable build back to mainline - uses: EndBug/add-and-commit@v9.1.4 + uses: EndBug/add-and-commit@a94899bca583c204427a224a7af87c02f9b325d5 # v9.1.4 with: default_author: github_actions message: 'Update bid_wall verifiable build' @@ -116,7 +121,7 @@ jobs: runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 - - uses: metadaoproject/anchor-verifiable-build@v0.4 + - uses: metadaoproject/anchor-verifiable-build@6d8fc1999ea4b7ff701e8b166903b398741e1c50 # v0.4 with: program: liquidation anchor-version: '0.29.0' @@ -125,7 +130,7 @@ jobs: - run: 'git pull --rebase' - run: cp target/deploy/liquidation.so ./verifiable-builds - name: Commit verifiable build back to mainline - uses: EndBug/add-and-commit@v9.1.4 + uses: EndBug/add-and-commit@a94899bca583c204427a224a7af87c02f9b325d5 # v9.1.4 with: default_author: github_actions message: 'Update liquidation verifiable build' @@ -133,7 +138,7 @@ jobs: runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 - - uses: metadaoproject/anchor-verifiable-build@v0.4 + - uses: metadaoproject/anchor-verifiable-build@6d8fc1999ea4b7ff701e8b166903b398741e1c50 # v0.4 with: program: mint_governor anchor-version: '0.29.0' @@ -142,7 +147,7 @@ jobs: - run: 'git pull --rebase' - run: cp target/deploy/mint_governor.so ./verifiable-builds - name: Commit verifiable build back to mainline - uses: EndBug/add-and-commit@v9.1.4 + uses: EndBug/add-and-commit@a94899bca583c204427a224a7af87c02f9b325d5 # v9.1.4 with: default_author: github_actions message: 'Update mint_governor verifiable build' @@ -150,7 +155,7 @@ jobs: runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 - - uses: metadaoproject/anchor-verifiable-build@v0.4 + - uses: metadaoproject/anchor-verifiable-build@6d8fc1999ea4b7ff701e8b166903b398741e1c50 # v0.4 with: program: performance_package_v2 anchor-version: '0.29.0' @@ -159,7 +164,7 @@ jobs: - run: 'git pull --rebase' - run: cp target/deploy/performance_package_v2.so ./verifiable-builds - name: Commit verifiable build back to mainline - uses: EndBug/add-and-commit@v9.1.4 + uses: EndBug/add-and-commit@a94899bca583c204427a224a7af87c02f9b325d5 # v9.1.4 with: default_author: github_actions message: 'Update performance_package_v2 verifiable build' @@ -167,7 +172,7 @@ jobs: runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 - - uses: metadaoproject/anchor-verifiable-build@v0.4 + - uses: metadaoproject/anchor-verifiable-build@6d8fc1999ea4b7ff701e8b166903b398741e1c50 # v0.4 with: program: launchpad_v8 anchor-version: '0.29.0' @@ -176,7 +181,7 @@ jobs: - run: 'git pull --rebase' - run: cp target/deploy/launchpad_v8.so ./verifiable-builds - name: Commit verifiable build back to mainline - uses: EndBug/add-and-commit@v9.1.4 + uses: EndBug/add-and-commit@a94899bca583c204427a224a7af87c02f9b325d5 # v9.1.4 with: default_author: github_actions message: 'Update launchpad_v8 verifiable build' \ No newline at end of file diff --git a/.github/workflows/repo-guard.yml b/.github/workflows/repo-guard.yml new file mode 100644 index 000000000..966f3d60d --- /dev/null +++ b/.github/workflows/repo-guard.yml @@ -0,0 +1,183 @@ +name: Repository Guard + +on: + pull_request: + +permissions: + contents: read + pull-requests: write + +jobs: + repository-guard: + runs-on: ubuntu-22.04 + env: + EMERGENCY_BYPASS: ${{ contains(github.event.pull_request.labels.*.name, 'emergency-override') }} + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Fetch PR base branch + run: git fetch origin "${{ github.base_ref }}" --depth=1 + + - name: Show Cargo / Node versions + run: | + cargo --version + node --version + + - name: Verify Cargo.lock is up to date + id: cargo_lock + continue-on-error: true + # `cargo metadata --locked` resolves the workspace without modifying + # Cargo.lock; if anything is out of sync this fails. We allow network + # so the git dep on Squads can be resolved. + run: cargo metadata --locked --format-version 1 > /dev/null + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20.18.0' + cache: 'yarn' + + - name: Verify root yarn.lock is up to date + id: yarn_root + continue-on-error: true + run: yarn install --frozen-lockfile --ignore-scripts --non-interactive + + - name: Verify sdk yarn.lock is up to date + id: yarn_sdk + continue-on-error: true + run: | + cd sdk + yarn install --frozen-lockfile --ignore-scripts --non-interactive + + - name: Run repository guard checks + id: guard + continue-on-error: true + env: + GITHUB_BASE_REF: ${{ github.base_ref }} + REPO_GUARD_SUMMARY_PATH: repo-guard-summary.md + # Only run the guard if root yarn install succeeded - otherwise tsx + # is not installed and the script cannot run. + if: steps.yarn_root.outcome == 'success' + run: yarn repo:guard + + - name: Build PR comment + id: comment + env: + CARGO_OUTCOME: ${{ steps.cargo_lock.outcome }} + YARN_ROOT_OUTCOME: ${{ steps.yarn_root.outcome }} + YARN_SDK_OUTCOME: ${{ steps.yarn_sdk.outcome }} + GUARD_OUTCOME: ${{ steps.guard.outcome }} + run: | + { + echo "" + echo "**Repository Guard**" + echo + + if [ "$CARGO_OUTCOME" = "success" ]; then + echo "- Cargo.lock: pass" + else + echo "- Cargo.lock: fail" + echo " - Out of sync with the workspace manifests. Run \`cargo update --workspace\` (or rebuild) and commit the updated \`Cargo.lock\`." + fi + + if [ "$YARN_ROOT_OUTCOME" = "success" ]; then + echo "- yarn.lock (root): pass" + else + echo "- yarn.lock (root): fail" + echo " - Root \`yarn.lock\` is out of date. Run \`yarn install\` at the repo root and commit the result." + fi + + if [ "$YARN_SDK_OUTCOME" = "success" ]; then + echo "- yarn.lock (sdk): pass" + else + echo "- yarn.lock (sdk): fail" + echo " - \`sdk/yarn.lock\` is out of date. Run \`yarn install\` in \`sdk/\` and commit the result." + fi + + if [ "$GUARD_OUTCOME" = "success" ]; then + echo "- Repo guard: pass" + elif [ "$GUARD_OUTCOME" = "skipped" ]; then + echo "- Repo guard: skipped (root yarn install failed - fix that first)" + else + if [ "$EMERGENCY_BYPASS" = "true" ]; then + echo "- Repo guard: bypassed with \`emergency-override\`" + else + echo "- Repo guard: fail" + fi + fi + + echo + if [ -f repo-guard-summary.md ]; then + cat repo-guard-summary.md + else + echo "_Repository guard summary was not generated._" + fi + } > body.md + + { + echo "body<> "$GITHUB_OUTPUT" + + - name: Find existing comment + uses: peter-evans/find-comment@3eae4d37986fb5a8592848f6a574fdf654e61f9e # v3 + id: find + with: + issue-number: ${{ github.event.pull_request.number }} + body-includes: "" + + - name: Create or update PR comment + uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4 + with: + issue-number: ${{ github.event.pull_request.number }} + comment-id: ${{ steps.find.outputs.comment-id }} + body: ${{ steps.comment.outputs.body }} + edit-mode: replace + + - name: Fail if any check failed + env: + CARGO_OUTCOME: ${{ steps.cargo_lock.outcome }} + YARN_ROOT_OUTCOME: ${{ steps.yarn_root.outcome }} + YARN_SDK_OUTCOME: ${{ steps.yarn_sdk.outcome }} + GUARD_OUTCOME: ${{ steps.guard.outcome }} + run: | + failed=() + bypassed=() + + # Lockfile failures are NEVER bypassable - a stale lockfile breaks + # builds regardless of override labels. + if [ "$CARGO_OUTCOME" != "success" ]; then + failed+=("Cargo.lock out of sync - run \`cargo update --workspace\` (or rebuild) and commit") + fi + if [ "$YARN_ROOT_OUTCOME" != "success" ]; then + failed+=("root yarn.lock out of date - run \`yarn install\` at repo root and commit") + fi + if [ "$YARN_SDK_OUTCOME" != "success" ]; then + failed+=("sdk yarn.lock out of date - run \`yarn install\` in \`sdk/\` and commit") + fi + + # The guard itself (exact-version, age, action-pinning, toolchain + # consistency, sensitive-diff) is bypassable. + if [ "$GUARD_OUTCOME" = "failure" ]; then + if [ "$EMERGENCY_BYPASS" = "true" ]; then + bypassed+=("repo guard") + else + failed+=("repo guard - see the \"Run repository guard checks\" step logs and Files Changed annotations") + fi + fi + + if [ ${#bypassed[@]} -gt 0 ]; then + echo "::warning::Bypassed via emergency-override label: ${bypassed[*]}" + fi + + if [ ${#failed[@]} -gt 0 ]; then + echo "::error::Repository Guard failed:" + for item in "${failed[@]}"; do + echo "::error:: - ${item}" + done + exit 1 + fi diff --git a/.github/workflows/reusable-build.yaml b/.github/workflows/reusable-build.yaml index 99a8cd925..1ebe3ed68 100644 --- a/.github/workflows/reusable-build.yaml +++ b/.github/workflows/reusable-build.yaml @@ -1,5 +1,8 @@ name: Reusable Build Solana Program +permissions: + contents: read + on: workflow_call: inputs: @@ -133,11 +136,11 @@ jobs: echo "MULTISIG_VAULT=${{ secrets.DEVNET_MULTISIG_VAULT }}" >> $GITHUB_ENV fi - - uses: solana-developers/github-actions/extract-versions@v0.2.5 + - uses: solana-developers/github-actions/extract-versions@860d4e7d3afc9f180f3c5016593a1e86e77eede4 # v0.2.5 if: inputs.override-solana-version == '' || inputs.override-anchor-version == '' id: versions - - uses: solana-developers/github-actions/setup-all@v0.2.5 + - uses: solana-developers/github-actions/setup-all@860d4e7d3afc9f180f3c5016593a1e86e77eede4 # v0.2.5 id: setup with: solana_version: ${{ inputs.override-solana-version != '' && inputs.override-solana-version || steps.versions.outputs.solana_version }} @@ -261,14 +264,14 @@ jobs: fi - name: Build Anchor - uses: solana-developers/github-actions/build-anchor@v0.2.5 + uses: solana-developers/github-actions/build-anchor@860d4e7d3afc9f180f3c5016593a1e86e77eede4 # v0.2.5 if: steps.check-anchor.outputs.is_anchor == 'true' with: program: ${{ env.PROGRAM_NAME }} features: ${{ inputs.features }} - name: Build Verified - uses: solana-developers/github-actions/build-verified@v0.2.5 + uses: solana-developers/github-actions/build-verified@860d4e7d3afc9f180f3c5016593a1e86e77eede4 # v0.2.5 id: build-verified with: program: ${{ env.PROGRAM_NAME }} @@ -372,7 +375,7 @@ jobs: program-keypair: ${{ secrets.PROGRAM_ADDRESS_KEYPAIR }} - name: IDL Upload - uses: solana-developers/github-actions/idl-upload@v0.2.5 + uses: solana-developers/github-actions/idl-upload@860d4e7d3afc9f180f3c5016593a1e86e77eede4 # v0.2.5 if: inputs.upload_idl && inputs.use-squads == false with: program-id: ${{ env.PROGRAM_ID }} @@ -402,7 +405,7 @@ jobs: - name: Create squads program upgrade transaction (set Idl buffer, verify pda, set program buffer) if: inputs.deploy && inputs.use-squads - uses: solana-developers/squads-program-action@v0.3.0 + uses: solana-developers/squads-program-action@5bb4fd81d1ec273b5ca002bb268afbc7dd11f24b # v0.3.0 with: rpc: ${{ env.DEPLOY_URL }} program: ${{ env.PROGRAM_ID }} diff --git a/.github/workflows/verify-build.yaml b/.github/workflows/verify-build.yaml index 0b6defc67..56d29c9ee 100644 --- a/.github/workflows/verify-build.yaml +++ b/.github/workflows/verify-build.yaml @@ -1,5 +1,8 @@ name: Verify Build +permissions: + contents: read + env: HUSKY: 0 @@ -37,7 +40,7 @@ jobs: runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 - - uses: metadaoproject/setup-anchor@v3.2 + - uses: metadaoproject/setup-anchor@7d1e9699eb18c33ba5f32f6a9952f0e90515996a # v3.2 with: anchor-version: ${{ inputs.anchor-version }} solana-cli-version: ${{ inputs.solana-cli-version }} diff --git a/package.json b/package.json index cda3e841c..c78179d43 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "lint:fix": "prettier */*{.js,.ts} \"*/**/*{.js,.ts}\" -w", "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check", "typecheck": "tsc --noEmit", + "repo:guard": "tsx scripts/repo-guard.ts", "setup-metric-market": "tsx --tsconfig tsconfig.json scripts/setupMetricMarket.ts", "launch-init": "NODE_OPTIONS=\"--no-deprecation\" tsx --tsconfig tsconfig.json scripts/launchInit.ts", "launch-start": "NODE_OPTIONS=\"--no-deprecation\" tsx --tsconfig tsconfig.json scripts/launchStart.ts", @@ -23,54 +24,54 @@ ] }, "dependencies": { - "@coral-xyz/anchor": "=0.29.0", - "@inquirer/prompts": "^7.3.3", + "@coral-xyz/anchor": "0.29.0", + "@inquirer/prompts": "7.9.0", "@metadaoproject/programs": "./sdk", - "@metaplex-foundation/mpl-token-metadata": "^3.2.0", - "@metaplex-foundation/umi": "^0.9.1", - "@metaplex-foundation/umi-bundle-defaults": "^0.9.1", - "@metaplex-foundation/umi-signer-wallet-adapters": "^1.1.1", - "@metaplex-foundation/umi-uploader-bundlr": "^0.9.1", - "@metaplex-foundation/umi-web3js-adapters": "^1.1.1", - "@meteora-ag/cp-amm-sdk": "^1.2.6", - "@noble/ed25519": "^2.0.0", - "@noble/secp256k1": "^2.0.0", - "@solana/spl-token": "^0.3.7", - "@solana/web3.js": "=1.76.0", - "@sqds/multisig": "^2.1.4", - "anchor-bankrun": "^0.3.0", - "anchor-litesvm": "^0.1.2", - "arweave": "^1.14.4", - "bs58": "^6.0.0", - "litesvm": "^0.2.0", + "@metaplex-foundation/mpl-token-metadata": "3.4.0", + "@metaplex-foundation/umi": "0.9.2", + "@metaplex-foundation/umi-bundle-defaults": "0.9.2", + "@metaplex-foundation/umi-signer-wallet-adapters": "1.4.1", + "@metaplex-foundation/umi-uploader-bundlr": "0.9.2", + "@metaplex-foundation/umi-web3js-adapters": "1.4.1", + "@meteora-ag/cp-amm-sdk": "1.2.6", + "@noble/ed25519": "2.3.0", + "@noble/secp256k1": "2.3.0", + "@solana/spl-token": "0.3.11", + "@solana/web3.js": "1.76.0", + "@sqds/multisig": "2.1.4", + "anchor-bankrun": "0.3.0", + "anchor-litesvm": "0.1.2", + "arweave": "1.15.7", + "bs58": "6.0.0", + "litesvm": "0.2.0", "rpc-websockets": "7.5.0", - "solana-bankrun": "^0.3.0", + "solana-bankrun": "0.3.1", "spl-token-bankrun": "0.2.6" }, "devDependencies": { - "@eslint/js": "^9.35.0", - "@solana/spl-memo": "^0.2.3", - "@solana/spl-token-registry": "^0.2.4574", - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.3.0", - "@types/inquirer": "^9.0.7", - "@types/mocha": "^10.0.7", - "@types/node": "^20.8.6", - "chai": "^4.3.4", - "dotenv": "^16.4.7", - "eslint": "^9.35.0", - "eslint-plugin-unused-imports": "^4.2.0", - "globals": "^16.4.0", - "husky": "^9.1.7", - "jiti": "^2.5.1", - "lint-staged": "^16.2.0", - "mocha": "^9.0.3", - "prettier": "^3.6.2", - "ts-mocha": "^10.0.0", - "ts-node": "^10.9.2", - "tsx": "^4.7.1", + "@eslint/js": "9.38.0", + "@solana/spl-memo": "0.2.5", + "@solana/spl-token-registry": "0.2.4574", + "@types/bn.js": "5.2.0", + "@types/chai": "4.3.20", + "@types/inquirer": "9.0.9", + "@types/mocha": "10.0.10", + "@types/node": "20.19.23", + "chai": "4.5.0", + "dotenv": "16.6.1", + "eslint": "9.38.0", + "eslint-plugin-unused-imports": "4.3.0", + "globals": "16.4.0", + "husky": "9.1.7", + "jiti": "2.6.1", + "lint-staged": "16.2.5", + "mocha": "9.2.2", + "prettier": "3.6.2", + "ts-mocha": "10.1.0", + "ts-node": "10.9.2", + "tsx": "4.20.6", "typescript": "5.9.3", - "typescript-eslint": "^8.43.0" + "typescript-eslint": "8.46.2" }, "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e", "version": "0.5.0-alpha.1" diff --git a/programs/bid_wall/Cargo.toml b/programs/bid_wall/Cargo.toml index 9d2606da7..a711bbb2b 100644 --- a/programs/bid_wall/Cargo.toml +++ b/programs/bid_wall/Cargo.toml @@ -17,6 +17,6 @@ default = [] production = [] [dependencies] -anchor-lang = { version = "0.29.0", features = ["event-cpi", "init-if-needed"] } -anchor-spl = "0.29.0" -solana-security-txt = "1.1.1" +anchor-lang = { version = "=0.29.0", features = ["event-cpi", "init-if-needed"] } +anchor-spl = "=0.29.0" +solana-security-txt = "=1.1.1" diff --git a/programs/conditional_vault/Cargo.toml b/programs/conditional_vault/Cargo.toml index 540e1a327..e3318ddac 100644 --- a/programs/conditional_vault/Cargo.toml +++ b/programs/conditional_vault/Cargo.toml @@ -17,6 +17,6 @@ default = [] production = [] [dependencies] -anchor-lang = { version = "0.29.0", features = ["init-if-needed", "event-cpi"] } -anchor-spl = { version = "0.29.0", features = ["metadata"] } -solana-security-txt = "1.1.1" +anchor-lang = { version = "=0.29.0", features = ["init-if-needed", "event-cpi"] } +anchor-spl = { version = "=0.29.0", features = ["metadata"] } +solana-security-txt = "=1.1.1" diff --git a/programs/damm_v2_cpi/Cargo.toml b/programs/damm_v2_cpi/Cargo.toml index e37cf68b5..e1194a796 100644 --- a/programs/damm_v2_cpi/Cargo.toml +++ b/programs/damm_v2_cpi/Cargo.toml @@ -16,4 +16,4 @@ cpi = ["no-entrypoint"] default = [] [dependencies] -anchor-lang = { version = "0.29.0", features = ["event-cpi"] } +anchor-lang = { version = "=0.29.0", features = ["event-cpi"] } diff --git a/programs/futarchy/Cargo.toml b/programs/futarchy/Cargo.toml index 9e9d44763..d95d70295 100644 --- a/programs/futarchy/Cargo.toml +++ b/programs/futarchy/Cargo.toml @@ -17,9 +17,9 @@ default = [] production = [] [dependencies] -anchor-lang = "^0.29.0" -anchor-spl = "^0.29.0" -solana-security-txt = "1.1.1" +anchor-lang = "=0.29.0" +anchor-spl = "=0.29.0" +solana-security-txt = "=1.1.1" conditional_vault = { path = "../conditional_vault", features = ["cpi"] } squads-multisig-program = { git = "https://github.com/Squads-Protocol/v4", package = "squads-multisig-program", rev = "6d5235da621a2e9b7379ea358e48760e981053be", features = ["cpi"] } damm_v2_cpi = { path = "../damm_v2_cpi", features = ["cpi"] } diff --git a/programs/liquidation/Cargo.toml b/programs/liquidation/Cargo.toml index b567ab434..4b400389c 100644 --- a/programs/liquidation/Cargo.toml +++ b/programs/liquidation/Cargo.toml @@ -17,6 +17,6 @@ default = [] production = [] [dependencies] -anchor-lang = { version = "0.29.0", features = ["event-cpi", "init-if-needed"] } -anchor-spl = "0.29.0" -solana-security-txt = "1.1.1" +anchor-lang = { version = "=0.29.0", features = ["event-cpi", "init-if-needed"] } +anchor-spl = "=0.29.0" +solana-security-txt = "=1.1.1" diff --git a/programs/mint_governor/Cargo.toml b/programs/mint_governor/Cargo.toml index a905ea84a..59986a36d 100644 --- a/programs/mint_governor/Cargo.toml +++ b/programs/mint_governor/Cargo.toml @@ -17,6 +17,6 @@ default = [] production = [] [dependencies] -anchor-lang = { version = "0.29.0", features = ["init-if-needed", "event-cpi"] } -anchor-spl = "0.29.0" -solana-security-txt = "1.1.1" +anchor-lang = { version = "=0.29.0", features = ["init-if-needed", "event-cpi"] } +anchor-spl = "=0.29.0" +solana-security-txt = "=1.1.1" diff --git a/programs/performance_package_v2/Cargo.toml b/programs/performance_package_v2/Cargo.toml index 5fbd69bd8..ad3b14516 100644 --- a/programs/performance_package_v2/Cargo.toml +++ b/programs/performance_package_v2/Cargo.toml @@ -17,8 +17,8 @@ default = [] production = [] [dependencies] -anchor-lang = { version = "0.29.0", features = ["init-if-needed", "event-cpi"] } -anchor-spl = "0.29.0" -solana-security-txt = "1.1.1" +anchor-lang = { version = "=0.29.0", features = ["init-if-needed", "event-cpi"] } +anchor-spl = "=0.29.0" +solana-security-txt = "=1.1.1" mint_governor = { path = "../mint_governor", features = ["cpi"] } futarchy = { path = "../futarchy", features = ["cpi"] } diff --git a/programs/price_based_performance_package/Cargo.toml b/programs/price_based_performance_package/Cargo.toml index 393ae15b5..e2a29a48d 100644 --- a/programs/price_based_performance_package/Cargo.toml +++ b/programs/price_based_performance_package/Cargo.toml @@ -17,6 +17,6 @@ default = [] production = [] [dependencies] -anchor-lang = { version = "0.29.0", features = ["init-if-needed", "event-cpi"] } -anchor-spl = "0.29.0" -solana-security-txt = "1.1.1" +anchor-lang = { version = "=0.29.0", features = ["init-if-needed", "event-cpi"] } +anchor-spl = "=0.29.0" +solana-security-txt = "=1.1.1" diff --git a/programs/v06_launchpad/Cargo.toml b/programs/v06_launchpad/Cargo.toml index cb6e19bdc..6b56c8dfa 100644 --- a/programs/v06_launchpad/Cargo.toml +++ b/programs/v06_launchpad/Cargo.toml @@ -19,14 +19,14 @@ production = [] custom-heap = [] [dependencies] -anchor-lang = "0.29.0" -anchor-spl = "0.29.0" +anchor-lang = "=0.29.0" +anchor-spl = "=0.29.0" futarchy = { path = "../futarchy", features = ["cpi"] } price_based_performance_package = { path = "../price_based_performance_package", features = ["cpi"] } spl-memo = "=4.0.0" solana-program = "=1.17.14" spl-token = "=4.0.0" ahash = "=0.8.6" -solana-security-txt = "1.1.1" +solana-security-txt = "=1.1.1" squads-multisig-program = { git = "https://github.com/Squads-Protocol/v4", package = "squads-multisig-program", rev = "6d5235da621a2e9b7379ea358e48760e981053be", features = ["cpi"] } damm_v2_cpi = { path = "../damm_v2_cpi", features = ["cpi"] } diff --git a/programs/v07_launchpad/Cargo.toml b/programs/v07_launchpad/Cargo.toml index 556558adf..a81326e89 100644 --- a/programs/v07_launchpad/Cargo.toml +++ b/programs/v07_launchpad/Cargo.toml @@ -19,15 +19,15 @@ production = [] custom-heap = [] [dependencies] -anchor-lang = "0.29.0" -anchor-spl = "0.29.0" +anchor-lang = "=0.29.0" +anchor-spl = "=0.29.0" futarchy = { path = "../futarchy", features = ["cpi"] } price_based_performance_package = { path = "../price_based_performance_package", features = ["cpi"] } spl-memo = "=4.0.0" solana-program = "=1.17.14" spl-token = "=4.0.0" ahash = "=0.8.6" -solana-security-txt = "1.1.1" +solana-security-txt = "=1.1.1" squads-multisig-program = { git = "https://github.com/Squads-Protocol/v4", package = "squads-multisig-program", rev = "6d5235da621a2e9b7379ea358e48760e981053be", features = ["cpi"] } damm_v2_cpi = { path = "../damm_v2_cpi", features = ["cpi"] } bid_wall = { path = "../bid_wall", features = ["cpi"] } \ No newline at end of file diff --git a/programs/v08_launchpad/Cargo.toml b/programs/v08_launchpad/Cargo.toml index d2f0d277f..99a957b47 100644 --- a/programs/v08_launchpad/Cargo.toml +++ b/programs/v08_launchpad/Cargo.toml @@ -19,8 +19,8 @@ production = [] custom-heap = [] [dependencies] -anchor-lang = { version = "0.29.0", features = ["init-if-needed", "event-cpi"] } -anchor-spl = "0.29.0" +anchor-lang = { version = "=0.29.0", features = ["init-if-needed", "event-cpi"] } +anchor-spl = "=0.29.0" futarchy = { path = "../futarchy", features = ["cpi"] } performance_package_v2 = { path = "../performance_package_v2", features = ["cpi"] } mint_governor = { path = "../mint_governor", features = ["cpi"] } @@ -28,7 +28,7 @@ spl-memo = "=4.0.0" solana-program = "=1.17.14" spl-token = "=4.0.0" ahash = "=0.8.6" -solana-security-txt = "1.1.1" +solana-security-txt = "=1.1.1" squads-multisig-program = { git = "https://github.com/Squads-Protocol/v4", package = "squads-multisig-program", rev = "6d5235da621a2e9b7379ea358e48760e981053be", features = ["cpi"] } damm_v2_cpi = { path = "../damm_v2_cpi", features = ["cpi"] } bid_wall = { path = "../bid_wall", features = ["cpi"] } diff --git a/scripts/repo-guard.ts b/scripts/repo-guard.ts new file mode 100644 index 000000000..d82a11268 --- /dev/null +++ b/scripts/repo-guard.ts @@ -0,0 +1,1395 @@ +// Repository Guard for the futarchy programs repo. +// +// Reads .github/repo-guard.toml as policy and runs the checks below. +// Companion workflow .github/workflows/repo-guard.yml posts a PR comment +// summarising the results. +// +// Checks: +// 1. Cargo manifests pin every external dep with `=x.y.z`. +// 2. anchor-lang / anchor-spl versions across programs match the value +// declared in repo-guard.toml [cargo] - no cross-program drift. +// 3. `solana-program` crate pin in launchpads must match the value in +// [cargo].solana_program_version. Distinct from any CLI version. +// 4. Anchor.toml [toolchain].solana_version must match +// [toolchain].local_dev_solana_version. +// 5. Crates.io minimum age (scoped to PR-introduced version changes). +// 6. Yarn package.json files use exact versions (no ^, ~, ranges). +// 7. npm registry minimum age for new yarn pins. +// 8. anchor-version in every workflow is [toolchain].anchor_version. +// solana-cli-version is checked per-file against +// [toolchain.workflow_solana_cli]. Workflows not in the map are +// assumed to read versions from Cargo.lock (e.g. reusable-build.yaml). +// 9. Every third-party GitHub Action is pinned to a SHA from the +// [actions.sha_allowlist] in repo-guard.toml. actions/* (GitHub-owned) +// are exempt. +// 10. Sensitive-diff heuristics (review-assist, not a merge gate): +// changes to declare_id! literals, #[error_code] enums, Anchor.toml +// [programs.*], or files listed in [sensitive_diff.files]. +// +// Lockfile freshness (Cargo.lock + yarn.lock) is checked by the workflow +// directly via `cargo metadata --locked` and `yarn install --frozen-lockfile`, +// so it cannot be bypassed even if this script is disabled. + +import { execFileSync } from "node:child_process"; +import { readdirSync, readFileSync, writeFileSync, existsSync } from "node:fs"; +import { dirname, join, relative, resolve } from "node:path"; + +// --- Types --- + +type CheckStatus = "pass" | "fail" | "skip" | "warn"; + +type GuardConfig = { + anchorVersion: string; + localDevSolanaVersion: string; + workflowSolanaCli: Map; + anchorLangVersion: string; + anchorSplVersion: string; + solanaProgramVersion: string; + packageMinAgeDays: number; + actionShaAllowlist: Map>; + sensitiveFiles: Set; +}; + +type CargoViolation = { + file: string; + dependency: string; + reason: string; + spec: string; +}; + +type CrossProgramViolation = { + dependency: string; + expected: string; + variants: Array<{ file: string; spec: string }>; +}; + +type WorkflowVersionViolation = { + file: string; + line: number; + key: "anchor-version" | "solana-cli-version"; + actual: string; + expected: string; +}; + +type WorkflowActionViolation = { + file: string; + line: number; + action: string; + reason: string; +}; + +type PackageJsonViolation = { + file: string; + section: string; + dependency: string; + spec: string; +}; + +type CrateAgeViolation = { + crate: string; + version: string; + publishedAt: string; + ageDays: number; + usedIn: string[]; +}; + +type NpmAgeViolation = { + dependency: string; + version: string; + publishedAt: string; + ageDays: number; + usedIn: string[]; +}; + +type SensitiveFinding = { + file: string; + line: number; + kind: string; + text: string; +}; + +// --- Constants --- + +const ROOT = process.cwd(); +const SUMMARY_PATH = + process.env.REPO_GUARD_SUMMARY_PATH ?? + join(process.env.TMPDIR ?? "/tmp", "repo-guard-summary.md"); +const BASE_REF = process.env.GITHUB_BASE_REF ?? ""; +const IS_CI = process.env.CI === "true"; +const CONFIG_PATH = join(ROOT, ".github", "repo-guard.toml"); + +const cargoExactPattern = /^=\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/; +const npmExactPattern = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/; +const sha40Pattern = /^[0-9a-f]{40}$/; + +const cargoIgnoredDirectories = new Set([".git", "target", "node_modules"]); +const packageJsonIgnored = new Set([".git", "node_modules", "dist", "target"]); + +// Surfaces where heuristics should ignore matches; this file declares the +// rules themselves. +const sensitiveExcludedFiles = new Set([ + "scripts/repo-guard.ts", + ".github/repo-guard.toml", + ".github/CODEOWNERS", + ".github/workflows/repo-guard.yml", +]); + +// --- Tiny TOML reader --- +// +// The config file is intentionally simple: flat tables + the +// [actions.sha_allowlist] sub-table. We avoid a TOML dependency to keep +// the script's surface area small. Supports: `key = "string"`, +// `key = number`, `key = ["a", "b"]`, `[section]`, `[section.sub]`, +// quoted keys. + +type TomlValue = string | number | string[]; + +function parseToml(text: string): Record> { + const result: Record> = {}; + let currentSection: Record | null = null; + const lines = text.split("\n"); + + for (let i = 0; i < lines.length; i += 1) { + const raw = lines[i]!; + const line = raw.replace(/\s*#.*$/, "").trim(); + if (!line) continue; + + const sectionMatch = line.match(/^\[([A-Za-z0-9_.]+)\]$/); + if (sectionMatch) { + const name = sectionMatch[1]!; + result[name] = result[name] ?? {}; + currentSection = result[name]!; + continue; + } + + if (!currentSection) { + throw new Error(`repo-guard.toml line ${i + 1}: value outside section`); + } + + const keyMatch = line.match(/^(?:"([^"]+)"|([A-Za-z0-9_-]+))\s*=\s*(.+)$/); + if (!keyMatch) { + throw new Error(`repo-guard.toml line ${i + 1}: cannot parse: ${line}`); + } + const key = keyMatch[1] ?? keyMatch[2]!; + let valuePart = keyMatch[3]!; + + if (valuePart.startsWith("[") && !valuePart.endsWith("]")) { + // multi-line array + let buffer = valuePart; + while (!buffer.trimEnd().endsWith("]") && i + 1 < lines.length) { + i += 1; + const next = lines[i]!.replace(/\s*#.*$/, ""); + buffer += " " + next.trim(); + } + valuePart = buffer; + } + + if (valuePart.startsWith("[")) { + const inner = valuePart.slice(1, valuePart.lastIndexOf("]")); + const items: string[] = []; + for (const part of inner.split(",")) { + const p = part.trim().replace(/,$/, ""); + if (!p) continue; + const sm = p.match(/^"([^"]*)"$/); + if (!sm) { + throw new Error(`repo-guard.toml line ${i + 1}: array item not a string: ${p}`); + } + items.push(sm[1]!); + } + currentSection[key] = items; + continue; + } + + if (/^\d+$/.test(valuePart)) { + currentSection[key] = Number.parseInt(valuePart, 10); + continue; + } + + const strMatch = valuePart.match(/^"([^"]*)"$/); + if (strMatch) { + currentSection[key] = strMatch[1]!; + continue; + } + + throw new Error(`repo-guard.toml line ${i + 1}: unsupported value: ${valuePart}`); + } + + return result; +} + +function loadConfig(): GuardConfig { + const text = readFileSync(CONFIG_PATH, "utf8"); + const toml = parseToml(text); + + const requireString = (section: string, key: string): string => { + const v = toml[section]?.[key]; + if (typeof v !== "string") { + throw new Error(`repo-guard.toml: missing string ${section}.${key}`); + } + return v; + }; + const requireNumber = (section: string, key: string): number => { + const v = toml[section]?.[key]; + if (typeof v !== "number") { + throw new Error(`repo-guard.toml: missing number ${section}.${key}`); + } + return v; + }; + + const allowlist = new Map>(); + for (const [k, v] of Object.entries(toml["actions.sha_allowlist"] ?? {})) { + if (!Array.isArray(v)) { + throw new Error(`repo-guard.toml: actions.sha_allowlist.${k} must be array of strings`); + } + allowlist.set(k, new Set(v)); + } + + const sensitiveFiles = new Set(); + const sd = toml["sensitive_diff"]?.["files"]; + if (Array.isArray(sd)) { + for (const f of sd) sensitiveFiles.add(f); + } + + const workflowSolanaCli = new Map(); + for (const [k, v] of Object.entries(toml["toolchain.workflow_solana_cli"] ?? {})) { + if (typeof v !== "string") { + throw new Error(`repo-guard.toml: toolchain.workflow_solana_cli.${k} must be a string`); + } + workflowSolanaCli.set(k, v); + } + + return { + anchorVersion: requireString("toolchain", "anchor_version"), + localDevSolanaVersion: requireString("toolchain", "local_dev_solana_version"), + workflowSolanaCli, + anchorLangVersion: requireString("cargo", "anchor_lang_version"), + anchorSplVersion: requireString("cargo", "anchor_spl_version"), + solanaProgramVersion: requireString("cargo", "solana_program_version"), + packageMinAgeDays: requireNumber("cargo", "package_min_age_days"), + actionShaAllowlist: allowlist, + sensitiveFiles, + }; +} + +// --- Shell helpers --- + +function run(command: string, args: string[]): string { + return execFileSync(command, args, { + cwd: ROOT, + encoding: "utf8", + }).trim(); +} + +function getDiffBase(): string | null { + if (!BASE_REF) return null; + try { + return run("git", ["merge-base", "HEAD", `origin/${BASE_REF}`]); + } catch { + return null; + } +} + +function readFileAtRef(ref: string, filePath: string): string | null { + try { + return execFileSync("git", ["show", `${ref}:${filePath}`], { + cwd: ROOT, + encoding: "utf8", + stdio: ["ignore", "pipe", "ignore"], + }); + } catch { + return null; + } +} + +// --- File walkers --- + +function walkCargoToml(dir: string, acc: string[]): string[] { + for (const entry of readdirSync(dir, { withFileTypes: true })) { + if (cargoIgnoredDirectories.has(entry.name)) continue; + const full = join(dir, entry.name); + if (entry.isDirectory()) { + walkCargoToml(full, acc); + continue; + } + if (entry.isFile() && entry.name === "Cargo.toml") { + acc.push(relative(ROOT, full)); + } + } + return acc; +} + +function walkPackageJson(dir: string, acc: string[]): string[] { + for (const entry of readdirSync(dir, { withFileTypes: true })) { + if (packageJsonIgnored.has(entry.name)) continue; + const full = join(dir, entry.name); + if (entry.isDirectory()) { + walkPackageJson(full, acc); + continue; + } + if (entry.isFile() && entry.name === "package.json") { + acc.push(relative(ROOT, full)); + } + } + return acc; +} + +// --- Cargo dep parser --- +// +// Hand-rolled because we need line numbers for annotations and the +// surface is small. Walks the `[dependencies]` table of each Cargo.toml +// and emits one entry per dep with the version spec and its location. + +type CargoDep = { + file: string; + line: number; + name: string; + spec: string | null; // null if path/git/workspace dep with no version + isPath: boolean; + isGit: boolean; + gitRev: string | null; +}; + +function parseCargoToml(file: string): CargoDep[] { + const text = readFileSync(join(ROOT, file), "utf8"); + const lines = text.split("\n"); + const deps: CargoDep[] = []; + let inDeps = false; + + for (let i = 0; i < lines.length; i += 1) { + const raw = lines[i]!; + const stripped = raw.replace(/\s*#.*$/, "").trimEnd(); + if (!stripped) continue; + + const section = stripped.match(/^\[([^\]]+)\]$/); + if (section) { + inDeps = /^(dependencies|dev-dependencies|build-dependencies)$/.test(section[1]!); + continue; + } + + if (!inDeps) continue; + + const m = stripped.match(/^([A-Za-z0-9_-]+)\s*=\s*(.+)$/); + if (!m) continue; + + const name = m[1]!; + const rhs = m[2]!.trim(); + + if (rhs.startsWith('"') && rhs.endsWith('"')) { + deps.push({ + file, + line: i + 1, + name, + spec: rhs.slice(1, -1), + isPath: false, + isGit: false, + gitRev: null, + }); + continue; + } + + if (rhs.startsWith("{") && rhs.endsWith("}")) { + const inner = rhs.slice(1, -1); + const pathField = inner.match(/path\s*=\s*"([^"]+)"/); + const gitField = inner.match(/git\s*=\s*"([^"]+)"/); + const verField = inner.match(/version\s*=\s*"([^"]+)"/); + const revField = inner.match(/rev\s*=\s*"([^"]+)"/); + deps.push({ + file, + line: i + 1, + name, + spec: verField?.[1] ?? null, + isPath: !!pathField, + isGit: !!gitField, + gitRev: revField?.[1] ?? null, + }); + continue; + } + } + + return deps; +} + +// --- Cargo checks --- + +function checkCargoExactPinning(config: GuardConfig): { + status: CheckStatus; + violations: CargoViolation[]; + exactDependencies: Map>; // "name@version" -> set of "file:line" +} { + const files = walkCargoToml(join(ROOT, "programs"), []); + const violations: CargoViolation[] = []; + const exact = new Map>(); + + for (const file of files) { + const deps = parseCargoToml(file); + for (const dep of deps) { + if (dep.isPath) continue; + if (dep.isGit) { + if (!dep.gitRev || !sha40Pattern.test(dep.gitRev)) { + violations.push({ + file, + dependency: dep.name, + reason: "git dep without 40-char rev SHA", + spec: dep.gitRev ?? "(no rev)", + }); + } + continue; + } + if (!dep.spec) { + violations.push({ + file, + dependency: dep.name, + reason: "no version, path, or git", + spec: "(none)", + }); + continue; + } + if (!cargoExactPattern.test(dep.spec)) { + violations.push({ + file, + dependency: dep.name, + reason: "non-exact version spec (must be =x.y.z)", + spec: dep.spec, + }); + continue; + } + const version = dep.spec.slice(1); + const key = `${dep.name}@${version}`; + const set = exact.get(key) ?? new Set(); + set.add(`${file}:${dep.line}`); + exact.set(key, set); + } + } + + return { + status: violations.length === 0 ? "pass" : "fail", + violations, + exactDependencies: exact, + }; +} + +function checkCrossProgramConsistency(config: GuardConfig): { + status: CheckStatus; + violations: CrossProgramViolation[]; +} { + const files = walkCargoToml(join(ROOT, "programs"), []); + const seen = new Map>>(); + + const watched = new Map([ + ["anchor-lang", config.anchorLangVersion], + ["anchor-spl", config.anchorSplVersion], + ]); + + for (const file of files) { + const deps = parseCargoToml(file); + for (const dep of deps) { + if (!watched.has(dep.name)) continue; + if (!dep.spec) continue; + const versionOnly = dep.spec.replace(/^=/, ""); + const perDep = seen.get(dep.name) ?? new Map(); + const arr = perDep.get(versionOnly) ?? []; + arr.push({ file, spec: dep.spec }); + perDep.set(versionOnly, arr); + seen.set(dep.name, perDep); + } + } + + const violations: CrossProgramViolation[] = []; + for (const [name, expected] of watched) { + const perDep = seen.get(name); + if (!perDep) continue; + for (const [version, instances] of perDep.entries()) { + if (version !== expected) { + violations.push({ + dependency: name, + expected, + variants: instances, + }); + } + } + } + + return { + status: violations.length === 0 ? "pass" : "fail", + violations, + }; +} + +// --- Crates.io age check --- + +async function fetchCratePublishTime(crate: string, version: string): Promise { + const url = `https://crates.io/api/v1/crates/${encodeURIComponent(crate)}/${encodeURIComponent(version)}`; + // crates.io requires a descriptive User-Agent. Without it the API returns + // 403. See https://crates.io/policies#crawlers + const response = await fetch(url, { + headers: { + Accept: "application/json", + "User-Agent": "metadao-repo-guard (https://github.com/metaDAOproject/programs)", + }, + }); + if (!response.ok) { + throw new Error(`crates.io returned ${response.status} for ${crate}@${version}`); + } + const meta = (await response.json()) as { version?: { created_at?: string } }; + const at = meta.version?.created_at; + if (!at) { + throw new Error(`crates.io: no created_at for ${crate}@${version}`); + } + return at; +} + +function filterCratesToPRChanges( + all: Map>, + diffBase: string +): Map> { + const changed = new Map>(); + for (const [key, locations] of all.entries()) { + const atIdx = key.lastIndexOf("@"); + const name = key.slice(0, atIdx); + const headVersion = key.slice(atIdx + 1); + + for (const loc of locations) { + const file = loc.split(":")[0]!; + const baseText = readFileAtRef(diffBase, file); + if (baseText === null) { + const s = changed.get(key) ?? new Set(); + s.add(loc); + changed.set(key, s); + continue; + } + let baseVersion: string | null = null; + try { + const tmpFile = file; + // parse base copy: write to memory and reuse parseCargoToml? easier: + // do an inline parse here. + const lines = baseText.split("\n"); + let inDeps = false; + for (const raw of lines) { + const stripped = raw.replace(/\s*#.*$/, "").trimEnd(); + const section = stripped.match(/^\[([^\]]+)\]$/); + if (section) { + inDeps = /^(dependencies|dev-dependencies|build-dependencies)$/.test(section[1]!); + continue; + } + if (!inDeps) continue; + const m = stripped.match(/^([A-Za-z0-9_-]+)\s*=\s*(.+)$/); + if (!m || m[1] !== name) continue; + const rhs = m[2]!.trim(); + if (rhs.startsWith('"') && rhs.endsWith('"')) { + baseVersion = rhs.slice(1, -1).replace(/^=/, ""); + } else if (rhs.startsWith("{")) { + const v = rhs.match(/version\s*=\s*"([^"]+)"/); + if (v) baseVersion = v[1]!.replace(/^=/, ""); + } + break; + } + } catch { + // fall through; treat as changed + } + if (baseVersion === headVersion) continue; + const s = changed.get(key) ?? new Set(); + s.add(loc); + changed.set(key, s); + } + } + return changed; +} + +async function checkCrateAge( + config: GuardConfig, + exactDeps: Map> +): Promise<{ status: CheckStatus; violations: CrateAgeViolation[]; reason?: string }> { + const diffBase = getDiffBase(); + if (!diffBase) { + return { + status: "skip", + violations: [], + reason: "no PR base ref (GITHUB_BASE_REF) available", + }; + } + + const scoped = filterCratesToPRChanges(exactDeps, diffBase); + const now = Date.now(); + const violations: CrateAgeViolation[] = []; + + try { + for (const [key, locations] of [...scoped.entries()].sort()) { + const atIdx = key.lastIndexOf("@"); + const name = key.slice(0, atIdx); + const version = key.slice(atIdx + 1); + const publishedAt = await fetchCratePublishTime(name, version); + const ageDays = Math.floor( + (now - new Date(publishedAt).getTime()) / (1000 * 60 * 60 * 24) + ); + if (ageDays >= config.packageMinAgeDays) continue; + violations.push({ + crate: name, + version, + publishedAt, + ageDays, + usedIn: [...locations].sort(), + }); + } + } catch (error) { + if (IS_CI) throw error; + return { + status: "skip", + violations: [], + reason: error instanceof Error ? error.message : String(error), + }; + } + + return { + status: violations.length === 0 ? "pass" : "fail", + violations, + }; +} + +// --- Yarn package.json checks --- + +const npmDepSections = [ + "dependencies", + "devDependencies", + "optionalDependencies", + "peerDependencies", + "resolutions", +]; + +function shouldPinNpmSpec(spec: string): boolean { + // skip non-registry refs - they're pinned by other means + return !( + spec.startsWith("file:") || + spec.startsWith("link:") || + spec.startsWith("workspace:") || + spec.startsWith("./") || + spec.startsWith("../") || + spec.startsWith("git+") || + spec.startsWith("git:") || + spec.startsWith("http://") || + spec.startsWith("https://") + ); +} + +function checkPackageJsonPinning(): { + status: CheckStatus; + violations: PackageJsonViolation[]; + exactDependencies: Map>; +} { + const files = walkPackageJson(ROOT, []); + const violations: PackageJsonViolation[] = []; + const exact = new Map>(); + + for (const file of files) { + let pkg: Record; + try { + pkg = JSON.parse(readFileSync(join(ROOT, file), "utf8")); + } catch { + continue; + } + + for (const section of npmDepSections) { + const deps = pkg[section]; + if (!deps || typeof deps !== "object") continue; + for (const [name, spec] of Object.entries(deps as Record)) { + if (typeof spec !== "string") continue; + if (!shouldPinNpmSpec(spec)) continue; + if (!npmExactPattern.test(spec)) { + violations.push({ file, section, dependency: name, spec }); + continue; + } + const key = `${name}@${spec}`; + const set = exact.get(key) ?? new Set(); + set.add(`${file} (${section})`); + exact.set(key, set); + } + } + } + + return { + status: violations.length === 0 ? "pass" : "fail", + violations, + exactDependencies: exact, + }; +} + +async function fetchNpmPublishTime(name: string, version: string): Promise { + const response = await fetch( + `https://registry.npmjs.org/${encodeURIComponent(name)}`, + { headers: { Accept: "application/json" } } + ); + if (!response.ok) { + throw new Error(`npm registry returned ${response.status} for ${name}`); + } + const meta = (await response.json()) as { time?: Record }; + const at = meta.time?.[version]; + if (!at) { + throw new Error(`npm: no publish time for ${name}@${version}`); + } + return at; +} + +function filterNpmDepsToChanges( + all: Map>, + diffBase: string +): Map> { + const locationPattern = /^(.+) \((\w+)\)$/; + const changed = new Map>(); + + for (const [key, locations] of all.entries()) { + const atIdx = key.lastIndexOf("@"); + const name = key.slice(0, atIdx); + const headVersion = key.slice(atIdx + 1); + + for (const loc of locations) { + const m = loc.match(locationPattern); + if (!m) continue; + const file = m[1]!; + const section = m[2]!; + + const baseText = readFileAtRef(diffBase, file); + if (baseText === null) { + const s = changed.get(key) ?? new Set(); + s.add(loc); + changed.set(key, s); + continue; + } + let baseVersion: unknown = null; + try { + const basePkg = JSON.parse(baseText) as Record; + const baseSection = basePkg[section]; + if (baseSection && typeof baseSection === "object") { + baseVersion = (baseSection as Record)[name]; + } + } catch { + // fall through + } + if (baseVersion === headVersion) continue; + const s = changed.get(key) ?? new Set(); + s.add(loc); + changed.set(key, s); + } + } + return changed; +} + +async function checkNpmAge( + config: GuardConfig, + exactDeps: Map> +): Promise<{ status: CheckStatus; violations: NpmAgeViolation[]; reason?: string }> { + const diffBase = getDiffBase(); + if (!diffBase) { + return { status: "skip", violations: [], reason: "no PR base ref available" }; + } + + const scoped = filterNpmDepsToChanges(exactDeps, diffBase); + const now = Date.now(); + const violations: NpmAgeViolation[] = []; + + try { + for (const [key, locations] of [...scoped.entries()].sort()) { + const atIdx = key.lastIndexOf("@"); + const name = key.slice(0, atIdx); + const version = key.slice(atIdx + 1); + const publishedAt = await fetchNpmPublishTime(name, version); + const ageDays = Math.floor( + (now - new Date(publishedAt).getTime()) / (1000 * 60 * 60 * 24) + ); + if (ageDays >= config.packageMinAgeDays) continue; + violations.push({ + dependency: name, + version, + publishedAt, + ageDays, + usedIn: [...locations].sort(), + }); + } + } catch (error) { + if (IS_CI) throw error; + return { + status: "skip", + violations: [], + reason: error instanceof Error ? error.message : String(error), + }; + } + + return { + status: violations.length === 0 ? "pass" : "fail", + violations, + }; +} + +// --- Workflow checks --- + +function listWorkflowFiles(): string[] { + const acc: string[] = []; + for (const dir of [join(ROOT, ".github", "workflows"), join(ROOT, ".github", "actions")]) { + if (!existsSync(dir)) continue; + walkYaml(dir, acc); + } + return acc; +} + +function walkYaml(dir: string, acc: string[]): void { + for (const entry of readdirSync(dir, { withFileTypes: true })) { + const full = join(dir, entry.name); + if (entry.isDirectory()) { + walkYaml(full, acc); + continue; + } + if (entry.isFile() && /\.ya?ml$/i.test(entry.name)) { + acc.push(relative(ROOT, full)); + } + } +} + +function checkWorkflowToolchain(config: GuardConfig): { + status: CheckStatus; + violations: WorkflowVersionViolation[]; +} { + const files = listWorkflowFiles(); + const violations: WorkflowVersionViolation[] = []; + + for (const file of files) { + const lines = readFileSync(join(ROOT, file), "utf8").split("\n"); + // Per-file expected Solana CLI version. Workflows not in the map are + // dynamic (e.g. reusable-build.yaml reads from Cargo.lock) - we don't + // enforce a value for those. + const expectedSolana = config.workflowSolanaCli.get(file); + + for (let i = 0; i < lines.length; i += 1) { + const raw = lines[i]!; + const stripped = raw.split("#")[0]!; + // Quoted literal value: anchor-version: '0.29.0' or "0.29.0". + // `${{ inputs.* }}` template references don't have quotes, so they + // are skipped by this regex. + const a = stripped.match(/\banchor-version\s*:\s*['"]([^'"]+)['"]/); + const s = stripped.match(/\bsolana-cli-version\s*:\s*['"]([^'"]+)['"]/); + if (a) { + const actual = a[1]!; + if (actual !== config.anchorVersion) { + violations.push({ + file, + line: i + 1, + key: "anchor-version", + actual, + expected: config.anchorVersion, + }); + } + } + if (s && expectedSolana !== undefined) { + const actual = s[1]!; + if (actual !== expectedSolana) { + violations.push({ + file, + line: i + 1, + key: "solana-cli-version", + actual, + expected: expectedSolana, + }); + } + } + } + } + + return { + status: violations.length === 0 ? "pass" : "fail", + violations, + }; +} + +// `solana-program` crate pin in launchpads. Must match +// [cargo].solana_program_version exactly across every program that +// declares it. Programs that don't declare `solana-program` rely on +// anchor-lang's transitive dep - not our concern here. +function checkSolanaProgramCrate(config: GuardConfig): { + status: CheckStatus; + violations: Array<{ file: string; line: number; spec: string; expected: string }>; +} { + const files = walkCargoToml(join(ROOT, "programs"), []); + const violations: Array<{ file: string; line: number; spec: string; expected: string }> = []; + + for (const file of files) { + const deps = parseCargoToml(file); + for (const dep of deps) { + if (dep.name !== "solana-program") continue; + if (!dep.spec) continue; + const version = dep.spec.replace(/^=/, ""); + if (version !== config.solanaProgramVersion) { + violations.push({ + file, + line: dep.line, + spec: dep.spec, + expected: `=${config.solanaProgramVersion}`, + }); + } + } + } + + return { + status: violations.length === 0 ? "pass" : "fail", + violations, + }; +} + +// Anchor.toml [toolchain].solana_version is what `anchor test` auto-installs +// on a local-dev machine. CI workflows don't read it (they pass +// solana-cli-version explicitly), but we still lock it down so the value +// stays predictable. +function checkAnchorTomlSolanaVersion(config: GuardConfig): { + status: CheckStatus; + actual: string | null; + expected: string; +} { + const anchorTomlPath = join(ROOT, "Anchor.toml"); + if (!existsSync(anchorTomlPath)) { + return { status: "skip", actual: null, expected: config.localDevSolanaVersion }; + } + const text = readFileSync(anchorTomlPath, "utf8"); + const match = text.match(/^\s*solana_version\s*=\s*"([^"]+)"/m); + if (!match) { + return { status: "skip", actual: null, expected: config.localDevSolanaVersion }; + } + const actual = match[1]!; + return { + status: actual === config.localDevSolanaVersion ? "pass" : "fail", + actual, + expected: config.localDevSolanaVersion, + }; +} + +function checkWorkflowActionPinning(config: GuardConfig): { + status: CheckStatus; + violations: WorkflowActionViolation[]; +} { + const files = listWorkflowFiles(); + const violations: WorkflowActionViolation[] = []; + + for (const file of files) { + const lines = readFileSync(join(ROOT, file), "utf8").split("\n"); + for (let i = 0; i < lines.length; i += 1) { + const raw = lines[i]!; + // strip trailing comment (the SHA-pin format keeps the tag in a #-comment) + const usesMatch = raw.match(/\buses:\s*([^\s#]+)/); + if (!usesMatch) continue; + const ref = usesMatch[1]!; + if (ref.startsWith("./")) continue; // local composite action + const atIdx = ref.lastIndexOf("@"); + if (atIdx < 0) continue; + const repoPath = ref.slice(0, atIdx); + const rev = ref.slice(atIdx + 1); + // owner from "owner/repo" or "owner/repo/sub" + const slash = repoPath.indexOf("/"); + const owner = slash > 0 ? repoPath.slice(0, slash) : repoPath; + + // GitHub-owned actions are allowed to stay tag-pinned. + if (owner === "actions") continue; + + // For nested paths (e.g. solana-developers/github-actions/extract-versions), + // the allowlist is keyed by "owner/repo" - the top-level repo. + const repoEnd = repoPath.indexOf("/", slash + 1); + const repoKey = repoEnd > 0 ? repoPath.slice(0, repoEnd) : repoPath; + + if (!sha40Pattern.test(rev)) { + violations.push({ + file, + line: i + 1, + action: ref, + reason: "third-party action must be SHA-pinned (40 hex chars)", + }); + continue; + } + + const allowed = config.actionShaAllowlist.get(repoKey); + if (!allowed || !allowed.has(rev)) { + violations.push({ + file, + line: i + 1, + action: ref, + reason: `SHA not in [actions.sha_allowlist] for ${repoKey}`, + }); + } + } + } + + return { + status: violations.length === 0 ? "pass" : "fail", + violations, + }; +} + +// --- Sensitive-diff (review-assist) --- + +const sensitiveRules: Array<{ kind: string; pattern: RegExp }> = [ + { + kind: "declare_id! literal change", + pattern: /\bdeclare_id!\s*\(\s*["'][^"']+["']\s*\)/, + }, + { + kind: "#[error_code] enum modification", + pattern: /^\s*#\[(?:error_code|error)\]/, + }, + { + kind: "Hardcoded Solana address literal", + pattern: /["'`](?:[1-9A-HJ-NP-Za-km-z]{32,44})["'`]/, + }, + { + kind: "Program ID constant or variable change", + pattern: /\b(?:PROGRAM_ID|program_id)\b/, + }, + { + kind: "Anchor [programs.*] entry change", + pattern: /^\s*[a-z_][a-z0-9_]*\s*=\s*"[1-9A-HJ-NP-Za-km-z]{32,44}"/, + }, + { + kind: "Unsafe block introduced or modified", + pattern: /\bunsafe\s*\{/, + }, +]; + +function checkSensitiveDiff(config: GuardConfig): { + status: CheckStatus; + findings: SensitiveFinding[]; + touchedSensitiveFiles: string[]; +} { + const diffBase = getDiffBase(); + if (!diffBase) { + return { status: "skip", findings: [], touchedSensitiveFiles: [] }; + } + + const changedFiles = new Set( + run("git", ["diff", "--name-only", `${diffBase}...HEAD`]).split("\n").filter(Boolean) + ); + const touchedSensitiveFiles = [...config.sensitiveFiles].filter((f) => changedFiles.has(f)); + + const diff = run("git", ["diff", "--unified=0", "--no-color", `${diffBase}...HEAD`]); + + const findings: SensitiveFinding[] = []; + let currentFile = ""; + let nextLine = 0; + + for (const rawLine of diff.split("\n")) { + if (rawLine.startsWith("+++ b/")) { + currentFile = rawLine.slice(6); + continue; + } + if (rawLine.startsWith("@@")) { + const m = rawLine.match(/\+(\d+)(?:,(\d+))?/); + nextLine = m ? Number.parseInt(m[1]!, 10) : 0; + continue; + } + if (sensitiveExcludedFiles.has(currentFile)) continue; + if (/\.(md|mdx|txt|rst)$/i.test(currentFile)) continue; + + if (!rawLine.startsWith("+") || rawLine.startsWith("+++")) { + if (rawLine.startsWith("-") && !rawLine.startsWith("---")) continue; + if (!rawLine.startsWith("-")) continue; + } + + const sign = rawLine[0]!; + const text = rawLine.slice(1); + if (!currentFile || !text.trim()) { + if (sign === "+") nextLine += 1; + continue; + } + + const kinds = sensitiveRules.filter((r) => r.pattern.test(text)).map((r) => r.kind); + if (kinds.length > 0) { + findings.push({ + file: currentFile, + line: nextLine, + kind: kinds.join("; "), + text: `${sign}${text}`.trim(), + }); + } + if (sign === "+") nextLine += 1; + } + + if (findings.length === 0 && touchedSensitiveFiles.length === 0) { + return { status: "pass", findings, touchedSensitiveFiles }; + } + return { status: "warn", findings, touchedSensitiveFiles }; +} + +// --- Render --- + +function fmtPath(p: string): string { + return `\`${p}\``; +} + +function renderHeader(title: string, status: CheckStatus): string[] { + return [`### ${title}`, "", `- Status: ${status}`]; +} + +function renderCargoPinning(r: ReturnType): string[] { + const lines = renderHeader("Cargo dependency pinning", r.status); + if (r.status === "pass") { + lines.push("- Every `programs/*/Cargo.toml` dep uses `=x.y.z`, a `path = ..` workspace ref, or a git dep with a 40-char `rev`."); + return lines; + } + lines.push("- The following Cargo entries are not exact:"); + for (const v of r.violations) { + lines.push(`- ${fmtPath(v.file)} -> \`${v.dependency}\`: ${v.reason}; spec: \`${v.spec}\``); + } + return lines; +} + +function renderCrossProgram(r: ReturnType): string[] { + const lines = renderHeader("Cross-program Anchor/Solana version consistency", r.status); + if (r.status === "pass") { + lines.push("- `anchor-lang` and `anchor-spl` are pinned to the version declared in `repo-guard.toml` across every program."); + return lines; + } + for (const v of r.violations) { + lines.push(`- \`${v.dependency}\` expected \`=${v.expected}\` but found:`); + for (const inst of v.variants) { + lines.push(` - ${fmtPath(inst.file)} uses \`${inst.spec}\``); + } + } + return lines; +} + +function renderCrateAge(r: Awaited>, config: GuardConfig): string[] { + const lines = renderHeader("Crate minimum age", r.status); + if (r.status === "pass") { + lines.push(`- All Cargo deps changed by this PR are at least ${config.packageMinAgeDays} days old on crates.io.`); + return lines; + } + if (r.status === "skip") { + lines.push(`- Skipped: ${r.reason}`); + return lines; + } + lines.push(`- The following crates are newer than ${config.packageMinAgeDays} days:`); + for (const v of r.violations) { + lines.push( + `- \`${v.crate}@${v.version}\` is ${v.ageDays} days old (published ${v.publishedAt}); used in ${v.usedIn.map(fmtPath).join(", ")}` + ); + } + return lines; +} + +function renderPackageJson(r: ReturnType): string[] { + const lines = renderHeader("Yarn package.json pinning", r.status); + if (r.status === "pass") { + lines.push("- All `package.json` deps use exact versions (no `^`, `~`, ranges)."); + return lines; + } + for (const v of r.violations) { + lines.push(`- ${fmtPath(v.file)} -> \`${v.section}.${v.dependency}\` uses \`${v.spec}\``); + } + return lines; +} + +function renderNpmAge(r: Awaited>, config: GuardConfig): string[] { + const lines = renderHeader("npm minimum age", r.status); + if (r.status === "pass") { + lines.push(`- All npm deps changed by this PR are at least ${config.packageMinAgeDays} days old.`); + return lines; + } + if (r.status === "skip") { + lines.push(`- Skipped: ${r.reason}`); + return lines; + } + for (const v of r.violations) { + lines.push( + `- \`${v.dependency}@${v.version}\` is ${v.ageDays} days old (published ${v.publishedAt}); used in ${v.usedIn.map(fmtPath).join(", ")}` + ); + } + return lines; +} + +function renderWorkflowToolchain(r: ReturnType, config: GuardConfig): string[] { + const lines = renderHeader("Workflow toolchain consistency", r.status); + if (r.status === "pass") { + lines.push(`- Every workflow declares \`anchor-version: ${config.anchorVersion}\`.`); + lines.push("- Per-file \`solana-cli-version\` values match \`[toolchain.workflow_solana_cli]\` in \`repo-guard.toml\`."); + return lines; + } + for (const v of r.violations) { + lines.push(`- ${fmtPath(v.file)}:${v.line} has \`${v.key}: ${v.actual}\`, expected \`${v.expected}\``); + } + return lines; +} + +function renderSolanaProgramCrate(r: ReturnType, config: GuardConfig): string[] { + const lines = renderHeader("solana-program crate pin", r.status); + if (r.status === "pass") { + lines.push(`- Every \`solana-program = "=X"\` declaration is \`=${config.solanaProgramVersion}\` (locked to match \`Cargo.lock\`).`); + return lines; + } + for (const v of r.violations) { + lines.push(`- ${fmtPath(v.file)}:${v.line} has \`solana-program = "${v.spec}"\`, expected \`${v.expected}\``); + } + return lines; +} + +function renderAnchorTomlSolanaVersion(r: ReturnType): string[] { + const lines = renderHeader("Anchor.toml solana_version", r.status); + if (r.status === "pass") { + lines.push(`- \`Anchor.toml\` declares \`solana_version = "${r.expected}"\` (local-dev install for \`anchor test\`).`); + return lines; + } + if (r.status === "skip") { + lines.push("- Skipped: `Anchor.toml` has no `solana_version` field."); + return lines; + } + lines.push(`- \`Anchor.toml\` declares \`solana_version = "${r.actual ?? "(missing)"}"\`, expected \`"${r.expected}"\``); + return lines; +} + +function renderActionPinning(r: ReturnType): string[] { + const lines = renderHeader("GitHub Action SHA pinning", r.status); + if (r.status === "pass") { + lines.push("- Every third-party action is pinned to a SHA in `[actions.sha_allowlist]`."); + return lines; + } + for (const v of r.violations) { + lines.push(`- ${fmtPath(v.file)}:${v.line} \`${v.action}\`: ${v.reason}`); + } + return lines; +} + +function renderSensitive(r: ReturnType): string[] { + const lines = renderHeader("Sensitive program / config changes", r.status); + if (r.status === "skip") { + lines.push("- Skipped: no PR base ref available."); + return lines; + } + if (r.status === "pass") { + lines.push("- No suspicious changes to program IDs, error enums, or sensitive files detected."); + return lines; + } + lines.push("- Review hint only (CODEOWNERS is the merge gate). Lines below match heuristics for security-sensitive changes:"); + if (r.touchedSensitiveFiles.length > 0) { + lines.push(`- High-sensitivity files touched: ${r.touchedSensitiveFiles.map(fmtPath).join(", ")}`); + } + for (const f of r.findings.slice(0, 30)) { + lines.push(`- ${fmtPath(`${f.file}:${f.line}`)} ${f.kind} -> \`${f.text}\``); + } + return lines; +} + +// --- Main --- + +async function main() { + const config = loadConfig(); + + const cargoPinning = checkCargoExactPinning(config); + const crossProgram = checkCrossProgramConsistency(config); + const solanaProgramCrate = checkSolanaProgramCrate(config); + const anchorTomlSolana = checkAnchorTomlSolanaVersion(config); + const crateAge = await checkCrateAge(config, cargoPinning.exactDependencies); + const npmPinning = checkPackageJsonPinning(); + const npmAge = await checkNpmAge(config, npmPinning.exactDependencies); + const workflowToolchain = checkWorkflowToolchain(config); + const actionPinning = checkWorkflowActionPinning(config); + const sensitive = checkSensitiveDiff(config); + + const overallFailed = + cargoPinning.status === "fail" || + crossProgram.status === "fail" || + solanaProgramCrate.status === "fail" || + anchorTomlSolana.status === "fail" || + crateAge.status === "fail" || + npmPinning.status === "fail" || + npmAge.status === "fail" || + workflowToolchain.status === "fail" || + actionPinning.status === "fail"; + + const summary = [ + "## Repository Guard", + "", + ...renderCargoPinning(cargoPinning), + "", + ...renderCrossProgram(crossProgram), + "", + ...renderSolanaProgramCrate(solanaProgramCrate, config), + "", + ...renderAnchorTomlSolanaVersion(anchorTomlSolana), + "", + ...renderCrateAge(crateAge, config), + "", + ...renderPackageJson(npmPinning), + "", + ...renderNpmAge(npmAge, config), + "", + ...renderWorkflowToolchain(workflowToolchain, config), + "", + ...renderActionPinning(actionPinning), + "", + ...renderSensitive(sensitive), + "", + `Overall status: ${overallFailed ? "fail" : "pass"}`, + "", + "_Lockfile freshness (Cargo.lock + yarn.lock) is checked by the workflow directly and cannot be bypassed. The sensitive-diff section is a review hint - CODEOWNERS handles the actual merge gate._", + ].join("\n"); + + writeFileSync(SUMMARY_PATH, summary + "\n"); + + // Sensitive findings as ::warning:: annotations + if (sensitive.status === "warn") { + for (const f of sensitive.findings.slice(0, 30)) { + console.log(`::warning file=${f.file},line=${f.line}::${f.kind}: ${f.text}`); + } + for (const f of sensitive.touchedSensitiveFiles) { + console.log(`::warning file=${f}::High-sensitivity file modified - please review carefully.`); + } + } + + if (!overallFailed) { + console.log(summary); + return; + } + + console.error("\nRepository Guard failed.\n"); + console.error(summary); + + for (const v of cargoPinning.violations) { + console.error(`::error file=${v.file}::${v.dependency} ${v.reason} (\`${v.spec}\`)`); + } + for (const v of crossProgram.violations) { + for (const inst of v.variants) { + console.error( + `::error file=${inst.file}::${v.dependency} = ${inst.spec}, expected =${v.expected}` + ); + } + } + for (const v of solanaProgramCrate.violations) { + console.error( + `::error file=${v.file},line=${v.line}::solana-program = "${v.spec}", expected "${v.expected}"` + ); + } + if (anchorTomlSolana.status === "fail") { + console.error( + `::error file=Anchor.toml::solana_version = "${anchorTomlSolana.actual ?? "(missing)"}", expected "${anchorTomlSolana.expected}"` + ); + } + if (crateAge.status === "fail") { + for (const v of crateAge.violations) { + const where = v.usedIn[0]?.split(":")[0] ?? "Cargo.toml"; + console.error( + `::error file=${where}::${v.crate}@${v.version} is ${v.ageDays} days old (min ${config.packageMinAgeDays}d)` + ); + } + } + for (const v of npmPinning.violations) { + console.error(`::error file=${v.file}::${v.section}.${v.dependency} uses \`${v.spec}\` - pin to exact`); + } + if (npmAge.status === "fail") { + for (const v of npmAge.violations) { + const where = v.usedIn[0]?.split(" ")[0] ?? "package.json"; + console.error( + `::error file=${where}::${v.dependency}@${v.version} is ${v.ageDays} days old (min ${config.packageMinAgeDays}d)` + ); + } + } + for (const v of workflowToolchain.violations) { + console.error(`::error file=${v.file},line=${v.line}::${v.key}: ${v.actual} (expected ${v.expected})`); + } + for (const v of actionPinning.violations) { + console.error(`::error file=${v.file},line=${v.line}::${v.action}: ${v.reason}`); + } + + process.exit(1); +} + +await main(); diff --git a/sdk/package.json b/sdk/package.json index 775a0ed1e..e8e0638f3 100644 --- a/sdk/package.json +++ b/sdk/package.json @@ -42,44 +42,44 @@ "prepublishOnly": "yarn lint:fix && yarn build" }, "dependencies": { - "@coral-xyz/anchor": "^0.29.0", - "@noble/hashes": "^1.4.0", - "@solana/spl-token": "^0.3.7", - "@solana/web3.js": "^1.76.0", - "@sqds/multisig": "^2.1.4", - "bn.js": "^5.2.1" + "@coral-xyz/anchor": "0.29.0", + "@noble/hashes": "1.8.0", + "@solana/spl-token": "0.3.11", + "@solana/web3.js": "1.98.4", + "@sqds/multisig": "2.1.4", + "bn.js": "5.2.2" }, "devDependencies": { - "@types/bn.js": "^5.1.0", - "@types/chai": "^4.3.0", - "@types/mocha": "^9.0.0", - "chai": "^4.3.4", - "mocha": "^9.0.3", + "@types/bn.js": "5.2.0", + "@types/chai": "4.3.20", + "@types/mocha": "9.1.1", + "chai": "4.5.0", + "mocha": "9.2.2", "prettier": "3.6.2", - "solana-bankrun": "^0.2.0", + "solana-bankrun": "0.2.0", "spl-token-bankrun": "0.2.3", - "ts-mocha": "^10.0.0", + "ts-mocha": "10.1.0", "typescript": "5.9.3" }, "resolutions": { - "error-ex": "=1.3.2", - "strip-ansi": "=6.0.1", - "wrap-ansi": "=7.0.0", - "ansi-styles": "=4.3.0", - "color-string": "=2.1.0", - "is-arrayish": "=0.3.2", - "chalk": "=4.1.2", - "supports-color": "=7.2.0", - "slice-ansi": "=5.0.0", - "ansi-regex": "=5.0.1", - "color-name": "=2.0.0", - "chalk-template": "=0.4.0", - "supports-hyperlinks": "=2.3.0", - "has-ansi": "=4.0.1", - "color-convert": "=2.0.1", - "backslash": "=0.2.0", - "simple-swizzle": "=0.2.2", - "debug": "=4.4.1", - "color": "=4.2.3" + "error-ex": "1.3.2", + "strip-ansi": "6.0.1", + "wrap-ansi": "7.0.0", + "ansi-styles": "4.3.0", + "color-string": "2.1.0", + "is-arrayish": "0.3.2", + "chalk": "4.1.2", + "supports-color": "7.2.0", + "slice-ansi": "5.0.0", + "ansi-regex": "5.0.1", + "color-name": "2.0.0", + "chalk-template": "0.4.0", + "supports-hyperlinks": "2.3.0", + "has-ansi": "4.0.1", + "color-convert": "2.0.1", + "backslash": "0.2.0", + "simple-swizzle": "0.2.2", + "debug": "4.4.1", + "color": "4.2.3" } } diff --git a/sdk/yarn.lock b/sdk/yarn.lock index 2dde4ad19..e9047bfe2 100644 --- a/sdk/yarn.lock +++ b/sdk/yarn.lock @@ -7,7 +7,7 @@ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.28.4.tgz#a70226016fabe25c5783b2f22d3e1c9bc5ca3326" integrity sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ== -"@coral-xyz/anchor@^0.29.0": +"@coral-xyz/anchor@0.29.0": version "0.29.0" resolved "https://registry.yarnpkg.com/@coral-xyz/anchor/-/anchor-0.29.0.tgz#bd0be95bedfb30a381c3e676e5926124c310ff12" integrity sha512-eny6QNG0WOwqV0zQ7cs/b1tIuzZGmP7U7EcH+ogt4Gdbl8HDmIYVMh/9aTmYZPaFWjtUaI8qSn73uYEXWfATdA== @@ -191,7 +191,7 @@ dependencies: "@solana/codecs" "2.0.0-rc.1" -"@solana/spl-token@^0.3.6", "@solana/spl-token@^0.3.7", "@solana/spl-token@^0.3.8": +"@solana/spl-token@0.3.11", "@solana/spl-token@^0.3.6", "@solana/spl-token@^0.3.8": version "0.3.11" resolved "https://registry.yarnpkg.com/@solana/spl-token/-/spl-token-0.3.11.tgz#cdc10f9472b29b39c8983c92592cadd06627fb9a" integrity sha512-bvohO3rIMSVL24Pb+I4EYTJ6cL82eFpInEXD/I8K8upOGjpqHsKUoAempR/RnUlI1qSFNyFlWJfu6MNUgfbCQQ== @@ -201,7 +201,7 @@ "@solana/spl-token-metadata" "^0.1.2" buffer "^6.0.3" -"@solana/web3.js@^1.32.0", "@solana/web3.js@^1.56.2", "@solana/web3.js@^1.68.0", "@solana/web3.js@^1.70.3", "@solana/web3.js@^1.76.0": +"@solana/web3.js@1.98.4", "@solana/web3.js@^1.32.0", "@solana/web3.js@^1.56.2", "@solana/web3.js@^1.68.0", "@solana/web3.js@^1.70.3": version "1.98.4" resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.98.4.tgz#df51d78be9d865181ec5138b4e699d48e6895bbe" integrity sha512-vv9lfnvjUsRiq//+j5pBdXig0IQdtzA0BRZ3bXEP4KaIyF1CcaydWqgyzQgfZMNIsWNWmG+AUHwPy4AHOD6gpw== @@ -222,7 +222,7 @@ rpc-websockets "^9.0.2" superstruct "^2.0.2" -"@sqds/multisig@^2.1.4": +"@sqds/multisig@2.1.4": version "2.1.4" resolved "https://registry.yarnpkg.com/@sqds/multisig/-/multisig-2.1.4.tgz#f69067ee8e23e86b1170ae7509cdfbc460ac9d0d" integrity sha512-5w+NmwHOzl96nI50R/fjSD6uFydRLNUquhoEmmWbGepS4D9DnQyF2TKcUBfTyxV3sgJt00ypBt7SXB3y8WOzUQ== @@ -245,14 +245,14 @@ dependencies: tslib "^2.8.0" -"@types/bn.js@^5.1.0", "@types/bn.js@^5.1.1": +"@types/bn.js@5.2.0", "@types/bn.js@^5.1.1": version "5.2.0" resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.2.0.tgz#4349b9710e98f9ab3cdc50f1c5e4dcbd8ef29c80" integrity sha512-DLbJ1BPqxvQhIGbeu8VbUC1DiAiahHtAYvA0ZEAa4P31F7IaArc8z3C3BRQdWX4mtLQuABG4yzp76ZrS02Ui1Q== dependencies: "@types/node" "*" -"@types/chai@^4.3.0": +"@types/chai@4.3.20": version "4.3.20" resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.20.tgz#cb291577ed342ca92600430841a00329ba05cecc" integrity sha512-/pC9HAB5I/xMlc5FP77qjCnI16ChlJfW0tGa0IUcFn38VJrTV6DeZ60NU5KZBtaOZqjdpwTWohz5HU1RrhiYxQ== @@ -269,7 +269,7 @@ resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== -"@types/mocha@^9.0.0": +"@types/mocha@9.1.1": version "9.1.1" resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-9.1.1.tgz#e7c4f1001eefa4b8afbd1eee27a237fee3bf29c4" integrity sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw== @@ -322,12 +322,12 @@ ansi-colors@4.1.1: resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== -ansi-regex@=5.0.1, ansi-regex@^4.1.0, ansi-regex@^5.0.1: +ansi-regex@5.0.1, ansi-regex@^4.1.0, ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== -ansi-styles@=4.3.0, ansi-styles@^4.0.0, ansi-styles@^4.1.0, ansi-styles@^6.0.0: +ansi-styles@4.3.0, ansi-styles@^4.0.0, ansi-styles@^4.1.0, ansi-styles@^6.0.0: version "4.3.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== @@ -380,7 +380,7 @@ available-typed-arrays@^1.0.7: dependencies: possible-typed-array-names "^1.0.0" -backslash@=0.2.0: +backslash@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/backslash/-/backslash-0.2.0.tgz#6c3c1fce7e7e714ccfc10fd74f0f73410677375f" integrity sha512-Avs+8FUZ1HF/VFP4YWwHQZSGzRPm37ukU1JQYQWijuHhtXdOuAzcZ8PcAzfIw898a8PyBzdn+RtnKA6MzW0X2A== @@ -431,7 +431,7 @@ bindings@^1.3.0: dependencies: file-uri-to-path "1.0.0" -bn.js@^5.1.2, bn.js@^5.2.0, bn.js@^5.2.1: +bn.js@5.2.2, bn.js@^5.1.2, bn.js@^5.2.0, bn.js@^5.2.1: version "5.2.2" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.2.tgz#82c09f9ebbb17107cd72cb7fd39bd1f9d0aaa566" integrity sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw== @@ -535,7 +535,7 @@ camelcase@^6.0.0, camelcase@^6.3.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -chai@^4.3.4: +chai@4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/chai/-/chai-4.5.0.tgz#707e49923afdd9b13a8b0b47d33d732d13812fd8" integrity sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw== @@ -548,14 +548,14 @@ chai@^4.3.4: pathval "^1.1.1" type-detect "^4.1.0" -chalk-template@=0.4.0: +chalk-template@0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/chalk-template/-/chalk-template-0.4.0.tgz#692c034d0ed62436b9062c1707fadcd0f753204b" integrity sha512-/ghrgmhfY8RaSdeo43hNXxpoHAtxdbskUHjPpfqUWGttFgycUhYPGx3YZBCnUCvOa7Doivn1IZec3DEGFoMgLg== dependencies: chalk "^4.1.2" -chalk@=4.1.2, chalk@^4.1.0, chalk@^4.1.2, chalk@^5.3.0, chalk@^5.4.1: +chalk@4.1.2, chalk@^4.1.0, chalk@^4.1.2, chalk@^5.3.0, chalk@^5.4.1: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -594,26 +594,26 @@ cliui@^7.0.2: strip-ansi "^6.0.0" wrap-ansi "^7.0.0" -color-convert@=2.0.1, color-convert@^2.0.1: +color-convert@2.0.1, color-convert@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== dependencies: color-name "~1.1.4" -color-name@=2.0.0, color-name@^2.0.0, color-name@~1.1.4: +color-name@2.0.0, color-name@^2.0.0, color-name@~1.1.4: version "2.0.0" resolved "https://registry.yarnpkg.com/color-name/-/color-name-2.0.0.tgz#03ff6b1b5aec9bb3cf1ed82400c2790dfcd01d2d" integrity sha512-SbtvAMWvASO5TE2QP07jHBMXKafgdZz8Vrsrn96fiL+O92/FN/PLARzUW5sKt013fjAprK2d2iCn2hk2Xb5oow== -color-string@=2.1.0, color-string@^1.9.0: +color-string@2.1.0, color-string@^1.9.0: version "2.1.0" resolved "https://registry.yarnpkg.com/color-string/-/color-string-2.1.0.tgz#a1cc4bb16a23032ff1048a2458a170323b15a23f" integrity sha512-gNVoDzpaSwvftp6Y8nqk97FtZoXP9Yj7KGYB8yIXuv0JcfqbYihTrd1OU5iZW9btfXde4YAOCRySBHT7O910MA== dependencies: color-name "^2.0.0" -color@=4.2.3: +color@4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/color/-/color-4.2.3.tgz#d781ecb5e57224ee43ea9627560107c0e0c6463a" integrity sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A== @@ -653,7 +653,7 @@ crypto-hash@^1.3.0: resolved "https://registry.yarnpkg.com/crypto-hash/-/crypto-hash-1.3.0.tgz#b402cb08f4529e9f4f09346c3e275942f845e247" integrity sha512-lyAZ0EMyjDkVvz8WOeVnuCPvKVBXcMv1l5SVqO1yC7PzTwrD/pPje/BIRbWhMoPe436U+Y2nD7f5bFx0kt+Sbg== -debug@4.3.3, debug@=4.4.1, debug@^4.3.3, debug@^4.3.4: +debug@4.3.3, debug@4.4.1, debug@^4.3.3, debug@^4.3.4: version "4.4.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.1.tgz#e5a8bc6cbc4c6cd3e64308b0693a3d4fa550189b" integrity sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ== @@ -727,7 +727,7 @@ emoji-regex@^8.0.0: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== -error-ex@=1.3.2: +error-ex@1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== @@ -908,7 +908,7 @@ growl@1.10.5: resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== -has-ansi@=4.0.1: +has-ansi@4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-4.0.1.tgz#f216a8c8d7b129e490dc15f4a62cc1cdb9603ce8" integrity sha512-Qr4RtTm30xvEdqUXbSBVWDu+PrTokJOwe/FU+VdfJPk+MXAPoeOzKpRyrDTnZIJwAkQ4oBLTU53nu0HrkF/Z2A== @@ -991,7 +991,7 @@ is-arguments@^1.0.4: call-bound "^1.0.2" has-tostringtag "^1.0.2" -is-arrayish@=0.3.2, is-arrayish@^0.2.1, is-arrayish@^0.3.1: +is-arrayish@0.3.2, is-arrayish@^0.2.1, is-arrayish@^0.3.1: version "0.3.2" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== @@ -1205,7 +1205,7 @@ mkdirp@^0.5.1: dependencies: minimist "^1.2.6" -mocha@^9.0.3: +mocha@9.2.2: version "9.2.2" resolved "https://registry.yarnpkg.com/mocha/-/mocha-9.2.2.tgz#d70db46bdb93ca57402c809333e5a84977a88fb9" integrity sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g== @@ -1419,14 +1419,14 @@ set-function-length@^1.2.2: gopd "^1.0.1" has-property-descriptors "^1.0.2" -simple-swizzle@=0.2.2: +simple-swizzle@0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" integrity sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg== dependencies: is-arrayish "^0.3.1" -slice-ansi@=5.0.0: +slice-ansi@5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-5.0.0.tgz#b73063c57aa96f9cd881654b15294d95d285c42a" integrity sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ== @@ -1467,7 +1467,7 @@ solana-bankrun-linux-x64-musl@0.2.0: resolved "https://registry.yarnpkg.com/solana-bankrun-linux-x64-musl/-/solana-bankrun-linux-x64-musl-0.2.0.tgz#a99c5187f34ab5979c708281da74093c64baab4a" integrity sha512-8mtf14ZBoah30+MIJBUwb5BlGLRZyK5cZhCkYnC/ROqaIDN8RxMM44NL63gTUIaNHsFwWGA9xR0KSeljeh3PKQ== -solana-bankrun@^0.2.0: +solana-bankrun@0.2.0, solana-bankrun@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/solana-bankrun/-/solana-bankrun-0.2.0.tgz#e1df2126ee887b9eae17962f09db18aaa25d736f" integrity sha512-TS6vYoO/9YJZng7oiLOVyuz8V7yLow5Hp4SLYWW71XM3702v+z9f1fvUBKudRfa4dfpta4tRNufApSiBIALxJQ== @@ -1523,7 +1523,7 @@ string-width@^4.1.0, string-width@^4.2.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" -strip-ansi@=6.0.1, strip-ansi@^6.0.0, strip-ansi@^6.0.1: +strip-ansi@6.0.1, strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -1550,14 +1550,14 @@ superstruct@^2.0.2: resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-2.0.2.tgz#3f6d32fbdc11c357deff127d591a39b996300c54" integrity sha512-uV+TFRZdXsqXTL2pRvujROjdZQ4RAlBUS5BTh9IGm+jTqQntYThciG/qu57Gs69yjnVUSqdxF9YLmSnpupBW9A== -supports-color@8.1.1, supports-color@=7.2.0, supports-color@^7.0.0, supports-color@^7.1.0: +supports-color@7.2.0, supports-color@8.1.1, supports-color@^7.0.0, supports-color@^7.1.0: version "7.2.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== dependencies: has-flag "^4.0.0" -supports-hyperlinks@=2.3.0: +supports-hyperlinks@2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz#3943544347c1ff90b15effb03fc14ae45ec10624" integrity sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA== @@ -1587,7 +1587,7 @@ tr46@~0.0.3: resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== -ts-mocha@^10.0.0: +ts-mocha@10.1.0: version "10.1.0" resolved "https://registry.yarnpkg.com/ts-mocha/-/ts-mocha-10.1.0.tgz#17a1c055f5f7733fd82447c4420740db87221bc8" integrity sha512-T0C0Xm3/WqCuF2tpa0GNGESTBoKZaiqdUP8guNv4ZY316AFXlyidnrzQ1LUrCT0Wb1i3J0zFTgOh/55Un44WdA== @@ -1701,7 +1701,7 @@ workerpool@6.2.0: resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.0.tgz#827d93c9ba23ee2019c3ffaff5c27fccea289e8b" integrity sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A== -wrap-ansi@=7.0.0, wrap-ansi@^7.0.0: +wrap-ansi@7.0.0, wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== diff --git a/yarn.lock b/yarn.lock index 3f05b3875..3c2163f68 100644 --- a/yarn.lock +++ b/yarn.lock @@ -42,7 +42,7 @@ resolved "https://registry.yarnpkg.com/@coral-xyz/anchor-errors/-/anchor-errors-0.31.1.tgz#d635cbac2533973ae6bfb5d3ba1de89ce5aece2d" integrity sha512-NhNEku4F3zzUSBtrYz84FzYWm48+9OvmT1Hhnwr6GnPQry2dsEqH/ti/7ASjjpoFTWRnPXrjAIT1qM6Isop+LQ== -"@coral-xyz/anchor@=0.29.0", "@coral-xyz/anchor@^0.29.0": +"@coral-xyz/anchor@0.29.0": version "0.29.0" resolved "https://registry.yarnpkg.com/@coral-xyz/anchor/-/anchor-0.29.0.tgz#bd0be95bedfb30a381c3e676e5926124c310ff12" integrity sha512-eny6QNG0WOwqV0zQ7cs/b1tIuzZGmP7U7EcH+ogt4Gdbl8HDmIYVMh/9aTmYZPaFWjtUaI8qSn73uYEXWfATdA== @@ -313,7 +313,7 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@eslint/js@9.38.0", "@eslint/js@^9.35.0": +"@eslint/js@9.38.0": version "9.38.0" resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.38.0.tgz#f7aa9c7577577f53302c1d795643589d7709ebd1" integrity sha512-UZ1VpFvXf9J06YG9xQBdnzU+kthors6KjhMAl6f4gH4usHyh31rUf2DLGInT8RFYIReYXNSydgPY0V2LuWgl7A== @@ -795,7 +795,7 @@ "@inquirer/core" "^10.3.0" "@inquirer/type" "^3.0.9" -"@inquirer/prompts@^7.3.3": +"@inquirer/prompts@7.9.0": version "7.9.0" resolved "https://registry.yarnpkg.com/@inquirer/prompts/-/prompts-7.9.0.tgz#497718b2ac43b15cac636d8f7b501efd1574e1cd" integrity sha512-X7/+dG9SLpSzRkwgG5/xiIzW0oMrV3C0HOa7YHG1WnrLK+vCQHfte4k/T80059YBdei29RBC3s+pSMvPJDU9/A== @@ -867,12 +867,12 @@ "@metadaoproject/programs@./sdk": version "0.1.0-alpha.2" dependencies: - "@coral-xyz/anchor" "^0.29.0" - "@noble/hashes" "^1.4.0" - "@solana/spl-token" "^0.3.7" - "@solana/web3.js" "^1.76.0" - "@sqds/multisig" "^2.1.4" - bn.js "^5.2.1" + "@coral-xyz/anchor" "0.29.0" + "@noble/hashes" "1.8.0" + "@solana/spl-token" "0.3.11" + "@solana/web3.js" "1.98.4" + "@sqds/multisig" "2.1.4" + bn.js "5.2.2" "@metaplex-foundation/beet-solana@0.4.0": version "0.4.0" @@ -908,7 +908,7 @@ resolved "https://registry.yarnpkg.com/@metaplex-foundation/cusper/-/cusper-0.0.2.tgz#dc2032a452d6c269e25f016aa4dd63600e2af975" integrity sha512-S9RulC2fFCFOQraz61bij+5YCHhSO9llJegK8c8Y6731fSi6snUSQJdCUqYS8AIgR0TKbQvdvgSyIIdbDFZbBA== -"@metaplex-foundation/mpl-token-metadata@^3.2.0": +"@metaplex-foundation/mpl-token-metadata@3.4.0": version "3.4.0" resolved "https://registry.yarnpkg.com/@metaplex-foundation/mpl-token-metadata/-/mpl-token-metadata-3.4.0.tgz#03a2ab3b90ac30973407565e07cc570c8897385d" integrity sha512-AxBAYCK73JWxY3g9//z/C9krkR0t1orXZDknUPS4+GjwGH2vgPfsk04yfZ31Htka2AdS9YE/3wH7sMUBHKn9Rg== @@ -920,7 +920,7 @@ resolved "https://registry.yarnpkg.com/@metaplex-foundation/mpl-toolbox/-/mpl-toolbox-0.10.0.tgz#c7d2f27259e69ab86cc4b7dd55b7bfef11bbed13" integrity sha512-84KD1L5cFyw5xnntHwL4uPwfcrkKSiwuDeypiVr92qCUFuF3ZENa2zlFVPu+pQcjTlod2LmEX3MhBmNjRMpdKg== -"@metaplex-foundation/umi-bundle-defaults@^0.9.1": +"@metaplex-foundation/umi-bundle-defaults@0.9.2": version "0.9.2" resolved "https://registry.yarnpkg.com/@metaplex-foundation/umi-bundle-defaults/-/umi-bundle-defaults-0.9.2.tgz#f8e296b1a0ecb3a6511dbaca4131bc9263071cfc" integrity sha512-kV3tfvgvRjVP1p9OFOtH+ibOtN9omVJSwKr0We4/9r45e5LTj+32su0V/rixZUkG1EZzzOYBsxhtIE0kIw/Hrw== @@ -1018,7 +1018,7 @@ "@metaplex-foundation/umi-serializers-encodings" "^0.8.9" "@metaplex-foundation/umi-serializers-numbers" "^0.8.9" -"@metaplex-foundation/umi-signer-wallet-adapters@^1.1.1": +"@metaplex-foundation/umi-signer-wallet-adapters@1.4.1": version "1.4.1" resolved "https://registry.yarnpkg.com/@metaplex-foundation/umi-signer-wallet-adapters/-/umi-signer-wallet-adapters-1.4.1.tgz#38bb5db562f2da168c81fed71498175de1852de6" integrity sha512-Y2qUFxtpbO4qnot+H99f7mvH2+IAJwOdq4kXKRTlwKX9yBznE43wvsF968lnzUNiuyY86E8MQqoemK6xGifMJw== @@ -1032,7 +1032,7 @@ dependencies: "@metaplex-foundation/umi-web3js-adapters" "^0.9.2" -"@metaplex-foundation/umi-uploader-bundlr@^0.9.1": +"@metaplex-foundation/umi-uploader-bundlr@0.9.2": version "0.9.2" resolved "https://registry.yarnpkg.com/@metaplex-foundation/umi-uploader-bundlr/-/umi-uploader-bundlr-0.9.2.tgz#0d832816a32970cac9f412a0b0a8234415ab8534" integrity sha512-wmixKqWyEO0lRB2GNvm5XOwi3jEyCtPZ6Oqds6sY5YHYdrn1Cqgd1TcdAuu7+DuojcNFErTjWsaQ1F9QR502QQ== @@ -1042,6 +1042,13 @@ bignumber.js "^9.0.2" buffer "^6.0.3" +"@metaplex-foundation/umi-web3js-adapters@1.4.1", "@metaplex-foundation/umi-web3js-adapters@^1.4.1": + version "1.4.1" + resolved "https://registry.yarnpkg.com/@metaplex-foundation/umi-web3js-adapters/-/umi-web3js-adapters-1.4.1.tgz#1c2edae285c94e16fc3eed5da16061b31fc82dbd" + integrity sha512-9LkueHDVVljRY83HcaRxGh011zMwrFpvlgb2VrkYlhC7afTM7VrDw4oxdR1zwC80bXyf0D1gyKqi+ANO8QQqtw== + dependencies: + buffer "^6.0.3" + "@metaplex-foundation/umi-web3js-adapters@^0.9.2": version "0.9.2" resolved "https://registry.yarnpkg.com/@metaplex-foundation/umi-web3js-adapters/-/umi-web3js-adapters-0.9.2.tgz#1e0ebb4e3c31e8bead27892b20204292ad6955c5" @@ -1049,14 +1056,7 @@ dependencies: buffer "^6.0.3" -"@metaplex-foundation/umi-web3js-adapters@^1.1.1", "@metaplex-foundation/umi-web3js-adapters@^1.4.1": - version "1.4.1" - resolved "https://registry.yarnpkg.com/@metaplex-foundation/umi-web3js-adapters/-/umi-web3js-adapters-1.4.1.tgz#1c2edae285c94e16fc3eed5da16061b31fc82dbd" - integrity sha512-9LkueHDVVljRY83HcaRxGh011zMwrFpvlgb2VrkYlhC7afTM7VrDw4oxdR1zwC80bXyf0D1gyKqi+ANO8QQqtw== - dependencies: - buffer "^6.0.3" - -"@metaplex-foundation/umi@^0.9.1": +"@metaplex-foundation/umi@0.9.2": version "0.9.2" resolved "https://registry.yarnpkg.com/@metaplex-foundation/umi/-/umi-0.9.2.tgz#6460bff91d2ac7745842eda1ee6a28fba4d2ffb2" integrity sha512-9i4Acm4pruQfJcpRrc2EauPBwkfDN0I9QTvJyZocIlKgoZwD6A6wH0PViH1AjOVG5CQCd1YI3tJd5XjYE1ElBw== @@ -1065,7 +1065,7 @@ "@metaplex-foundation/umi-public-keys" "^0.8.9" "@metaplex-foundation/umi-serializers" "^0.9.0" -"@meteora-ag/cp-amm-sdk@^1.2.6": +"@meteora-ag/cp-amm-sdk@1.2.6": version "1.2.6" resolved "https://registry.yarnpkg.com/@meteora-ag/cp-amm-sdk/-/cp-amm-sdk-1.2.6.tgz#9eb24abc0ed3b09eb96aabfe5af5e8d56637ebe5" integrity sha512-EYNk6/6/AwMAyFCwA9ZG1svJfUOM8cn8mpg/un/PkImuNSrbRlN9Apiw+mRiwLvrEiCjSVUCDyGJofr/eX5TFQ== @@ -1085,22 +1085,22 @@ dependencies: "@noble/hashes" "1.8.0" +"@noble/ed25519@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@noble/ed25519/-/ed25519-2.3.0.tgz#df0dbe424cfd7da4968b956b819c15db5fbe7f21" + integrity sha512-M7dvXL2B92/M7dw9+gzuydL8qn/jiqNHaoR3Q+cb1q1GHV7uwE17WCyFMG+Y+TZb5izcaXk5TdJRrDUxHXL78A== + "@noble/ed25519@^1.6.1": version "1.7.5" resolved "https://registry.yarnpkg.com/@noble/ed25519/-/ed25519-1.7.5.tgz#94df8bdb9fec9c4644a56007eecb57b0e9fbd0d7" integrity sha512-xuS0nwRMQBvSxDa7UxMb61xTiH3MxTgUfhyPUALVIe0FlOAz4sjELwyDRyUvqeEYfRSG9qNjFIycqLZppg4RSA== -"@noble/ed25519@^2.0.0": - version "2.3.0" - resolved "https://registry.yarnpkg.com/@noble/ed25519/-/ed25519-2.3.0.tgz#df0dbe424cfd7da4968b956b819c15db5fbe7f21" - integrity sha512-M7dvXL2B92/M7dw9+gzuydL8qn/jiqNHaoR3Q+cb1q1GHV7uwE17WCyFMG+Y+TZb5izcaXk5TdJRrDUxHXL78A== - "@noble/hashes@1.8.0", "@noble/hashes@^1.3.0", "@noble/hashes@^1.3.1", "@noble/hashes@^1.4.0": version "1.8.0" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.8.0.tgz#cee43d801fcef9644b11b8194857695acd5f815a" integrity sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A== -"@noble/secp256k1@^2.0.0": +"@noble/secp256k1@2.3.0": version "2.3.0" resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-2.3.0.tgz#ddfe6e853472fb88cba4d5e59b7067adc1e64adf" integrity sha512-0TQed2gcBbIrh7Ccyw+y/uZQvbJwm7Ao4scBUxqpBCcsOlZG0O4KGfjtNAy/li4W8n1xt3dxrwJ0beZ2h2G6Kw== @@ -1241,7 +1241,7 @@ "@solana/codecs-strings" "2.0.0-rc.1" "@solana/errors" "2.0.0-rc.1" -"@solana/spl-memo@^0.2.3": +"@solana/spl-memo@0.2.5": version "0.2.5" resolved "https://registry.yarnpkg.com/@solana/spl-memo/-/spl-memo-0.2.5.tgz#a7828cdd1e810ff77c7c015ac97dfa166d0651fe" integrity sha512-0Zx5t3gAdcHlRTt2O3RgGlni1x7vV7Xq7j4z9q8kKOMgU03PyoTbFQ/BSYCcICHzkaqD7ZxAiaJ6dlXolg01oA== @@ -1262,14 +1262,14 @@ dependencies: "@solana/codecs" "2.0.0-rc.1" -"@solana/spl-token-registry@^0.2.4574": +"@solana/spl-token-registry@0.2.4574": version "0.2.4574" resolved "https://registry.yarnpkg.com/@solana/spl-token-registry/-/spl-token-registry-0.2.4574.tgz#13f4636b7bec90d2bb43bbbb83512cd90d2ce257" integrity sha512-JzlfZmke8Rxug20VT/VpI2XsXlsqMlcORIUivF+Yucj7tFi7A0dXG7h+2UnD0WaZJw8BrUz2ABNkUnv89vbv1A== dependencies: cross-fetch "3.0.6" -"@solana/spl-token@^0.3.6", "@solana/spl-token@^0.3.7", "@solana/spl-token@^0.3.8": +"@solana/spl-token@0.3.11", "@solana/spl-token@^0.3.6", "@solana/spl-token@^0.3.8": version "0.3.11" resolved "https://registry.yarnpkg.com/@solana/spl-token/-/spl-token-0.3.11.tgz#cdc10f9472b29b39c8983c92592cadd06627fb9a" integrity sha512-bvohO3rIMSVL24Pb+I4EYTJ6cL82eFpInEXD/I8K8upOGjpqHsKUoAempR/RnUlI1qSFNyFlWJfu6MNUgfbCQQ== @@ -1308,7 +1308,7 @@ "@wallet-standard/base" "^1.1.0" "@wallet-standard/features" "^1.1.0" -"@solana/web3.js@=1.76.0": +"@solana/web3.js@1.76.0": version "1.76.0" resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.76.0.tgz#0f888e25d727d0dadf3dd8a01967347555200b2b" integrity sha512-aJtF/nTs+9St+KtTK/wgVJ+SinfjYzn+3w1ygYIPw8ST6LH+qHBn8XkodgDTwlv/xzNkaVz1kkUDOZ8BPXyZWA== @@ -1329,7 +1329,7 @@ rpc-websockets "^7.5.1" superstruct "^0.14.2" -"@solana/web3.js@>1.92.0, <2.0", "@solana/web3.js@^1.32.0", "@solana/web3.js@^1.36.0", "@solana/web3.js@^1.56.2", "@solana/web3.js@^1.68.0", "@solana/web3.js@^1.69.0", "@solana/web3.js@^1.70.3", "@solana/web3.js@^1.76.0", "@solana/web3.js@^1.95.3", "@solana/web3.js@^1.98.4": +"@solana/web3.js@1.98.4", "@solana/web3.js@>1.92.0, <2.0", "@solana/web3.js@^1.32.0", "@solana/web3.js@^1.36.0", "@solana/web3.js@^1.56.2", "@solana/web3.js@^1.68.0", "@solana/web3.js@^1.69.0", "@solana/web3.js@^1.70.3", "@solana/web3.js@^1.95.3", "@solana/web3.js@^1.98.4": version "1.98.4" resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.98.4.tgz#df51d78be9d865181ec5138b4e699d48e6895bbe" integrity sha512-vv9lfnvjUsRiq//+j5pBdXig0IQdtzA0BRZ3bXEP4KaIyF1CcaydWqgyzQgfZMNIsWNWmG+AUHwPy4AHOD6gpw== @@ -1350,7 +1350,7 @@ rpc-websockets "^9.0.2" superstruct "^2.0.2" -"@sqds/multisig@^2.1.4": +"@sqds/multisig@2.1.4": version "2.1.4" resolved "https://registry.yarnpkg.com/@sqds/multisig/-/multisig-2.1.4.tgz#f69067ee8e23e86b1170ae7509cdfbc460ac9d0d" integrity sha512-5w+NmwHOzl96nI50R/fjSD6uFydRLNUquhoEmmWbGepS4D9DnQyF2TKcUBfTyxV3sgJt00ypBt7SXB3y8WOzUQ== @@ -1398,14 +1398,14 @@ resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== -"@types/bn.js@^5.1.0", "@types/bn.js@^5.1.1": +"@types/bn.js@5.2.0", "@types/bn.js@^5.1.0", "@types/bn.js@^5.1.1": version "5.2.0" resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.2.0.tgz#4349b9710e98f9ab3cdc50f1c5e4dcbd8ef29c80" integrity sha512-DLbJ1BPqxvQhIGbeu8VbUC1DiAiahHtAYvA0ZEAa4P31F7IaArc8z3C3BRQdWX4mtLQuABG4yzp76ZrS02Ui1Q== dependencies: "@types/node" "*" -"@types/chai@^4.3.0": +"@types/chai@4.3.20": version "4.3.20" resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.20.tgz#cb291577ed342ca92600430841a00329ba05cecc" integrity sha512-/pC9HAB5I/xMlc5FP77qjCnI16ChlJfW0tGa0IUcFn38VJrTV6DeZ60NU5KZBtaOZqjdpwTWohz5HU1RrhiYxQ== @@ -1422,7 +1422,7 @@ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e" integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w== -"@types/inquirer@^9.0.7": +"@types/inquirer@9.0.9": version "9.0.9" resolved "https://registry.yarnpkg.com/@types/inquirer/-/inquirer-9.0.9.tgz#c659dffbb8c2dab112324c7ae19b3303a972a96d" integrity sha512-/mWx5136gts2Z2e5izdoRCo46lPp5TMs9R15GTSsgg/XnZyxDWVqoVU3R9lWnccKpqwsJLvRoxbCjoJtZB7DSw== @@ -1440,7 +1440,7 @@ resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== -"@types/mocha@^10.0.7": +"@types/mocha@10.0.10": version "10.0.10" resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-10.0.10.tgz#91f62905e8d23cbd66225312f239454a23bebfa0" integrity sha512-xPyYSz1cMPnJQhl0CLMH68j3gprKZaTjG3s5Vi+fDgx+uhG9NOXwbVt52eFS8ECyXhyKcjDLCBEqBExKuiZb7Q== @@ -1457,18 +1457,18 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-11.11.6.tgz#df929d1bb2eee5afdda598a41930fe50b43eaa6a" integrity sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ== -"@types/node@^12.12.54": - version "12.20.55" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.55.tgz#c329cbd434c42164f846b909bd6f85b5537f6240" - integrity sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ== - -"@types/node@^20.8.6": +"@types/node@20.19.23": version "20.19.23" resolved "https://registry.yarnpkg.com/@types/node/-/node-20.19.23.tgz#7de99389c814071cca78656a3243f224fed7453d" integrity sha512-yIdlVVVHXpmqRhtyovZAcSy0MiPcYWGkoO4CGe/+jpP0hmNuihm4XhHbADpK++MsiLHP5MVlv+bcgdF99kSiFQ== dependencies: undici-types "~6.21.0" +"@types/node@^12.12.54": + version "12.20.55" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.55.tgz#c329cbd434c42164f846b909bd6f85b5537f6240" + integrity sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ== + "@types/through@*": version "0.0.33" resolved "https://registry.yarnpkg.com/@types/through/-/through-0.0.33.tgz#14ebf599320e1c7851e7d598149af183c6b9ea56" @@ -1678,12 +1678,12 @@ algosdk@^1.13.1: tweetnacl "^1.0.3" vlq "^2.0.4" -anchor-bankrun@^0.3.0: +anchor-bankrun@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/anchor-bankrun/-/anchor-bankrun-0.3.0.tgz#3789fcecbc201a2334cff228b99cc0da8ef0167e" integrity sha512-PYBW5fWX+iGicIS5MIM/omhk1tQPUc0ELAnI/IkLKQJ6d75De/CQRh8MF2bU/TgGyFi6zEel80wUe3uRol9RrQ== -anchor-litesvm@^0.1.2: +anchor-litesvm@0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/anchor-litesvm/-/anchor-litesvm-0.1.2.tgz#c2f59c5a019c8b5b6cf2ce4b32c85a29ec15c349" integrity sha512-WW8PlPgbHhXdg4Blprw5leOm6hBRZv3fJDtbVs24s4iXSlMOYPy1ZWV8yfeumjyL6xHEHrAjogG89ogoTxseSQ== @@ -1798,7 +1798,7 @@ arweave-stream-tx@^1.1.0: dependencies: exponential-backoff "^3.1.0" -arweave@^1.10.13, arweave@^1.11.4, arweave@^1.14.4: +arweave@1.15.7, arweave@^1.10.13, arweave@^1.11.4: version "1.15.7" resolved "https://registry.yarnpkg.com/arweave/-/arweave-1.15.7.tgz#d09265d128e93a471203649de083ba7fec52cb29" integrity sha512-F+Y4iWU1qea9IsKQ/YNmLsY4DHQVsaJBuhEbFxQn9cfGHOmtXE+bwo14oY8xqymsqSNf/e1PeIfLk7G7qN/hVA== @@ -1959,16 +1959,16 @@ bn.js@5.2.0: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.0.tgz#358860674396c6997771a9d051fcc1b57d4ae002" integrity sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw== +bn.js@5.2.2, bn.js@^5.0.0, bn.js@^5.1.2, bn.js@^5.2.0, bn.js@^5.2.1: + version "5.2.2" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.2.tgz#82c09f9ebbb17107cd72cb7fd39bd1f9d0aaa566" + integrity sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw== + bn.js@^4.0.0, bn.js@^4.11.9: version "4.12.2" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.2.tgz#3d8fed6796c24e177737f7cc5172ee04ef39ec99" integrity sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw== -bn.js@^5.0.0, bn.js@^5.1.2, bn.js@^5.2.0, bn.js@^5.2.1: - version "5.2.2" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.2.tgz#82c09f9ebbb17107cd72cb7fd39bd1f9d0aaa566" - integrity sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw== - borsh@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/borsh/-/borsh-0.6.0.tgz#a7c9eeca6a31ca9e0607cb49f329cb659eb791e1" @@ -2019,6 +2019,13 @@ browser-stdout@1.3.1: resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== +bs58@6.0.0, bs58@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/bs58/-/bs58-6.0.0.tgz#a2cda0130558535dd281a2f8697df79caaf425d8" + integrity sha512-PD0wEnEYg6ijszw/u8s+iI3H17cTymlrwkKhDhPZq+Sokl3AU4htyBFTjAeNAlCCmg0f53g6ih3jATyCKftTfw== + dependencies: + base-x "^5.0.0" + bs58@^4.0.0, bs58@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" @@ -2033,13 +2040,6 @@ bs58@^5.0.0: dependencies: base-x "^4.0.0" -bs58@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/bs58/-/bs58-6.0.0.tgz#a2cda0130558535dd281a2f8697df79caaf425d8" - integrity sha512-PD0wEnEYg6ijszw/u8s+iI3H17cTymlrwkKhDhPZq+Sokl3AU4htyBFTjAeNAlCCmg0f53g6ih3jATyCKftTfw== - dependencies: - base-x "^5.0.0" - buffer-from@^1.0.0, buffer-from@^1.1.0: version "1.1.2" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" @@ -2114,7 +2114,7 @@ capability@^0.2.5: resolved "https://registry.yarnpkg.com/capability/-/capability-0.2.5.tgz#51ad87353f1936ffd77f2f21c74633a4dea88801" integrity sha512-rsJZYVCgXd08sPqwmaIqjAd5SUTfonV0z/gDJ8D6cN8wQphky1kkAYEqQ+hmDxTw7UihvBfjUVUSY+DBEe44jg== -chai@^4.3.4: +chai@4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/chai/-/chai-4.5.0.tgz#707e49923afdd9b13a8b0b47d33d732d13812fd8" integrity sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw== @@ -2459,7 +2459,7 @@ dot-case@^3.0.4: no-case "^3.0.4" tslib "^2.0.3" -dotenv@^16.4.7: +dotenv@16.6.1: version "16.6.1" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.6.1.tgz#773f0e69527a8315c7285d5ee73c4459d20a8020" integrity sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow== @@ -2586,7 +2586,7 @@ escape-string-regexp@^1.0.5: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== -eslint-plugin-unused-imports@^4.2.0: +eslint-plugin-unused-imports@4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.3.0.tgz#69ff9c4f83f02f7789808bbbab77636cb742af50" integrity sha512-ZFBmXMGBYfHttdRtOG9nFFpmUvMtbHSjsKrS20vdWdbfiVYsO3yA2SGYy9i9XmZJDfMGBflZGBCm70SEnFQtOA== @@ -2609,7 +2609,7 @@ eslint-visitor-keys@^4.2.1: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz#4cfea60fe7dd0ad8e816e1ed026c1d5251b512c1" integrity sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ== -eslint@^9.35.0: +eslint@9.38.0: version "9.38.0" resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.38.0.tgz#3957d2af804e5cf6cc503c618f60acc71acb2e7e" integrity sha512-t5aPOpmtJcZcz5UJyY2GbvpDlsK5E8JqRqoKtfiKE3cNh437KIqfJr3A3AKf5k64NPx6d0G3dno6XDY05PqPtw== @@ -2937,16 +2937,16 @@ glob@7.2.0: once "^1.3.0" path-is-absolute "^1.0.0" +globals@16.4.0: + version "16.4.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-16.4.0.tgz#574bc7e72993d40cf27cf6c241f324ee77808e51" + integrity sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw== + globals@^14.0.0: version "14.0.0" resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e" integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ== -globals@^16.4.0: - version "16.4.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-16.4.0.tgz#574bc7e72993d40cf27cf6c241f324ee77808e51" - integrity sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw== - gopd@^1.0.1, gopd@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" @@ -3048,7 +3048,7 @@ humanize-ms@^1.2.1: dependencies: ms "^2.0.0" -husky@^9.1.7: +husky@9.1.7: version "9.1.7" resolved "https://registry.yarnpkg.com/husky/-/husky-9.1.7.tgz#d46a38035d101b46a70456a850ff4201344c0b2d" integrity sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA== @@ -3286,7 +3286,7 @@ jayson@^4.1.1: uuid "^8.3.2" ws "^7.5.10" -jiti@^2.5.1: +jiti@2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/jiti/-/jiti-2.6.1.tgz#178ef2fc9a1a594248c20627cd820187a4d78d92" integrity sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ== @@ -3381,7 +3381,7 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" -lint-staged@^16.2.0: +lint-staged@16.2.5: version "16.2.5" resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-16.2.5.tgz#85f9dbe48f379217b7b0554be17c9da222f373a6" integrity sha512-o36wH3OX0jRWqDw5dOa8a8x6GXTKaLM+LvhRaucZxez0IxA+KNDUCiyjBfNgsMNmchwSX6urLSL7wShcUqAang== @@ -3456,6 +3456,20 @@ litesvm-linux-x64-musl@0.3.3: resolved "https://registry.yarnpkg.com/litesvm-linux-x64-musl/-/litesvm-linux-x64-musl-0.3.3.tgz#b8af27749f8df1f51a039fb33ed3f81cc66631a9" integrity sha512-bpWZ2f506hbfu1y6bkmuZf+qqtnLDxggpOMTQbibjd+q6faEO3sETWwKGlIgHB99P8wyU+aXKwLSGQX2sJEw6Q== +litesvm@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/litesvm/-/litesvm-0.2.0.tgz#539c83d8b377a725877a5813b5aa726774c8db9f" + integrity sha512-75+ZMkSFY5ynI3S+vCMnZv1wcILg5iNEj21B+XE/G3/P2dfTPj+rbdNM1q3eLFdlnXdewhiB4BLypKsBnQTSOw== + dependencies: + "@solana/web3.js" "^1.68.0" + bs58 "^4.0.1" + optionalDependencies: + litesvm-darwin-arm64 "0.2.0" + litesvm-darwin-universal "0.2.0" + litesvm-darwin-x64 "0.2.0" + litesvm-linux-x64-gnu "0.2.0" + litesvm-linux-x64-musl "0.2.0" + "litesvm@>=0.1.0, <0.4.0": version "0.3.3" resolved "https://registry.yarnpkg.com/litesvm/-/litesvm-0.3.3.tgz#2dac5fab34327de9fc8c673fbc0736e7603a1b19" @@ -3471,20 +3485,6 @@ litesvm-linux-x64-musl@0.3.3: litesvm-linux-x64-gnu "0.3.3" litesvm-linux-x64-musl "0.3.3" -litesvm@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/litesvm/-/litesvm-0.2.0.tgz#539c83d8b377a725877a5813b5aa726774c8db9f" - integrity sha512-75+ZMkSFY5ynI3S+vCMnZv1wcILg5iNEj21B+XE/G3/P2dfTPj+rbdNM1q3eLFdlnXdewhiB4BLypKsBnQTSOw== - dependencies: - "@solana/web3.js" "^1.68.0" - bs58 "^4.0.1" - optionalDependencies: - litesvm-darwin-arm64 "0.2.0" - litesvm-darwin-universal "0.2.0" - litesvm-darwin-x64 "0.2.0" - litesvm-linux-x64-gnu "0.2.0" - litesvm-linux-x64-musl "0.2.0" - locate-path@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" @@ -3639,7 +3639,7 @@ mkdirp@^0.5.1: dependencies: minimist "^1.2.6" -mocha@^9.0.3: +mocha@9.2.2: version "9.2.2" resolved "https://registry.yarnpkg.com/mocha/-/mocha-9.2.2.tgz#d70db46bdb93ca57402c809333e5a84977a88fb9" integrity sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g== @@ -3951,7 +3951,7 @@ prelude-ls@^1.2.1: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== -prettier@^3.6.2: +prettier@3.6.2: version "3.6.2" resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.6.2.tgz#ccda02a1003ebbb2bfda6f83a074978f608b9393" integrity sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ== @@ -4265,7 +4265,7 @@ solana-bankrun-linux-x64-musl@0.3.1: resolved "https://registry.yarnpkg.com/solana-bankrun-linux-x64-musl/-/solana-bankrun-linux-x64-musl-0.3.1.tgz#1a044a132138a0084e82406ec7bf4939f06bed68" integrity sha512-6r8i0NuXg3CGURql8ISMIUqhE7Hx/O7MlIworK4oN08jYrP0CXdLeB/hywNn7Z8d1NXrox/NpYUgvRm2yIzAsQ== -solana-bankrun@^0.3.0: +solana-bankrun@0.3.1, solana-bankrun@^0.3.0: version "0.3.1" resolved "https://registry.yarnpkg.com/solana-bankrun/-/solana-bankrun-0.3.1.tgz#13665ab7c1c15ec2b3354aae56980d0ded514998" integrity sha512-inRwON7fBU5lPC36HdEqPeDg15FXJYcf77+o0iz9amvkUMJepcwnRwEfTNyMVpVYdgjTOBW5vg+596/3fi1kGA== @@ -4478,7 +4478,7 @@ ts-api-utils@^2.1.0: resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-2.1.0.tgz#595f7094e46eed364c13fd23e75f9513d29baf91" integrity sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ== -ts-mocha@^10.0.0: +ts-mocha@10.1.0: version "10.1.0" resolved "https://registry.yarnpkg.com/ts-mocha/-/ts-mocha-10.1.0.tgz#17a1c055f5f7733fd82447c4420740db87221bc8" integrity sha512-T0C0Xm3/WqCuF2tpa0GNGESTBoKZaiqdUP8guNv4ZY316AFXlyidnrzQ1LUrCT0Wb1i3J0zFTgOh/55Un44WdA== @@ -4487,21 +4487,7 @@ ts-mocha@^10.0.0: optionalDependencies: tsconfig-paths "^3.5.0" -ts-node@7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-7.0.1.tgz#9562dc2d1e6d248d24bc55f773e3f614337d9baf" - integrity sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw== - dependencies: - arrify "^1.0.0" - buffer-from "^1.1.0" - diff "^3.1.0" - make-error "^1.1.1" - minimist "^1.2.0" - mkdirp "^0.5.1" - source-map-support "^0.5.6" - yn "^2.0.0" - -ts-node@^10.9.2: +ts-node@10.9.2: version "10.9.2" resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f" integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ== @@ -4520,6 +4506,20 @@ ts-node@^10.9.2: v8-compile-cache-lib "^3.0.1" yn "3.1.1" +ts-node@7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-7.0.1.tgz#9562dc2d1e6d248d24bc55f773e3f614337d9baf" + integrity sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw== + dependencies: + arrify "^1.0.0" + buffer-from "^1.1.0" + diff "^3.1.0" + make-error "^1.1.1" + minimist "^1.2.0" + mkdirp "^0.5.1" + source-map-support "^0.5.6" + yn "^2.0.0" + tsconfig-paths@^3.5.0: version "3.15.0" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz#5299ec605e55b1abb23ec939ef15edaf483070d4" @@ -4535,7 +4535,7 @@ tslib@^2.0.3, tslib@^2.1.0, tslib@^2.8.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== -tsx@^4.7.1: +tsx@4.20.6: version "4.20.6" resolved "https://registry.yarnpkg.com/tsx/-/tsx-4.20.6.tgz#8fb803fd9c1f70e8ccc93b5d7c5e03c3979ccb2e" integrity sha512-ytQKuwgmrrkDTFP4LjR0ToE2nqgy886GpvRSpU0JAnrdBYppuY5rLkRUYPU1yCryb24SsKBTL/hlDQAEFVwtZg== @@ -4576,7 +4576,7 @@ typed-array-buffer@^1.0.3: es-errors "^1.3.0" is-typed-array "^1.1.14" -typescript-eslint@^8.43.0: +typescript-eslint@8.46.2: version "8.46.2" resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-8.46.2.tgz#da1adec683ba93a1b6c3850a4efb0922ffbc627d" integrity sha512-vbw8bOmiuYNdzzV3lsiWv6sRwjyuKJMQqWulBOU7M0RrxedXledX8G8kBbQeiOYDnTfiXz0Y4081E1QMNB6iQg==