diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7b931ea..90f6adc 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -80,7 +80,6 @@ jobs: uses: ./.github/actions/setup with: pnpm: true - solana: true - name: Test Client JS run: make test-js diff --git a/.github/workflows/publish-js-client.yml b/.github/workflows/publish-js-client.yml index 0123d54..fa17f0c 100644 --- a/.github/workflows/publish-js-client.yml +++ b/.github/workflows/publish-js-client.yml @@ -39,7 +39,6 @@ jobs: uses: ./.github/actions/setup with: pnpm: true - solana: true - name: Format run: make format-js diff --git a/Makefile b/Makefile index 6c29c6c..fea5818 100644 --- a/Makefile +++ b/Makefile @@ -36,6 +36,4 @@ lint-js: cd ./clients/js && pnpm install && pnpm lint test-js: - ./scripts/restart-test-validator.sh cd ./clients/js && pnpm install && pnpm build && pnpm test - ./scripts/stop-test-validator.sh diff --git a/README.md b/README.md index a23d0a1..fc1d100 100644 --- a/README.md +++ b/README.md @@ -29,17 +29,3 @@ The following clients are available for the System program. You may use the foll - [JS client](./clients/js) - [Rust client](./clients/rust) - -## Starting and stopping the local validator - -The following script is available to start or restart your local validator. - -```sh -./scripts/restart-test-validator.sh -``` - -Finally, you may stop the local validator using the following command. - -```sh -./scripts/stop-test-validator.sh -``` diff --git a/clients/js/package.json b/clients/js/package.json index 8cffbf3..64da2f1 100644 --- a/clients/js/package.json +++ b/clients/js/package.json @@ -48,7 +48,7 @@ }, "devDependencies": { "@solana/eslint-config-solana": "^6.0.0", - "@solana/kit-plugin-rpc": "^0.10.0", + "@solana/kit-plugin-litesvm": "^0.10.0", "@solana/kit-plugin-signer": "^0.10.0", "@solana/kit": "^6.4.0", "@types/node": "^24", diff --git a/clients/js/pnpm-lock.yaml b/clients/js/pnpm-lock.yaml index 5d74fca..73beb06 100644 --- a/clients/js/pnpm-lock.yaml +++ b/clients/js/pnpm-lock.yaml @@ -14,9 +14,9 @@ importers: '@solana/kit': specifier: ^6.4.0 version: 6.8.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/kit-plugin-rpc': + '@solana/kit-plugin-litesvm': specifier: ^0.10.0 - version: 0.10.0(@solana/kit@6.8.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)) + version: 0.10.0(@solana/kit@6.8.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3))(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) '@solana/kit-plugin-signer': specifier: ^0.10.0 version: 0.10.0(@solana/kit@6.8.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)) @@ -951,6 +951,16 @@ packages: '@sinonjs/fake-timers@13.0.5': resolution: {integrity: sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==} + '@solana-program/system@0.12.0': + resolution: {integrity: sha512-ZnAAWeGVMWNtJhw3GdifI2HnhZ0A0H0qs8tBkcFvxp/8wIavvO+GOM4Jd0N22u2+Lni2zcwvcrxrsxj6Mjphng==} + peerDependencies: + '@solana/kit': ^6.1.0 + + '@solana-program/token@0.12.0': + resolution: {integrity: sha512-hnidRNuFhmqUdW5aWkKTJ+cdzuotVMNwLsTyAk0Nd8VjLDld+vQC0fugHWqm5GPrvYe0hCNAhtpJcZVnNp7rOA==} + peerDependencies: + '@solana/kit': ^6.1.0 + '@solana/accounts@6.8.0': resolution: {integrity: sha512-rXjFYVopaEw1H2PTBQbRjKr+0i4EFuBEhRT5E0dI4cMaabSb4KKypC2gaf47+6cjU3hMlM1AcsyIs72/MqAVBw==} engines: {node: '>=20.18.0'} @@ -1103,8 +1113,8 @@ packages: peerDependencies: '@solana/kit': ^6.8.0 - '@solana/kit-plugin-rpc@0.10.0': - resolution: {integrity: sha512-UWKCcardpRHbj1G1S5UVPbZCP6LCqEwVX784C0JSeaWSKfeK6G81guiW2oEt8ETcryQFiZLBpwypqgfBdYGliQ==} + '@solana/kit-plugin-litesvm@0.10.0': + resolution: {integrity: sha512-ks/sbFyYJOpa4BrdzEpp2karA66N4b1DFnWol3bui/UzJm+YJZ65xnOyeX9U8PC8uF/TPVkgf6oYvsxyLqrxIw==} peerDependencies: '@solana/kit': ^6.8.0 @@ -2517,6 +2527,46 @@ packages: linkify-it@5.0.0: resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==} + litesvm-darwin-arm64@1.0.0: + resolution: {integrity: sha512-Fl1i0G+DbsMh4M0nLtFvJcbYcxVZyYOnJhvLTxzFy26CN5dtOHRTWcHTkQZpfEwdIQxCJAvjsGIHAg4K/ecycQ==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [darwin] + + litesvm-darwin-x64@1.0.0: + resolution: {integrity: sha512-4gSTuYdOCZ0SpjbGRhZ6g8ua8oSJtMgHwz7qpjTPvXw5Zc1K2bdWDlV0FNwg+NSTTQhCn7PzmpFKip2lI/CU3w==} + engines: {node: '>= 20'} + cpu: [x64] + os: [darwin] + + litesvm-linux-arm64-gnu@1.0.0: + resolution: {integrity: sha512-i/NdIvl/D3AJE2PbvYOqORKAe5EYpKO6hlgqKEukzWDQd/yx7hmevg/yEI5rJuI0BfTDPZzRuK4Y5wMKdKu42A==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [linux] + + litesvm-linux-arm64-musl@1.0.0: + resolution: {integrity: sha512-suv1yKYH4oBcR9dIf4JdoMOjdDPyi4QHsO6dKB7Kw/0/tGxnWy/ZcZCMqE283exEyGc64bZXqFTZQQcZxqJrRw==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [linux] + + litesvm-linux-x64-gnu@1.0.0: + resolution: {integrity: sha512-mM+0lSof8Kb45EXUOqM6E+uVNEZgfOn7Vy0PgEgHI9igDhoxID7S4Z44AAcw5k0hzfPT7qtHGH/uOeIFz6w5fw==} + engines: {node: '>= 20'} + cpu: [x64] + os: [linux] + + litesvm-linux-x64-musl@1.0.0: + resolution: {integrity: sha512-xBuFg4PYicqrkthgEgX7GkY2XftqwwBhqZoxEjMjLT9XiRAu82xZJsZTQ0yC749+phXeWT7fjp3W6uVEKvDjAQ==} + engines: {node: '>= 20'} + cpu: [x64] + os: [linux] + + litesvm@1.0.0: + resolution: {integrity: sha512-+uM5Uqut++IKNoG4rw2QzMNspZhqqqRXZ5XDPxb68kJMBrOdvIJX9Ie7IAHTD26qdX074FqMDqlOqlJR9H3xIw==} + engines: {node: '>= 20'} + load-tsconfig@0.2.5: resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -4068,6 +4118,15 @@ snapshots: dependencies: '@sinonjs/commons': 3.0.1 + '@solana-program/system@0.12.0(@solana/kit@6.8.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3))': + dependencies: + '@solana/kit': 6.8.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) + + '@solana-program/token@0.12.0(@solana/kit@6.8.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3))': + dependencies: + '@solana-program/system': 0.12.0(@solana/kit@6.8.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)) + '@solana/kit': 6.8.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) + '@solana/accounts@6.8.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': dependencies: '@solana/addresses': 6.8.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) @@ -4209,10 +4268,16 @@ snapshots: dependencies: '@solana/kit': 6.8.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/kit-plugin-rpc@0.10.0(@solana/kit@6.8.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3))': + '@solana/kit-plugin-litesvm@0.10.0(@solana/kit@6.8.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3))(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)': dependencies: '@solana/kit': 6.8.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) '@solana/kit-plugin-instruction-plan': 0.10.0(@solana/kit@6.8.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)) + litesvm: 1.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) + transitivePeerDependencies: + - bufferutil + - fastestsmallesttextencoderdecoder + - typescript + - utf-8-validate '@solana/kit-plugin-signer@0.10.0(@solana/kit@6.8.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3))': dependencies: @@ -5987,6 +6052,42 @@ snapshots: dependencies: uc.micro: 2.1.0 + litesvm-darwin-arm64@1.0.0: + optional: true + + litesvm-darwin-x64@1.0.0: + optional: true + + litesvm-linux-arm64-gnu@1.0.0: + optional: true + + litesvm-linux-arm64-musl@1.0.0: + optional: true + + litesvm-linux-x64-gnu@1.0.0: + optional: true + + litesvm-linux-x64-musl@1.0.0: + optional: true + + litesvm@1.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3): + dependencies: + '@solana-program/system': 0.12.0(@solana/kit@6.8.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)) + '@solana-program/token': 0.12.0(@solana/kit@6.8.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)) + '@solana/kit': 6.8.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) + optionalDependencies: + litesvm-darwin-arm64: 1.0.0 + litesvm-darwin-x64: 1.0.0 + litesvm-linux-arm64-gnu: 1.0.0 + litesvm-linux-arm64-musl: 1.0.0 + litesvm-linux-x64-gnu: 1.0.0 + litesvm-linux-x64-musl: 1.0.0 + transitivePeerDependencies: + - bufferutil + - fastestsmallesttextencoderdecoder + - typescript + - utf-8-validate + load-tsconfig@0.2.5: {} locate-path@5.0.0: diff --git a/clients/js/test/_setup.ts b/clients/js/test/_setup.ts index 6871ebb..56cb3ca 100644 --- a/clients/js/test/_setup.ts +++ b/clients/js/test/_setup.ts @@ -7,7 +7,7 @@ import { lamports, sequentialInstructionPlan, } from '@solana/kit'; -import { solanaLocalRpc } from '@solana/kit-plugin-rpc'; +import { litesvm } from '@solana/kit-plugin-litesvm'; import { airdropSigner, generatedSigner } from '@solana/kit-plugin-signer'; import { SYSTEM_PROGRAM_ADDRESS, @@ -20,7 +20,7 @@ import { export const createTestClient = () => { return createClient() .use(generatedSigner()) - .use(solanaLocalRpc()) + .use(litesvm()) .use(systemProgram()) .use(airdropSigner(lamports(1_000_000_000n))); }; diff --git a/clients/js/test/advanceNonceAccount.test.ts b/clients/js/test/advanceNonceAccount.test.ts index b141991..4941731 100644 --- a/clients/js/test/advanceNonceAccount.test.ts +++ b/clients/js/test/advanceNonceAccount.test.ts @@ -12,6 +12,12 @@ it('advances the nonce account', async () => { await client.sendTransaction(await getCreateNonceInstructionPlan(client, nonce, authority)); const originalNonceAccount = await client.system.accounts.nonce.fetch(nonce.address); + // Expire the blockhash so the nonce's stored blockhash is no longer in the + // RecentBlockhashes sysvar. On a live cluster this happens naturally between + // blocks; under LiteSVM we have to trigger it explicitly, otherwise the + // System Program returns NonceBlockhashNotExpired (error 7). + client.svm.expireBlockhash(); + // When the authority advances the nonce account. await client.system.instructions .advanceNonceAccount({ nonceAccount: nonce.address, nonceAuthority: authority }) diff --git a/scripts/restart-test-validator.sh b/scripts/restart-test-validator.sh deleted file mode 100755 index 062ab9d..0000000 --- a/scripts/restart-test-validator.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env bash - -PORT=8899 -LOG_FILE="./test-ledger/validator.log" - -PID=$(lsof -t -i:$PORT) - -if [ -n "$PID" ]; then - echo "Detected test validator running on PID $PID. Restarting..." - kill "$PID" - sleep 1 -fi - -echo "Starting Solana test validator..." -solana-test-validator > /dev/null 2>&1 & -VALIDATOR_PID=$! - -# Wait for test validator to move past slot 0. -echo -n "Waiting for validator to stabilize" -for i in {1..8}; do - if ! kill -0 "$VALIDATOR_PID" 2>/dev/null; then - echo -e "\nTest validator exited early." - exit 1 - fi - - SLOT=$(solana slot -ul 2>/dev/null) - if [[ "$SLOT" =~ ^[0-9]+$ ]] && [ "$SLOT" -gt 0 ]; then - echo -e "\nTest validator is ready. Slot: $SLOT" - exit 0 - fi - - echo -n "." - sleep 1 -done - -echo -e "\nTimed out waiting for test validator to stabilize." -exit 1 diff --git a/scripts/stop-test-validator.sh b/scripts/stop-test-validator.sh deleted file mode 100755 index 2859a14..0000000 --- a/scripts/stop-test-validator.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env bash - -if lsof -t -i:8899 > /dev/null; then - echo "Stopping test validator..." - pkill -f solana-test-validator - sleep 1 - echo "Test validator terminated." -else - echo "Test validator is not running." -fi