diff --git a/.github/actions/setup-anchor/action.yaml b/.github/actions/setup-workspace/action.yaml similarity index 68% rename from .github/actions/setup-anchor/action.yaml rename to .github/actions/setup-workspace/action.yaml index 4a1e759..9f75892 100644 --- a/.github/actions/setup-anchor/action.yaml +++ b/.github/actions/setup-workspace/action.yaml @@ -1,22 +1,10 @@ -name: "Solana Local Validator" -author: "Switchboard Labs" +name: "Setup workspace" + description: - "Start a localnet Solana validator with a specific feature set enabled." -branding: - color: purple - icon: activity + "Build the workspace and install all dependencies including Rust, Solana, + Anchor, NodeJS, and pnpm" + inputs: - cluster: - type: choice - description: "the cluster to match a feature set for" - required: false - default: "local" - options: - - "all" - - "local" - - "devnet" - - "testnet" - - "mainnet" rust-version: description: "" required: false @@ -26,19 +14,18 @@ inputs: required: false default: "stable" anchor-version: - description: - "the Anchor version to install. if blank then dont install anchor" + description: "the Anchor version to install" required: false - default: "" - args: - description: "solana-test-validator arguements" + default: "0.26.0" + node-version: + description: "the NodeJS version to install" required: false - default: "" - quiet: - type: boolean - description: "suppress solana-test-validator stdout" + default: "18" + pnpm-version: + description: "the pnpm version to install" required: false - default: true + default: "7.28.0" + runs: using: "composite" steps: @@ -100,25 +87,6 @@ runs: run: | solana --version - # Install Solana Cluster Feature Set Diff - - name: Cache SCFSD Install - id: cache-scfsd-cli - uses: actions/cache@v3 - with: - path: | - ~/.cargo/bin/scfsd - key: scfsd-cli-${{ runner.os }}-9f742d455586a3cae2a31b85d0bb1c8709c143ab - - name: Cargo Install SCFSD - shell: bash - if: steps.cache-scfsd-cli.outputs.cache-hit != 'true' - run: - cargo install --git https://github.com/FrankC01/solana-gadgets --rev - 9f742d455586a3cae2a31b85d0bb1c8709c143ab scfsd - - name: Verify SCFSD Install - shell: bash - run: | - scfsd --version - # Install Anchor - name: Setup Anchor Cache uses: actions/cache@v3 @@ -152,14 +120,41 @@ runs: find ~/.config/solana/id.json || solana-keygen new -s --no-bip39-passphrase echo "DEFAULT_SOLANA_PUBLIC_KEY=$(solana-keygen pubkey ~/.config/solana/id.json)" >> $GITHUB_ENV - # Setup Local Validator Config - - name: Optional Quiet Flag + - name: Install pnpm + uses: pnpm/action-setup@v2 + with: + version: ${{inputs.pnpm-version }} + - name: Use Node.js + uses: actions/setup-node@v3 + with: + node-version: ${{inputs.node-version }} + cache: "pnpm" + - name: Get pnpm store directory + id: pnpm-cache shell: bash - run: - echo "SOLANA_QUIET_FLAG=$(${{ inputs.quiet }} && echo -q )" >> - $GITHUB_ENV - - name: Get Cluster Feature Set + run: | + echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT + - uses: actions/cache@v3 + name: Setup pnpm cache + with: + path: ${{ steps.pnpm-cache.outputs.STORE_PATH }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-pnpm-store- + - name: Install Dependencies shell: bash - run: - echo "SOLANA_FEATURES=$(scfsd -c ${{ inputs.cluster }} -k -t )" >> - $GITHUB_ENV + run: pnpm install --frozen-lockfile + - name: Setup Solana SDK Cache + id: cache-solana-sdk-build + uses: actions/cache@v3 + with: + key: + ${{ runner.os }}-Solana.js-${{ + hashFiles('javascript/solana.js/src/**') }} + path: | + javascript/solana.js/lib + - name: Build solana.js + if: steps.cache-solana-sdk-build.outputs.cache-hit != 'true' + shell: bash + working-directory: javascript/solana.js + run: pnpm build diff --git a/.github/workflows/anchor-test.yml b/.github/workflows/anchor-test.yml new file mode 100644 index 0000000..482bb24 --- /dev/null +++ b/.github/workflows/anchor-test.yml @@ -0,0 +1,81 @@ +name: Anchor Tests +on: + workflow_dispatch: + push: + branches: + - "main" + paths: + - "javascript/solana.js/**" + - "programs/**" + - "rust/switchboard-v2/**" + +jobs: + vrfParserTest: + name: "Anchor VRF Parser Tests" + runs-on: ubuntu-latest + defaults: + run: + shell: bash + steps: + - uses: actions/checkout@v3 + - name: Setup Workspace + uses: ./.github/actions/setup-workspace + + - name: Cache Build + id: cache-anchor-vrf-build + uses: actions/cache@v3 + with: + path: | + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + ./programs/anchor-vrf-parser/deploy + ./programs/anchor-vrf-parser/target + key: + ${{ runner.os }}-AnchorVrfParser-${{ + hashFiles('./programs/anchor-vrf-parser/Cargo.toml', + './programs/anchor-vrf-parser/src/**') }} + + - name: Anchor Build + working-directory: programs/anchor-vrf-parser + run: pnpm build + + - name: Anchor Test + working-directory: programs/anchor-vrf-parser + run: anchor test + + feedParserTest: + name: "Anchor Feed Parser Tests" + runs-on: ubuntu-latest + defaults: + run: + shell: bash + steps: + - uses: actions/checkout@v3 + - name: Setup Workspace + uses: ./.github/actions/setup-workspace + + - name: Cache Build + id: cache-anchor-feed-build + uses: actions/cache@v3 + with: + path: | + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + ./programs/anchor-feed-parser/deploy + ./programs/anchor-feed-parser/target + key: + ${{ runner.os }}-AnchorFeedParser-${{ + hashFiles('./programs/anchor-feed-parser/Cargo.toml', + './programs/anchor-feed-parser/src/**') }} + + - name: Anchor Build + working-directory: programs/anchor-feed-parser + run: pnpm build + + - name: Anchor Test + working-directory: programs/anchor-feed-parser + run: anchor test diff --git a/.github/workflows/solana-js-test.yml b/.github/workflows/solana-js-test.yml index 4966157..8fcc0df 100644 --- a/.github/workflows/solana-js-test.yml +++ b/.github/workflows/solana-js-test.yml @@ -1,4 +1,4 @@ -name: solana-js-test +name: Solana.js Tests on: workflow_dispatch: push: diff --git a/javascript/solana.js/src/index.ts b/javascript/solana.js/src/index.ts index 86d9cae..45c9fdf 100644 --- a/javascript/solana.js/src/index.ts +++ b/javascript/solana.js/src/index.ts @@ -9,9 +9,6 @@ export * from './SwitchboardError'; export * from './SwitchboardEvents'; export * from './SwitchboardNetwork'; export * from './SwitchboardProgram'; -export { - NodeConfig, - SwitchboardTestContextV2, -} from './test/SwitchboardTestContextV2'; +export * from './test'; export * from './TransactionObject'; export * from './utils'; diff --git a/package.json b/package.json index 87bdf7d..9c8e1b8 100644 --- a/package.json +++ b/package.json @@ -2,12 +2,17 @@ "name": "sbv2-solana", "private": true, "scripts": { - "preinstall": "npx only-allow pnpm" + "preinstall": "npx only-allow pnpm", + "build": "pnpm -r build", + "lint": "pnpm -r lint", + "fix": "pnpm -r fix" }, "devDependencies": { "@commitlint/config-conventional": "^17.0.2", "@switchboard-xyz/eslint-config": "latest", - "commitlint": "^17.4.2" + "commitlint": "^17.4.2", + "shelljs": "^0.8.5", + "shx": "^0.3.4" }, "engines": { "node": ">=14.0.0" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c21f45c..a15b9d6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,10 +7,14 @@ importers: '@commitlint/config-conventional': ^17.0.2 '@switchboard-xyz/eslint-config': latest commitlint: ^17.4.2 + shelljs: ^0.8.5 + shx: ^0.3.4 devDependencies: '@commitlint/config-conventional': 17.4.4 '@switchboard-xyz/eslint-config': 0.1.8 commitlint: 17.4.4 + shelljs: 0.8.5 + shx: 0.3.4 javascript/feed-walkthrough: specifiers: diff --git a/programs/anchor-buffer-parser/package.json b/programs/anchor-buffer-parser/package.json index 17cf8e3..51a3713 100644 --- a/programs/anchor-buffer-parser/package.json +++ b/programs/anchor-buffer-parser/package.json @@ -8,7 +8,7 @@ "directory": "programs/anchor-buffer-parser" }, "scripts": { - "build": "echo \"For workspace anchor-buffer-parser, run 'anchor build' from the project root\" && exit 0", + "build": "node ../build.js anchor-buffer-parser 96punQGZDShZGkzsBa3SsfTxfUnwu4XGpzXbhF7NTgcP", "lint": "eslint --ext .js,.json,.ts 'src/**' --fix" }, "dependencies": { diff --git a/programs/anchor-feed-parser/package.json b/programs/anchor-feed-parser/package.json index d695318..8ff8202 100644 --- a/programs/anchor-feed-parser/package.json +++ b/programs/anchor-feed-parser/package.json @@ -8,7 +8,7 @@ "directory": "programs/anchor-feed-parser" }, "scripts": { - "build": "echo \"For workspace anchor-feed-parser, run 'anchor build' from the project root\" && exit 0", + "build": "node ../build.js anchor-feed-parser Fstf3oTcBxHMZFaoBzxk5oSkTh5HaAjxjh6zcgdZpNBb", "lint": "eslint --ext .js,.json,.ts 'src/**' --fix" }, "dependencies": { diff --git a/programs/anchor-history-parser/package.json b/programs/anchor-history-parser/package.json index 84037b3..71cf67d 100644 --- a/programs/anchor-history-parser/package.json +++ b/programs/anchor-history-parser/package.json @@ -8,7 +8,7 @@ "directory": "programs/anchor-history-parser" }, "scripts": { - "build": "echo \"For workspace anchor-history-parser, run 'anchor build' from the project root\" && exit 0", + "build": "node ../build.js anchor-history-parser C7rn1qJkq9FjTwV86RrY5Uih91NgymRVLdJ81rqLNXRS", "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" }, diff --git a/programs/anchor-vrf-parser/package.json b/programs/anchor-vrf-parser/package.json index 1357320..a4ce687 100644 --- a/programs/anchor-vrf-parser/package.json +++ b/programs/anchor-vrf-parser/package.json @@ -19,8 +19,7 @@ "network:create": "sbv2 solana network create --keypair ~/.config/solana/id.json --configFile .switchboard/networks/default.config.json --schemaFile .switchboard/networks/default.json --cluster localnet --force", "network:start": "sbv2 solana network start --keypair ~/.config/solana/id.json --schemaFile .switchboard/networks/default.json --cluster localnet --nodeImage dev-v2-RC_01_05_23_20_01-beta", "network:start:dev": "VERBOSE=1 DEBUG=1 CHAIN=solana CLUSTER=localnet TASK_RUNNER_SOLANA_RPC=https://api.mainnet-beta.solana.com FS_PAYER_SECRET_PATH=~/.config/solana/id.json RPC_URL=http://localhost:8899 ORACLE_KEY=Ei4HcqRQtf6TfwbuRXKRwCtt8PDXhmq9NhYLWpoh23xp ts-node ../../../switchboard-oracle-v2/node/src/apps/oracle", - "build:old": "anchor build && npx anchor-client-gen target/idl/anchor_vrf_parser.json client/generated --program-id $(solana-keygen pubkey target/deploy/anchor_vrf_parser-keypair.json) && npx prettier client/generated --write", - "build": "echo \"For workspace anchor-vrf-parser, run 'anchor build' from the project root\" && exit 0", + "build": "node ../build.js anchor-vrf-parser 4wTeTACfwiXqqvy44bNBB3V2rFjmSTXVoEr4ZAYamJEN", "test": "npm run localnet && npm run network:create && npm run network:start & sleep 60 && anchor test --skip-local-validator", "test:dev": "npm run localnet && npm run network:create && npm run network:start:dev & sleep 15 && anchor test --skip-local-validator" }, diff --git a/programs/build.js b/programs/build.js new file mode 100644 index 0000000..02480e3 --- /dev/null +++ b/programs/build.js @@ -0,0 +1,97 @@ +const path = require("node:path"); +const fs = require("node:fs"); +const shell = require("shelljs"); + +function verifyBinary(binaryName, installationUrl) { + if (!shell.which(binaryName)) { + shell.echo( + `Sorry, this script requires '${binaryName}' to be installed in your $PATH` + ); + shell.echo(`See installation to get started: ${installationUrl}`); + shell.exit(1); + } +} + +function helperText() { + shell.echo( + `node build.js [PACKAGE_NAME] [PUBKEY]\n\nExample:\nnode build.js anchor-buffer-parser 96punQGZDShZGkzsBa3SsfTxfUnwu4XGpzXbhF7NTgcP` + ); +} + +async function main() { + const args = process.argv.slice(2); + if (args.length < 2) { + helperText(); + throw new Error(`Incorrect number of arguements provided`); + } + const packageName = args[0]; + const programName = packageName.replaceAll("-", "_"); + + const pubkey = args[1]; + if (pubkey.length === 0) { + helperText(); + throw new Error(`Failed to provide the program pubkey`); + } + + const skipBuild = args.includes("--skipBuild"); + + verifyBinary( + "solana", + "https://docs.solana.com/cli/install-solana-cli-tools" + ); + verifyBinary( + "anchor", + "https://book.anchor-lang.com/getting_started/installation.html" + ); + + // check if its a valid package name + const packagePath = path.join(__dirname, packageName); + if (!fs.existsSync(packagePath)) { + throw new Error(`Failed to find directory for ${packageName}`); + } + + // check if directory has an existing program ID keypair + const keypairDir = path.join(packagePath, "target", "deploy"); + const keypairPath = path.join(keypairDir, `${programName}-keypair.json`); + if (!fs.existsSync(keypairPath)) { + if (!fs.existsSync(keypairDir)) { + fs.mkdirSync(keypairDir, { recursive: true }); + } + shell.exec( + `solana-keygen new -s --no-bip39-passphrase --outfile ${keypairPath}` + ); + } + + const programId = shell + .exec(`solana-keygen pubkey ${keypairPath}`) + .toString() + .trim(); + + // update the program ID + const anchorTomlPath = path.join(packagePath, "Anchor.toml"); + if (!fs.existsSync(anchorTomlPath)) { + throw new Error(`Package directory has no Anchor.toml file`); + } + + const libRsPath = path.join(packagePath, "src", "lib.rs"); + if (!fs.existsSync(libRsPath)) { + throw new Error(`Package directory has no src/lib.rs file`); + } + + shell.sed("-i", pubkey, programId, [anchorTomlPath, libRsPath]); + + if (!skipBuild) { + const currentDirectory = shell.pwd(); + try { + shell.cd(packagePath); + shell.exec(`anchor build`); + } catch (error) { + console.error(`Anchor build failed: ${error}`); + } + shell.cd(currentDirectory); + } +} + +main() + .then() + .catch((err) => console.error(err)); diff --git a/programs/native-feed-parser/package.json b/programs/native-feed-parser/package.json index 136ce3d..a42ac39 100644 --- a/programs/native-feed-parser/package.json +++ b/programs/native-feed-parser/package.json @@ -8,7 +8,6 @@ "directory": "programs/native-feed-parser" }, "scripts": { - "build": "echo \"For workspace native-feed-parser, run 'anchor build' from the project root\" && exit 0", "build:bpf": "cargo build-bpf --manifest-path=Cargo.toml", "deploy": "solana program deploy target/deploy/native_feed_parser.so", "test": "echo \"For workspace native-feed-parser, use the anchor:test script\" && exit 0"