├── .github ├── actions │ └── setup │ │ └── action.yml └── workflows │ ├── main.yml │ ├── publish-js-client.yml │ └── publish-rust-client.yml ├── .gitignore ├── .prettierrc ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── Makefile ├── README.md ├── clients ├── js │ ├── .eslintrc.cjs │ ├── .gitignore │ ├── .prettierrc.json │ ├── README.md │ ├── package.json │ ├── pnpm-lock.yaml │ ├── src │ │ ├── generated │ │ │ ├── accounts │ │ │ │ ├── index.ts │ │ │ │ └── nonce.ts │ │ │ ├── errors │ │ │ │ ├── index.ts │ │ │ │ └── system.ts │ │ │ ├── index.ts │ │ │ ├── instructions │ │ │ │ ├── advanceNonceAccount.ts │ │ │ │ ├── allocate.ts │ │ │ │ ├── allocateWithSeed.ts │ │ │ │ ├── assign.ts │ │ │ │ ├── assignWithSeed.ts │ │ │ │ ├── authorizeNonceAccount.ts │ │ │ │ ├── createAccount.ts │ │ │ │ ├── createAccountWithSeed.ts │ │ │ │ ├── index.ts │ │ │ │ ├── initializeNonceAccount.ts │ │ │ │ ├── transferSol.ts │ │ │ │ ├── transferSolWithSeed.ts │ │ │ │ ├── upgradeNonceAccount.ts │ │ │ │ └── withdrawNonceAccount.ts │ │ │ ├── programs │ │ │ │ ├── index.ts │ │ │ │ └── system.ts │ │ │ ├── shared │ │ │ │ └── index.ts │ │ │ └── types │ │ │ │ ├── index.ts │ │ │ │ ├── nonceState.ts │ │ │ │ └── nonceVersion.ts │ │ └── index.ts │ ├── test │ │ ├── _setup.ts │ │ ├── advanceNonceAccount.test.ts │ │ ├── createAccount.test.ts │ │ ├── initializeNonceAccount.test.ts │ │ └── transferSol.test.ts │ ├── tsconfig.declarations.json │ ├── tsconfig.json │ ├── tsup.config.ts │ └── typedoc.json └── rust │ ├── Cargo.toml │ ├── README.md │ └── src │ ├── generated │ ├── accounts │ │ ├── mod.rs │ │ └── nonce.rs │ ├── errors │ │ ├── mod.rs │ │ └── system.rs │ ├── instructions │ │ ├── advance_nonce_account.rs │ │ ├── allocate.rs │ │ ├── allocate_with_seed.rs │ │ ├── assign.rs │ │ ├── assign_with_seed.rs │ │ ├── authorize_nonce_account.rs │ │ ├── create_account.rs │ │ ├── create_account_with_seed.rs │ │ ├── initialize_nonce_account.rs │ │ ├── mod.rs │ │ ├── transfer_sol.rs │ │ ├── transfer_sol_with_seed.rs │ │ ├── upgrade_nonce_account.rs │ │ └── withdraw_nonce_account.rs │ ├── mod.rs │ ├── programs.rs │ ├── shared.rs │ └── types │ │ ├── mod.rs │ │ ├── nonce_state.rs │ │ └── nonce_version.rs │ └── lib.rs ├── codama.mjs ├── interface ├── Cargo.toml ├── README.md └── src │ ├── error.rs │ ├── instruction.rs │ ├── lib.rs │ └── wasm.rs ├── package.json ├── pnpm-lock.yaml ├── program └── idl.json ├── rust-toolchain.toml ├── rustfmt.toml ├── scripts ├── publish-js.sh ├── publish-rust.sh ├── restart-test-validator.sh └── stop-test-validator.sh └── vars.env /.github/actions/setup/action.yml: -------------------------------------------------------------------------------- 1 | name: Setup environment 2 | 3 | inputs: 4 | cargo-cache-key: 5 | description: The key to cache cargo dependencies. Skips cargo caching if not provided. 6 | required: false 7 | cargo-cache-fallback-key: 8 | description: The fallback key to use when caching cargo dependencies. Default to not using a fallback key. 9 | required: false 10 | cargo-cache-local-key: 11 | description: The key to cache local cargo dependencies. Skips local cargo caching if not provided. 12 | required: false 13 | pnpm: 14 | description: Install pnpm if `true`. Defaults to `false`. 15 | required: false 16 | solana: 17 | description: Install Solana if `true`. Defaults to `false`. 18 | required: false 19 | toolchain: 20 | description: Rust toolchain to install. Comma-separated string of [`build`, `format`, `lint`, `test`]. 21 | required: false 22 | 23 | runs: 24 | using: 'composite' 25 | steps: 26 | - name: Set Environment Variables 27 | shell: bash 28 | run: | 29 | source ./vars.env 30 | echo "RUST_TOOLCHAIN_NIGHTLY=$RUST_TOOLCHAIN_NIGHTLY" >> "$GITHUB_ENV" 31 | echo "SOLANA_CLI_VERSION=$SOLANA_CLI_VERSION" >> "$GITHUB_ENV" 32 | 33 | - name: Setup pnpm 34 | if: ${{ inputs.pnpm == 'true' }} 35 | uses: pnpm/action-setup@v3 36 | 37 | - name: Setup Node.js 38 | if: ${{ inputs.pnpm == 'true' }} 39 | uses: actions/setup-node@v4 40 | with: 41 | node-version: 20 42 | cache: 'pnpm' 43 | 44 | - name: Install Dependencies 45 | if: ${{ inputs.pnpm == 'true' }} 46 | run: pnpm install --frozen-lockfile 47 | shell: bash 48 | 49 | - name: Install Rust 'build' Toolchain 50 | if: ${{ contains(inputs.toolchain, 'build') }} 51 | uses: dtolnay/rust-toolchain@master 52 | with: 53 | toolchain: ${{ env.RUST_TOOLCHAIN_NIGHTLY }} 54 | 55 | - name: Install Rust 'format' Toolchain 56 | if: ${{ contains(inputs.toolchain, 'format') }} 57 | uses: dtolnay/rust-toolchain@master 58 | with: 59 | toolchain: ${{ env.RUST_TOOLCHAIN_NIGHTLY }} 60 | components: rustfmt 61 | 62 | - name: Install Rust 'lint' Toolchain 63 | if: ${{ contains(inputs.toolchain, 'lint') }} 64 | uses: dtolnay/rust-toolchain@master 65 | with: 66 | toolchain: ${{ env.RUST_TOOLCHAIN_NIGHTLY }} 67 | components: clippy 68 | 69 | - name: Install Rust 'test' Toolchain 70 | if: ${{ contains(inputs.toolchain, 'test') }} 71 | uses: dtolnay/rust-toolchain@master 72 | with: 73 | toolchain: ${{ env.RUST_TOOLCHAIN_NIGHTLY }} 74 | 75 | - name: Install Solana 76 | if: ${{ inputs.solana == 'true' }} 77 | uses: solana-program/actions/install-solana@v1 78 | with: 79 | version: ${{ env.SOLANA_CLI_VERSION }} 80 | cache: true 81 | 82 | - name: Install 'cargo-hack' 83 | if: ${{ contains(inputs.toolchain, 'lint') }} 84 | shell: bash 85 | run: cargo install cargo-hack 86 | 87 | - name: Cache Cargo Dependencies 88 | if: ${{ inputs.cargo-cache-key && !inputs.cargo-cache-fallback-key }} 89 | uses: actions/cache@v4 90 | with: 91 | path: | 92 | ~/.cargo/bin/ 93 | ~/.cargo/registry/index/ 94 | ~/.cargo/registry/cache/ 95 | ~/.cargo/git/db/ 96 | target/ 97 | key: ${{ runner.os }}-${{ inputs.cargo-cache-key }}-${{ hashFiles('**/Cargo.lock') }} 98 | restore-keys: ${{ runner.os }}-${{ inputs.cargo-cache-key }} 99 | 100 | - name: Cache Cargo Dependencies With Fallback 101 | if: ${{ inputs.cargo-cache-key && inputs.cargo-cache-fallback-key }} 102 | uses: actions/cache@v4 103 | with: 104 | path: | 105 | ~/.cargo/bin/ 106 | ~/.cargo/registry/index/ 107 | ~/.cargo/registry/cache/ 108 | ~/.cargo/git/db/ 109 | target/ 110 | key: ${{ runner.os }}-${{ inputs.cargo-cache-key }}-${{ hashFiles('**/Cargo.lock') }} 111 | restore-keys: | 112 | ${{ runner.os }}-${{ inputs.cargo-cache-key }} 113 | ${{ runner.os }}-${{ inputs.cargo-cache-fallback-key }}-${{ hashFiles('**/Cargo.lock') }} 114 | ${{ runner.os }}-${{ inputs.cargo-cache-fallback-key }} 115 | 116 | - name: Cache Local Cargo Dependencies 117 | if: ${{ inputs.cargo-cache-local-key }} 118 | uses: actions/cache@v4 119 | with: 120 | path: | 121 | .cargo/bin/ 122 | .cargo/registry/index/ 123 | .cargo/registry/cache/ 124 | .cargo/git/db/ 125 | key: ${{ runner.os }}-${{ inputs.cargo-cache-local-key }}-${{ hashFiles('**/Cargo.lock') }} 126 | restore-keys: ${{ runner.os }}-${{ inputs.cargo-cache-local-key }} 127 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Main 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | pull_request: 7 | 8 | jobs: 9 | format_and_lint_client_js: 10 | name: Format & Lint Client JS 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Git Checkout 14 | uses: actions/checkout@v4 15 | 16 | - name: Setup Environment 17 | uses: ./.github/actions/setup 18 | with: 19 | pnpm: true 20 | 21 | - name: Format Client JS 22 | run: make format-js 23 | 24 | - name: Lint Client JS 25 | run: make lint-js 26 | 27 | format_and_lint_client_rust: 28 | name: Format & Lint Client Rust 29 | runs-on: ubuntu-latest 30 | steps: 31 | - name: Git Checkout 32 | uses: actions/checkout@v4 33 | 34 | - name: Setup Environment 35 | uses: ./.github/actions/setup 36 | with: 37 | toolchain: format, lint 38 | 39 | - name: Format 40 | run: make format-clients-rust 41 | 42 | - name: Lint / Clippy 43 | run: make clippy-clients-rust 44 | 45 | - name: Lint / Docs 46 | run: make lint-docs-clients-rust 47 | 48 | - name: Lint / Features 49 | run: make lint-features-clients-rust 50 | 51 | format_and_lint_interface: 52 | name: Format & Lint Interface 53 | runs-on: ubuntu-latest 54 | steps: 55 | - name: Git Checkout 56 | uses: actions/checkout@v4 57 | 58 | - name: Setup Environment 59 | uses: ./.github/actions/setup 60 | with: 61 | toolchain: format, lint 62 | 63 | - name: Format 64 | run: make format-interface 65 | 66 | - name: Lint / Clippy 67 | run: make clippy-interface 68 | 69 | - name: Lint / Docs 70 | run: make lint-docs-interface 71 | 72 | - name: Lint / Features 73 | run: make lint-features-interface 74 | 75 | wasm_interface: 76 | name: Build Interface in WASM 77 | runs-on: ubuntu-latest 78 | steps: 79 | - name: Git Checkout 80 | uses: actions/checkout@v4 81 | 82 | - name: Setup Environment 83 | uses: ./.github/actions/setup 84 | with: 85 | cargo-cache-key: cargo-wasm-interface 86 | solana: true 87 | 88 | - name: Install wasm-pack 89 | uses: taiki-e/install-action@v2 90 | with: 91 | tool: wasm-pack 92 | 93 | - name: Build Interface with wasm-pack 94 | run: make build-wasm-interface 95 | 96 | test_interface: 97 | name: Test Interface 98 | runs-on: ubuntu-latest 99 | steps: 100 | - name: Git Checkout 101 | uses: actions/checkout@v4 102 | 103 | - name: Setup Environment 104 | uses: ./.github/actions/setup 105 | with: 106 | toolchain: test 107 | cargo-cache-key: cargo-interface 108 | solana: true 109 | 110 | - name: Test Interface 111 | run: make test-interface 112 | 113 | generate_clients: 114 | name: Check Client Generation 115 | runs-on: ubuntu-latest 116 | steps: 117 | - name: Git Checkout 118 | uses: actions/checkout@v4 119 | 120 | - name: Setup Environment 121 | uses: ./.github/actions/setup 122 | with: 123 | pnpm: true 124 | toolchain: format 125 | 126 | - name: Generate Clients 127 | run: pnpm generate:clients 128 | 129 | - name: Check Working Directory 130 | run: | 131 | git status --porcelain 132 | test -z "$(git status --porcelain)" 133 | 134 | test_client_js: 135 | name: Test Client JS 136 | runs-on: ubuntu-latest 137 | steps: 138 | - name: Git Checkout 139 | uses: actions/checkout@v4 140 | 141 | - name: Setup Environment 142 | uses: ./.github/actions/setup 143 | with: 144 | pnpm: true 145 | solana: true 146 | 147 | - name: Test Client JS 148 | run: make test-js 149 | 150 | test_client_rust: 151 | name: Test Client Rust 152 | runs-on: ubuntu-latest 153 | steps: 154 | - name: Git Checkout 155 | uses: actions/checkout@v4 156 | 157 | - name: Setup Environment 158 | uses: ./.github/actions/setup 159 | with: 160 | cargo-cache-key: cargo-rust-client 161 | toolchain: test 162 | solana: true 163 | 164 | - name: Test Client Rust 165 | run: make test-clients-rust 166 | -------------------------------------------------------------------------------- /.github/workflows/publish-js-client.yml: -------------------------------------------------------------------------------- 1 | name: Publish JS Client 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | level: 7 | description: Version level 8 | required: true 9 | default: patch 10 | type: choice 11 | options: 12 | - patch 13 | - minor 14 | - major 15 | - prerelease 16 | - prepatch 17 | - preminor 18 | - premajor 19 | tag: 20 | description: NPM Tag (and preid for pre-releases) 21 | required: true 22 | type: string 23 | default: latest 24 | create_release: 25 | description: Create a GitHub release 26 | required: true 27 | type: boolean 28 | default: true 29 | 30 | jobs: 31 | test_js: 32 | name: Test JS client 33 | runs-on: ubuntu-latest 34 | steps: 35 | - name: Git Checkout 36 | uses: actions/checkout@v4 37 | 38 | - name: Setup Environment 39 | uses: ./.github/actions/setup 40 | with: 41 | solana: true 42 | 43 | - name: Format 44 | run: make format-js 45 | 46 | - name: Lint 47 | run: make lint-js 48 | 49 | - name: Test 50 | run: make test-js 51 | 52 | publish_js: 53 | name: Publish JS client 54 | runs-on: ubuntu-latest 55 | needs: test_js 56 | permissions: 57 | contents: write 58 | steps: 59 | - name: Git Checkout 60 | uses: actions/checkout@v4 61 | 62 | - name: Setup Environment 63 | uses: ./.github/actions/setup 64 | 65 | - name: Ensure NPM_TOKEN variable is set 66 | env: 67 | token: ${{ secrets.NPM_TOKEN }} 68 | if: ${{ env.token == '' }} 69 | run: | 70 | echo "The NPM_TOKEN secret variable is not set" 71 | echo "Go to \"Settings\" -> \"Secrets and variables\" -> \"Actions\" -> \"New repository secret\"." 72 | exit 1 73 | 74 | - name: NPM Authentication 75 | run: pnpm config set '//registry.npmjs.org/:_authToken' "${NODE_AUTH_TOKEN}" 76 | env: 77 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 78 | 79 | - name: Set Git Author 80 | run: | 81 | git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" 82 | git config --global user.name "github-actions[bot]" 83 | 84 | - name: Publish JS Client 85 | id: publish 86 | run: ./scripts/publish-js.sh clients/js ${{ inputs.level }} ${{ inputs.tag }} 87 | 88 | - name: Push Commit and Tag 89 | run: git push origin --follow-tags 90 | 91 | - name: Create GitHub release 92 | if: github.event.inputs.create_release == 'true' 93 | uses: ncipollo/release-action@v1 94 | with: 95 | tag: js@v${{ steps.publish.outputs.new_version }} 96 | -------------------------------------------------------------------------------- /.github/workflows/publish-rust-client.yml: -------------------------------------------------------------------------------- 1 | name: Publish Rust Client 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | level: 7 | description: Level 8 | required: true 9 | default: patch 10 | type: choice 11 | options: 12 | - patch 13 | - minor 14 | - major 15 | - rc 16 | - beta 17 | - alpha 18 | - release 19 | - version 20 | version: 21 | description: Version 22 | required: false 23 | type: string 24 | dry_run: 25 | description: Dry run 26 | required: true 27 | default: true 28 | type: boolean 29 | create_release: 30 | description: Create a GitHub release 31 | required: true 32 | type: boolean 33 | default: true 34 | 35 | jobs: 36 | test_rust: 37 | name: Test Rust client 38 | runs-on: ubuntu-latest 39 | steps: 40 | - name: Git Checkout 41 | uses: actions/checkout@v4 42 | 43 | - name: Setup Environment 44 | uses: ./.github/actions/setup 45 | with: 46 | cargo-cache-key: cargo-rust-client 47 | clippy: true 48 | rustfmt: true 49 | solana: true 50 | 51 | - name: Format 52 | run: make format-clients-rust 53 | 54 | - name: Lint 55 | run: make clippy-clients-rust 56 | 57 | - name: Test 58 | run: make test-clients-rust 59 | 60 | publish_rust: 61 | name: Publish Rust Client 62 | runs-on: ubuntu-latest 63 | needs: test_rust 64 | permissions: 65 | contents: write 66 | steps: 67 | - name: Git Checkout 68 | uses: actions/checkout@v4 69 | 70 | - name: Setup Environment 71 | uses: ./.github/actions/setup 72 | with: 73 | cargo-cache-key: cargo-publish-rust-client 74 | cargo-cache-fallback-key: cargo-rust-client 75 | clippy: true 76 | rustfmt: true 77 | 78 | - name: Install Cargo Release 79 | run: which cargo-release || cargo install cargo-release 80 | 81 | - name: Ensure CARGO_REGISTRY_TOKEN variable is set 82 | env: 83 | token: ${{ secrets.CARGO_REGISTRY_TOKEN }} 84 | if: ${{ env.token == '' }} 85 | run: | 86 | echo "The CARGO_REGISTRY_TOKEN secret variable is not set" 87 | echo "Go to \"Settings\" -> \"Secrets and variables\" -> \"Actions\" -> \"New repository secret\"." 88 | exit 1 89 | 90 | - name: Set Git Author 91 | run: | 92 | git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" 93 | git config --global user.name "github-actions[bot]" 94 | 95 | - name: Publish Rust Client 96 | id: publish 97 | env: 98 | CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} 99 | run: | 100 | if [ "${{ inputs.level }}" == "version" ]; then 101 | LEVEL=${{ inputs.version }} 102 | else 103 | LEVEL=${{ inputs.level }} 104 | fi 105 | 106 | if [ "${{ inputs.dry_run }}" == "true" ]; then 107 | OPTIONS="--dry-run" 108 | else 109 | OPTIONS="" 110 | fi 111 | 112 | ./scripts/publish-rust.sh clients/rust $LEVEL $OPTIONS 113 | 114 | - name: Push Commit and Tag 115 | if: github.event.inputs.dry_run != 'true' 116 | run: git push origin --follow-tags 117 | 118 | - name: Create GitHub release 119 | if: github.event.inputs.create_release == 'true' && github.event.inputs.dry_run != 'true' 120 | uses: ncipollo/release-action@v1 121 | with: 122 | tag: rust@v${{ steps.publish.outputs.new_version }} 123 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .anchor 2 | .cargo 3 | .DS_Store 4 | **/.DS_Store 5 | **/target 6 | **/*.rs.bk 7 | node_modules 8 | test-ledger 9 | dist 10 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": true, 3 | "singleQuote": true, 4 | "trailingComma": "es5", 5 | "useTabs": false, 6 | "tabWidth": 2, 7 | "arrowParens": "always", 8 | "printWidth": 80 9 | } 10 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | resolver = "2" 3 | members = [ 4 | "clients/rust", 5 | "interface", 6 | ] 7 | 8 | [workspace.package] 9 | authors = ["Anza Maintainers "] 10 | repository = "https://github.com/solana-program/system" 11 | homepage = "https://anza.xyz/" 12 | license = "Apache-2.0" 13 | edition = "2021" 14 | 15 | [workspace.dependencies] 16 | solana-account-info = "2.2.1" 17 | solana-cpi = "2.2.1" 18 | solana-decode-error = "2.2.1" 19 | solana-example-mocks = "2.2.1" 20 | solana-frozen-abi = "2.2.1" 21 | solana-frozen-abi-macro = "2.2.1" 22 | solana-instruction = "2.2.1" 23 | solana-logger = "2.2.1" 24 | solana-nonce = "2.2.1" 25 | solana-msg = "2.2.1" 26 | solana-program = { version = "2.2.1", default-features = false } 27 | solana-program-entrypoint = "2.2.1" 28 | solana-program-error = "2.2.1" 29 | solana-pubkey = { version = "2.2.1", default-features = false } 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | include vars.env 2 | 3 | nightly = +$(subst ",,${RUST_TOOLCHAIN_NIGHTLY}) 4 | 5 | clippy-%: 6 | cargo $(nightly) clippy --manifest-path $(subst -,/,$*)/Cargo.toml 7 | 8 | format-%: 9 | cargo $(nightly) fmt --check --manifest-path $(subst -,/,$*)/Cargo.toml 10 | 11 | format-%-fix: 12 | cargo $(nightly) fmt --manifest-path $(subst -,/,$*)/Cargo.toml 13 | 14 | features-%: 15 | cargo $(nightly) hack check --feature-powerset --all-targets --manifest-path $(subst -,/,$*)/Cargo.toml 16 | 17 | publish-%: 18 | ./scripts/publish-rust.sh $(subst -,/,$*) 19 | 20 | build-wasm-interface: 21 | wasm-pack build --target nodejs --dev ./interface --features bincode 22 | 23 | lint-docs-%: 24 | RUSTDOCFLAGS="--cfg docsrs -D warnings" cargo $(nightly) doc --all-features --no-deps --manifest-path $(subst -,/,$*)/Cargo.toml 25 | 26 | lint-features-%: 27 | cargo $(nightly) hack check --feature-powerset --all-targets --manifest-path $(subst -,/,$*)/Cargo.toml 28 | 29 | test-%: 30 | cargo $(nightly) test --manifest-path $(subst -,/,$*)/Cargo.toml 31 | 32 | format-js: 33 | cd ./clients/js && pnpm install && pnpm format 34 | 35 | lint-js: 36 | cd ./clients/js && pnpm install && pnpm lint 37 | 38 | test-js: 39 | ./scripts/restart-test-validator.sh 40 | cd ./clients/js && pnpm install && pnpm build && pnpm test 41 | ./scripts/stop-test-validator.sh 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # System 2 | 3 | 4 | 5 | 6 | 7 | 8 | The Solana System program and its generated clients. 9 | 10 | ## Project setup 11 | 12 | The first thing you'll want to do is install NPM dependencies which will allow you to access all the scripts and tools provided by this template. 13 | 14 | ```sh 15 | pnpm install 16 | ``` 17 | 18 | ## Generating clients 19 | 20 | You can generate clients for them using the following command. 21 | 22 | ```sh 23 | pnpm generate:clients 24 | ``` 25 | 26 | ## Managing clients 27 | 28 | The following clients are available for the System program. You may use the following links to learn more about each client. 29 | 30 | - [JS client](./clients/js) 31 | - [Rust client](./clients/rust) 32 | 33 | ## Starting and stopping the local validator 34 | 35 | The following script is available to start your local validator. 36 | 37 | ```sh 38 | pnpm validator:start 39 | ``` 40 | 41 | By default, if a local validator is already running, the script will be skipped. You may use the `validator:restart` script instead to force the validator to restart. 42 | 43 | ```sh 44 | pnpm validator:restart 45 | ``` 46 | 47 | Finally, you may stop the local validator using the following command. 48 | 49 | ```sh 50 | pnpm validator:stop 51 | ``` 52 | -------------------------------------------------------------------------------- /clients/js/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['@solana/eslint-config-solana'], 3 | ignorePatterns: ['.eslintrc.cjs', 'tsup.config.ts', 'env-shim.ts'], 4 | parserOptions: { 5 | project: 'tsconfig.json', 6 | tsconfigRootDir: __dirname, 7 | sourceType: 'module', 8 | }, 9 | rules: { 10 | '@typescript-eslint/ban-types': 'off', 11 | '@typescript-eslint/sort-type-constituents': 'off', 12 | 'prefer-destructuring': 'off', 13 | 'simple-import-sort/imports': 'off', 14 | 'sort-keys-fix/sort-keys-fix': 'off', 15 | 'typescript-sort-keys/interface': 'off', 16 | }, 17 | }; 18 | -------------------------------------------------------------------------------- /clients/js/.gitignore: -------------------------------------------------------------------------------- 1 | .vercel 2 | docs 3 | -------------------------------------------------------------------------------- /clients/js/.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "semi": true, 3 | "singleQuote": true, 4 | "trailingComma": "es5", 5 | "useTabs": false, 6 | "tabWidth": 2, 7 | "arrowParens": "always", 8 | "printWidth": 80 9 | } 10 | -------------------------------------------------------------------------------- /clients/js/README.md: -------------------------------------------------------------------------------- 1 | # JavaScript client 2 | 3 | A generated JavaScript library for the System program. 4 | 5 | ## Getting started 6 | 7 | To build and test your JavaScript client from the root of the repository, you may use the following command. 8 | 9 | ```sh 10 | pnpm clients:js:test 11 | ``` 12 | 13 | This will start a new local validator, if one is not already running, and run the tests for your JavaScript client. 14 | 15 | ## Available client scripts. 16 | 17 | Alternatively, you can go into the client directory and run the tests directly. 18 | 19 | ```sh 20 | # Start the validator. 21 | pnpm validator:restart 22 | 23 | # Go into the client directory and run the tests. 24 | cd clients/js 25 | pnpm install 26 | pnpm build 27 | pnpm test 28 | ``` 29 | 30 | You may also use the following scripts to lint and/or format your JavaScript client. 31 | 32 | ```sh 33 | pnpm lint 34 | pnpm lint:fix 35 | pnpm format 36 | pnpm format:fix 37 | ``` 38 | -------------------------------------------------------------------------------- /clients/js/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@solana-program/system", 3 | "version": "0.7.0", 4 | "description": "JavaScript client for the System program", 5 | "sideEffects": false, 6 | "module": "./dist/src/index.mjs", 7 | "main": "./dist/src/index.js", 8 | "types": "./dist/types/index.d.ts", 9 | "type": "commonjs", 10 | "exports": { 11 | ".": { 12 | "types": "./dist/types/index.d.ts", 13 | "import": "./dist/src/index.mjs", 14 | "require": "./dist/src/index.js" 15 | } 16 | }, 17 | "files": [ 18 | "./dist/src", 19 | "./dist/types" 20 | ], 21 | "scripts": { 22 | "build": "rimraf dist && tsup && tsc -p ./tsconfig.declarations.json", 23 | "build:docs": "typedoc", 24 | "test": "ava", 25 | "lint": "eslint --ext js,ts,tsx src", 26 | "lint:fix": "eslint --fix --ext js,ts,tsx src", 27 | "format": "prettier --check src test", 28 | "format:fix": "prettier --write src test", 29 | "prepublishOnly": "pnpm build" 30 | }, 31 | "publishConfig": { 32 | "access": "public", 33 | "registry": "https://registry.npmjs.org" 34 | }, 35 | "license": "Apache-2.0", 36 | "repository": { 37 | "type": "git", 38 | "url": "git+https://github.com/solana-program/system.git" 39 | }, 40 | "bugs": { 41 | "url": "https://github.com/solana-program/system/issues" 42 | }, 43 | "homepage": "https://github.com/solana-program/system#readme", 44 | "peerDependencies": { 45 | "@solana/kit": "^2.1.0" 46 | }, 47 | "devDependencies": { 48 | "@ava/typescript": "^4.1.0", 49 | "@solana/eslint-config-solana": "^3.0.3", 50 | "@solana/kit": "^2.1.0", 51 | "@types/node": "^20", 52 | "@typescript-eslint/eslint-plugin": "^7.16.1", 53 | "@typescript-eslint/parser": "^7.16.1", 54 | "ava": "^6.1.3", 55 | "eslint": "^8.57.0", 56 | "prettier": "^3.3.3", 57 | "rimraf": "^5.0.5", 58 | "tsup": "^8.1.2", 59 | "typedoc": "^0.25.12", 60 | "typescript": "^5.5.3" 61 | }, 62 | "ava": { 63 | "nodeArguments": [ 64 | "--no-warnings" 65 | ], 66 | "typescript": { 67 | "compile": false, 68 | "rewritePaths": { 69 | "test/": "dist/test/" 70 | } 71 | } 72 | }, 73 | "packageManager": "pnpm@9.1.0" 74 | } 75 | -------------------------------------------------------------------------------- /clients/js/src/generated/accounts/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was AUTOGENERATED using the codama library. 3 | * Please DO NOT EDIT THIS FILE, instead use visitors 4 | * to add features, then rerun codama to update it. 5 | * 6 | * @see https://github.com/codama-idl/codama 7 | */ 8 | 9 | export * from './nonce'; 10 | -------------------------------------------------------------------------------- /clients/js/src/generated/accounts/nonce.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was AUTOGENERATED using the codama library. 3 | * Please DO NOT EDIT THIS FILE, instead use visitors 4 | * to add features, then rerun codama to update it. 5 | * 6 | * @see https://github.com/codama-idl/codama 7 | */ 8 | 9 | import { 10 | assertAccountExists, 11 | assertAccountsExist, 12 | combineCodec, 13 | decodeAccount, 14 | fetchEncodedAccount, 15 | fetchEncodedAccounts, 16 | getAddressDecoder, 17 | getAddressEncoder, 18 | getStructDecoder, 19 | getStructEncoder, 20 | getU64Decoder, 21 | getU64Encoder, 22 | type Account, 23 | type Address, 24 | type Codec, 25 | type Decoder, 26 | type EncodedAccount, 27 | type Encoder, 28 | type FetchAccountConfig, 29 | type FetchAccountsConfig, 30 | type MaybeAccount, 31 | type MaybeEncodedAccount, 32 | } from '@solana/kit'; 33 | import { 34 | getNonceStateDecoder, 35 | getNonceStateEncoder, 36 | getNonceVersionDecoder, 37 | getNonceVersionEncoder, 38 | type NonceState, 39 | type NonceStateArgs, 40 | type NonceVersion, 41 | type NonceVersionArgs, 42 | } from '../types'; 43 | 44 | export type Nonce = { 45 | version: NonceVersion; 46 | state: NonceState; 47 | authority: Address; 48 | blockhash: Address; 49 | lamportsPerSignature: bigint; 50 | }; 51 | 52 | export type NonceArgs = { 53 | version: NonceVersionArgs; 54 | state: NonceStateArgs; 55 | authority: Address; 56 | blockhash: Address; 57 | lamportsPerSignature: number | bigint; 58 | }; 59 | 60 | export function getNonceEncoder(): Encoder { 61 | return getStructEncoder([ 62 | ['version', getNonceVersionEncoder()], 63 | ['state', getNonceStateEncoder()], 64 | ['authority', getAddressEncoder()], 65 | ['blockhash', getAddressEncoder()], 66 | ['lamportsPerSignature', getU64Encoder()], 67 | ]); 68 | } 69 | 70 | export function getNonceDecoder(): Decoder { 71 | return getStructDecoder([ 72 | ['version', getNonceVersionDecoder()], 73 | ['state', getNonceStateDecoder()], 74 | ['authority', getAddressDecoder()], 75 | ['blockhash', getAddressDecoder()], 76 | ['lamportsPerSignature', getU64Decoder()], 77 | ]); 78 | } 79 | 80 | export function getNonceCodec(): Codec { 81 | return combineCodec(getNonceEncoder(), getNonceDecoder()); 82 | } 83 | 84 | export function decodeNonce( 85 | encodedAccount: EncodedAccount 86 | ): Account; 87 | export function decodeNonce( 88 | encodedAccount: MaybeEncodedAccount 89 | ): MaybeAccount; 90 | export function decodeNonce( 91 | encodedAccount: EncodedAccount | MaybeEncodedAccount 92 | ): Account | MaybeAccount { 93 | return decodeAccount( 94 | encodedAccount as MaybeEncodedAccount, 95 | getNonceDecoder() 96 | ); 97 | } 98 | 99 | export async function fetchNonce( 100 | rpc: Parameters[0], 101 | address: Address, 102 | config?: FetchAccountConfig 103 | ): Promise> { 104 | const maybeAccount = await fetchMaybeNonce(rpc, address, config); 105 | assertAccountExists(maybeAccount); 106 | return maybeAccount; 107 | } 108 | 109 | export async function fetchMaybeNonce( 110 | rpc: Parameters[0], 111 | address: Address, 112 | config?: FetchAccountConfig 113 | ): Promise> { 114 | const maybeAccount = await fetchEncodedAccount(rpc, address, config); 115 | return decodeNonce(maybeAccount); 116 | } 117 | 118 | export async function fetchAllNonce( 119 | rpc: Parameters[0], 120 | addresses: Array
, 121 | config?: FetchAccountsConfig 122 | ): Promise[]> { 123 | const maybeAccounts = await fetchAllMaybeNonce(rpc, addresses, config); 124 | assertAccountsExist(maybeAccounts); 125 | return maybeAccounts; 126 | } 127 | 128 | export async function fetchAllMaybeNonce( 129 | rpc: Parameters[0], 130 | addresses: Array
, 131 | config?: FetchAccountsConfig 132 | ): Promise[]> { 133 | const maybeAccounts = await fetchEncodedAccounts(rpc, addresses, config); 134 | return maybeAccounts.map((maybeAccount) => decodeNonce(maybeAccount)); 135 | } 136 | 137 | export function getNonceSize(): number { 138 | return 80; 139 | } 140 | -------------------------------------------------------------------------------- /clients/js/src/generated/errors/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was AUTOGENERATED using the codama library. 3 | * Please DO NOT EDIT THIS FILE, instead use visitors 4 | * to add features, then rerun codama to update it. 5 | * 6 | * @see https://github.com/codama-idl/codama 7 | */ 8 | 9 | export * from './system'; 10 | -------------------------------------------------------------------------------- /clients/js/src/generated/errors/system.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was AUTOGENERATED using the codama library. 3 | * Please DO NOT EDIT THIS FILE, instead use visitors 4 | * to add features, then rerun codama to update it. 5 | * 6 | * @see https://github.com/codama-idl/codama 7 | */ 8 | 9 | import { 10 | isProgramError, 11 | type Address, 12 | type SOLANA_ERROR__INSTRUCTION_ERROR__CUSTOM, 13 | type SolanaError, 14 | } from '@solana/kit'; 15 | import { SYSTEM_PROGRAM_ADDRESS } from '../programs'; 16 | 17 | /** AccountAlreadyInUse: an account with the same address already exists */ 18 | export const SYSTEM_ERROR__ACCOUNT_ALREADY_IN_USE = 0x0; // 0 19 | /** ResultWithNegativeLamports: account does not have enough SOL to perform the operation */ 20 | export const SYSTEM_ERROR__RESULT_WITH_NEGATIVE_LAMPORTS = 0x1; // 1 21 | /** InvalidProgramId: cannot assign account to this program id */ 22 | export const SYSTEM_ERROR__INVALID_PROGRAM_ID = 0x2; // 2 23 | /** InvalidAccountDataLength: cannot allocate account data of this length */ 24 | export const SYSTEM_ERROR__INVALID_ACCOUNT_DATA_LENGTH = 0x3; // 3 25 | /** MaxSeedLengthExceeded: length of requested seed is too long */ 26 | export const SYSTEM_ERROR__MAX_SEED_LENGTH_EXCEEDED = 0x4; // 4 27 | /** AddressWithSeedMismatch: provided address does not match addressed derived from seed */ 28 | export const SYSTEM_ERROR__ADDRESS_WITH_SEED_MISMATCH = 0x5; // 5 29 | /** NonceNoRecentBlockhashes: advancing stored nonce requires a populated RecentBlockhashes sysvar */ 30 | export const SYSTEM_ERROR__NONCE_NO_RECENT_BLOCKHASHES = 0x6; // 6 31 | /** NonceBlockhashNotExpired: stored nonce is still in recent_blockhashes */ 32 | export const SYSTEM_ERROR__NONCE_BLOCKHASH_NOT_EXPIRED = 0x7; // 7 33 | /** NonceUnexpectedBlockhashValue: specified nonce does not match stored nonce */ 34 | export const SYSTEM_ERROR__NONCE_UNEXPECTED_BLOCKHASH_VALUE = 0x8; // 8 35 | 36 | export type SystemError = 37 | | typeof SYSTEM_ERROR__ACCOUNT_ALREADY_IN_USE 38 | | typeof SYSTEM_ERROR__ADDRESS_WITH_SEED_MISMATCH 39 | | typeof SYSTEM_ERROR__INVALID_ACCOUNT_DATA_LENGTH 40 | | typeof SYSTEM_ERROR__INVALID_PROGRAM_ID 41 | | typeof SYSTEM_ERROR__MAX_SEED_LENGTH_EXCEEDED 42 | | typeof SYSTEM_ERROR__NONCE_BLOCKHASH_NOT_EXPIRED 43 | | typeof SYSTEM_ERROR__NONCE_NO_RECENT_BLOCKHASHES 44 | | typeof SYSTEM_ERROR__NONCE_UNEXPECTED_BLOCKHASH_VALUE 45 | | typeof SYSTEM_ERROR__RESULT_WITH_NEGATIVE_LAMPORTS; 46 | 47 | let systemErrorMessages: Record | undefined; 48 | if (process.env.NODE_ENV !== 'production') { 49 | systemErrorMessages = { 50 | [SYSTEM_ERROR__ACCOUNT_ALREADY_IN_USE]: `an account with the same address already exists`, 51 | [SYSTEM_ERROR__ADDRESS_WITH_SEED_MISMATCH]: `provided address does not match addressed derived from seed`, 52 | [SYSTEM_ERROR__INVALID_ACCOUNT_DATA_LENGTH]: `cannot allocate account data of this length`, 53 | [SYSTEM_ERROR__INVALID_PROGRAM_ID]: `cannot assign account to this program id`, 54 | [SYSTEM_ERROR__MAX_SEED_LENGTH_EXCEEDED]: `length of requested seed is too long`, 55 | [SYSTEM_ERROR__NONCE_BLOCKHASH_NOT_EXPIRED]: `stored nonce is still in recent_blockhashes`, 56 | [SYSTEM_ERROR__NONCE_NO_RECENT_BLOCKHASHES]: `advancing stored nonce requires a populated RecentBlockhashes sysvar`, 57 | [SYSTEM_ERROR__NONCE_UNEXPECTED_BLOCKHASH_VALUE]: `specified nonce does not match stored nonce`, 58 | [SYSTEM_ERROR__RESULT_WITH_NEGATIVE_LAMPORTS]: `account does not have enough SOL to perform the operation`, 59 | }; 60 | } 61 | 62 | export function getSystemErrorMessage(code: SystemError): string { 63 | if (process.env.NODE_ENV !== 'production') { 64 | return (systemErrorMessages as Record)[code]; 65 | } 66 | 67 | return 'Error message not available in production bundles.'; 68 | } 69 | 70 | export function isSystemError( 71 | error: unknown, 72 | transactionMessage: { 73 | instructions: Record; 74 | }, 75 | code?: TProgramErrorCode 76 | ): error is SolanaError & 77 | Readonly<{ context: Readonly<{ code: TProgramErrorCode }> }> { 78 | return isProgramError( 79 | error, 80 | transactionMessage, 81 | SYSTEM_PROGRAM_ADDRESS, 82 | code 83 | ); 84 | } 85 | -------------------------------------------------------------------------------- /clients/js/src/generated/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was AUTOGENERATED using the codama library. 3 | * Please DO NOT EDIT THIS FILE, instead use visitors 4 | * to add features, then rerun codama to update it. 5 | * 6 | * @see https://github.com/codama-idl/codama 7 | */ 8 | 9 | export * from './accounts'; 10 | export * from './errors'; 11 | export * from './instructions'; 12 | export * from './programs'; 13 | export * from './types'; 14 | -------------------------------------------------------------------------------- /clients/js/src/generated/instructions/advanceNonceAccount.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was AUTOGENERATED using the codama library. 3 | * Please DO NOT EDIT THIS FILE, instead use visitors 4 | * to add features, then rerun codama to update it. 5 | * 6 | * @see https://github.com/codama-idl/codama 7 | */ 8 | 9 | import { 10 | combineCodec, 11 | getStructDecoder, 12 | getStructEncoder, 13 | getU32Decoder, 14 | getU32Encoder, 15 | transformEncoder, 16 | type Address, 17 | type Codec, 18 | type Decoder, 19 | type Encoder, 20 | type IAccountMeta, 21 | type IAccountSignerMeta, 22 | type IInstruction, 23 | type IInstructionWithAccounts, 24 | type IInstructionWithData, 25 | type ReadonlyAccount, 26 | type ReadonlySignerAccount, 27 | type TransactionSigner, 28 | type WritableAccount, 29 | } from '@solana/kit'; 30 | import { SYSTEM_PROGRAM_ADDRESS } from '../programs'; 31 | import { getAccountMetaFactory, type ResolvedAccount } from '../shared'; 32 | 33 | export const ADVANCE_NONCE_ACCOUNT_DISCRIMINATOR = 4; 34 | 35 | export function getAdvanceNonceAccountDiscriminatorBytes() { 36 | return getU32Encoder().encode(ADVANCE_NONCE_ACCOUNT_DISCRIMINATOR); 37 | } 38 | 39 | export type AdvanceNonceAccountInstruction< 40 | TProgram extends string = typeof SYSTEM_PROGRAM_ADDRESS, 41 | TAccountNonceAccount extends string | IAccountMeta = string, 42 | TAccountRecentBlockhashesSysvar extends 43 | | string 44 | | IAccountMeta = 'SysvarRecentB1ockHashes11111111111111111111', 45 | TAccountNonceAuthority extends string | IAccountMeta = string, 46 | TRemainingAccounts extends readonly IAccountMeta[] = [], 47 | > = IInstruction & 48 | IInstructionWithData & 49 | IInstructionWithAccounts< 50 | [ 51 | TAccountNonceAccount extends string 52 | ? WritableAccount 53 | : TAccountNonceAccount, 54 | TAccountRecentBlockhashesSysvar extends string 55 | ? ReadonlyAccount 56 | : TAccountRecentBlockhashesSysvar, 57 | TAccountNonceAuthority extends string 58 | ? ReadonlySignerAccount & 59 | IAccountSignerMeta 60 | : TAccountNonceAuthority, 61 | ...TRemainingAccounts, 62 | ] 63 | >; 64 | 65 | export type AdvanceNonceAccountInstructionData = { discriminator: number }; 66 | 67 | export type AdvanceNonceAccountInstructionDataArgs = {}; 68 | 69 | export function getAdvanceNonceAccountInstructionDataEncoder(): Encoder { 70 | return transformEncoder( 71 | getStructEncoder([['discriminator', getU32Encoder()]]), 72 | (value) => ({ 73 | ...value, 74 | discriminator: ADVANCE_NONCE_ACCOUNT_DISCRIMINATOR, 75 | }) 76 | ); 77 | } 78 | 79 | export function getAdvanceNonceAccountInstructionDataDecoder(): Decoder { 80 | return getStructDecoder([['discriminator', getU32Decoder()]]); 81 | } 82 | 83 | export function getAdvanceNonceAccountInstructionDataCodec(): Codec< 84 | AdvanceNonceAccountInstructionDataArgs, 85 | AdvanceNonceAccountInstructionData 86 | > { 87 | return combineCodec( 88 | getAdvanceNonceAccountInstructionDataEncoder(), 89 | getAdvanceNonceAccountInstructionDataDecoder() 90 | ); 91 | } 92 | 93 | export type AdvanceNonceAccountInput< 94 | TAccountNonceAccount extends string = string, 95 | TAccountRecentBlockhashesSysvar extends string = string, 96 | TAccountNonceAuthority extends string = string, 97 | > = { 98 | nonceAccount: Address; 99 | recentBlockhashesSysvar?: Address; 100 | nonceAuthority: TransactionSigner; 101 | }; 102 | 103 | export function getAdvanceNonceAccountInstruction< 104 | TAccountNonceAccount extends string, 105 | TAccountRecentBlockhashesSysvar extends string, 106 | TAccountNonceAuthority extends string, 107 | TProgramAddress extends Address = typeof SYSTEM_PROGRAM_ADDRESS, 108 | >( 109 | input: AdvanceNonceAccountInput< 110 | TAccountNonceAccount, 111 | TAccountRecentBlockhashesSysvar, 112 | TAccountNonceAuthority 113 | >, 114 | config?: { programAddress?: TProgramAddress } 115 | ): AdvanceNonceAccountInstruction< 116 | TProgramAddress, 117 | TAccountNonceAccount, 118 | TAccountRecentBlockhashesSysvar, 119 | TAccountNonceAuthority 120 | > { 121 | // Program address. 122 | const programAddress = config?.programAddress ?? SYSTEM_PROGRAM_ADDRESS; 123 | 124 | // Original accounts. 125 | const originalAccounts = { 126 | nonceAccount: { value: input.nonceAccount ?? null, isWritable: true }, 127 | recentBlockhashesSysvar: { 128 | value: input.recentBlockhashesSysvar ?? null, 129 | isWritable: false, 130 | }, 131 | nonceAuthority: { value: input.nonceAuthority ?? null, isWritable: false }, 132 | }; 133 | const accounts = originalAccounts as Record< 134 | keyof typeof originalAccounts, 135 | ResolvedAccount 136 | >; 137 | 138 | // Resolve default values. 139 | if (!accounts.recentBlockhashesSysvar.value) { 140 | accounts.recentBlockhashesSysvar.value = 141 | 'SysvarRecentB1ockHashes11111111111111111111' as Address<'SysvarRecentB1ockHashes11111111111111111111'>; 142 | } 143 | 144 | const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); 145 | const instruction = { 146 | accounts: [ 147 | getAccountMeta(accounts.nonceAccount), 148 | getAccountMeta(accounts.recentBlockhashesSysvar), 149 | getAccountMeta(accounts.nonceAuthority), 150 | ], 151 | programAddress, 152 | data: getAdvanceNonceAccountInstructionDataEncoder().encode({}), 153 | } as AdvanceNonceAccountInstruction< 154 | TProgramAddress, 155 | TAccountNonceAccount, 156 | TAccountRecentBlockhashesSysvar, 157 | TAccountNonceAuthority 158 | >; 159 | 160 | return instruction; 161 | } 162 | 163 | export type ParsedAdvanceNonceAccountInstruction< 164 | TProgram extends string = typeof SYSTEM_PROGRAM_ADDRESS, 165 | TAccountMetas extends readonly IAccountMeta[] = readonly IAccountMeta[], 166 | > = { 167 | programAddress: Address; 168 | accounts: { 169 | nonceAccount: TAccountMetas[0]; 170 | recentBlockhashesSysvar: TAccountMetas[1]; 171 | nonceAuthority: TAccountMetas[2]; 172 | }; 173 | data: AdvanceNonceAccountInstructionData; 174 | }; 175 | 176 | export function parseAdvanceNonceAccountInstruction< 177 | TProgram extends string, 178 | TAccountMetas extends readonly IAccountMeta[], 179 | >( 180 | instruction: IInstruction & 181 | IInstructionWithAccounts & 182 | IInstructionWithData 183 | ): ParsedAdvanceNonceAccountInstruction { 184 | if (instruction.accounts.length < 3) { 185 | // TODO: Coded error. 186 | throw new Error('Not enough accounts'); 187 | } 188 | let accountIndex = 0; 189 | const getNextAccount = () => { 190 | const accountMeta = instruction.accounts![accountIndex]!; 191 | accountIndex += 1; 192 | return accountMeta; 193 | }; 194 | return { 195 | programAddress: instruction.programAddress, 196 | accounts: { 197 | nonceAccount: getNextAccount(), 198 | recentBlockhashesSysvar: getNextAccount(), 199 | nonceAuthority: getNextAccount(), 200 | }, 201 | data: getAdvanceNonceAccountInstructionDataDecoder().decode( 202 | instruction.data 203 | ), 204 | }; 205 | } 206 | -------------------------------------------------------------------------------- /clients/js/src/generated/instructions/allocate.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was AUTOGENERATED using the codama library. 3 | * Please DO NOT EDIT THIS FILE, instead use visitors 4 | * to add features, then rerun codama to update it. 5 | * 6 | * @see https://github.com/codama-idl/codama 7 | */ 8 | 9 | import { 10 | combineCodec, 11 | getStructDecoder, 12 | getStructEncoder, 13 | getU32Decoder, 14 | getU32Encoder, 15 | getU64Decoder, 16 | getU64Encoder, 17 | transformEncoder, 18 | type Address, 19 | type Codec, 20 | type Decoder, 21 | type Encoder, 22 | type IAccountMeta, 23 | type IAccountSignerMeta, 24 | type IInstruction, 25 | type IInstructionWithAccounts, 26 | type IInstructionWithData, 27 | type TransactionSigner, 28 | type WritableSignerAccount, 29 | } from '@solana/kit'; 30 | import { SYSTEM_PROGRAM_ADDRESS } from '../programs'; 31 | import { getAccountMetaFactory, type ResolvedAccount } from '../shared'; 32 | 33 | export const ALLOCATE_DISCRIMINATOR = 8; 34 | 35 | export function getAllocateDiscriminatorBytes() { 36 | return getU32Encoder().encode(ALLOCATE_DISCRIMINATOR); 37 | } 38 | 39 | export type AllocateInstruction< 40 | TProgram extends string = typeof SYSTEM_PROGRAM_ADDRESS, 41 | TAccountNewAccount extends string | IAccountMeta = string, 42 | TRemainingAccounts extends readonly IAccountMeta[] = [], 43 | > = IInstruction & 44 | IInstructionWithData & 45 | IInstructionWithAccounts< 46 | [ 47 | TAccountNewAccount extends string 48 | ? WritableSignerAccount & 49 | IAccountSignerMeta 50 | : TAccountNewAccount, 51 | ...TRemainingAccounts, 52 | ] 53 | >; 54 | 55 | export type AllocateInstructionData = { discriminator: number; space: bigint }; 56 | 57 | export type AllocateInstructionDataArgs = { space: number | bigint }; 58 | 59 | export function getAllocateInstructionDataEncoder(): Encoder { 60 | return transformEncoder( 61 | getStructEncoder([ 62 | ['discriminator', getU32Encoder()], 63 | ['space', getU64Encoder()], 64 | ]), 65 | (value) => ({ ...value, discriminator: ALLOCATE_DISCRIMINATOR }) 66 | ); 67 | } 68 | 69 | export function getAllocateInstructionDataDecoder(): Decoder { 70 | return getStructDecoder([ 71 | ['discriminator', getU32Decoder()], 72 | ['space', getU64Decoder()], 73 | ]); 74 | } 75 | 76 | export function getAllocateInstructionDataCodec(): Codec< 77 | AllocateInstructionDataArgs, 78 | AllocateInstructionData 79 | > { 80 | return combineCodec( 81 | getAllocateInstructionDataEncoder(), 82 | getAllocateInstructionDataDecoder() 83 | ); 84 | } 85 | 86 | export type AllocateInput = { 87 | newAccount: TransactionSigner; 88 | space: AllocateInstructionDataArgs['space']; 89 | }; 90 | 91 | export function getAllocateInstruction< 92 | TAccountNewAccount extends string, 93 | TProgramAddress extends Address = typeof SYSTEM_PROGRAM_ADDRESS, 94 | >( 95 | input: AllocateInput, 96 | config?: { programAddress?: TProgramAddress } 97 | ): AllocateInstruction { 98 | // Program address. 99 | const programAddress = config?.programAddress ?? SYSTEM_PROGRAM_ADDRESS; 100 | 101 | // Original accounts. 102 | const originalAccounts = { 103 | newAccount: { value: input.newAccount ?? null, isWritable: true }, 104 | }; 105 | const accounts = originalAccounts as Record< 106 | keyof typeof originalAccounts, 107 | ResolvedAccount 108 | >; 109 | 110 | // Original args. 111 | const args = { ...input }; 112 | 113 | const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); 114 | const instruction = { 115 | accounts: [getAccountMeta(accounts.newAccount)], 116 | programAddress, 117 | data: getAllocateInstructionDataEncoder().encode( 118 | args as AllocateInstructionDataArgs 119 | ), 120 | } as AllocateInstruction; 121 | 122 | return instruction; 123 | } 124 | 125 | export type ParsedAllocateInstruction< 126 | TProgram extends string = typeof SYSTEM_PROGRAM_ADDRESS, 127 | TAccountMetas extends readonly IAccountMeta[] = readonly IAccountMeta[], 128 | > = { 129 | programAddress: Address; 130 | accounts: { 131 | newAccount: TAccountMetas[0]; 132 | }; 133 | data: AllocateInstructionData; 134 | }; 135 | 136 | export function parseAllocateInstruction< 137 | TProgram extends string, 138 | TAccountMetas extends readonly IAccountMeta[], 139 | >( 140 | instruction: IInstruction & 141 | IInstructionWithAccounts & 142 | IInstructionWithData 143 | ): ParsedAllocateInstruction { 144 | if (instruction.accounts.length < 1) { 145 | // TODO: Coded error. 146 | throw new Error('Not enough accounts'); 147 | } 148 | let accountIndex = 0; 149 | const getNextAccount = () => { 150 | const accountMeta = instruction.accounts![accountIndex]!; 151 | accountIndex += 1; 152 | return accountMeta; 153 | }; 154 | return { 155 | programAddress: instruction.programAddress, 156 | accounts: { 157 | newAccount: getNextAccount(), 158 | }, 159 | data: getAllocateInstructionDataDecoder().decode(instruction.data), 160 | }; 161 | } 162 | -------------------------------------------------------------------------------- /clients/js/src/generated/instructions/allocateWithSeed.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was AUTOGENERATED using the codama library. 3 | * Please DO NOT EDIT THIS FILE, instead use visitors 4 | * to add features, then rerun codama to update it. 5 | * 6 | * @see https://github.com/codama-idl/codama 7 | */ 8 | 9 | import { 10 | addDecoderSizePrefix, 11 | addEncoderSizePrefix, 12 | combineCodec, 13 | getAddressDecoder, 14 | getAddressEncoder, 15 | getStructDecoder, 16 | getStructEncoder, 17 | getU32Decoder, 18 | getU32Encoder, 19 | getU64Decoder, 20 | getU64Encoder, 21 | getUtf8Decoder, 22 | getUtf8Encoder, 23 | transformEncoder, 24 | type Address, 25 | type Codec, 26 | type Decoder, 27 | type Encoder, 28 | type IAccountMeta, 29 | type IAccountSignerMeta, 30 | type IInstruction, 31 | type IInstructionWithAccounts, 32 | type IInstructionWithData, 33 | type ReadonlySignerAccount, 34 | type TransactionSigner, 35 | type WritableAccount, 36 | } from '@solana/kit'; 37 | import { SYSTEM_PROGRAM_ADDRESS } from '../programs'; 38 | import { getAccountMetaFactory, type ResolvedAccount } from '../shared'; 39 | 40 | export const ALLOCATE_WITH_SEED_DISCRIMINATOR = 9; 41 | 42 | export function getAllocateWithSeedDiscriminatorBytes() { 43 | return getU32Encoder().encode(ALLOCATE_WITH_SEED_DISCRIMINATOR); 44 | } 45 | 46 | export type AllocateWithSeedInstruction< 47 | TProgram extends string = typeof SYSTEM_PROGRAM_ADDRESS, 48 | TAccountNewAccount extends string | IAccountMeta = string, 49 | TAccountBaseAccount extends string | IAccountMeta = string, 50 | TRemainingAccounts extends readonly IAccountMeta[] = [], 51 | > = IInstruction & 52 | IInstructionWithData & 53 | IInstructionWithAccounts< 54 | [ 55 | TAccountNewAccount extends string 56 | ? WritableAccount 57 | : TAccountNewAccount, 58 | TAccountBaseAccount extends string 59 | ? ReadonlySignerAccount & 60 | IAccountSignerMeta 61 | : TAccountBaseAccount, 62 | ...TRemainingAccounts, 63 | ] 64 | >; 65 | 66 | export type AllocateWithSeedInstructionData = { 67 | discriminator: number; 68 | base: Address; 69 | seed: string; 70 | space: bigint; 71 | programAddress: Address; 72 | }; 73 | 74 | export type AllocateWithSeedInstructionDataArgs = { 75 | base: Address; 76 | seed: string; 77 | space: number | bigint; 78 | programAddress: Address; 79 | }; 80 | 81 | export function getAllocateWithSeedInstructionDataEncoder(): Encoder { 82 | return transformEncoder( 83 | getStructEncoder([ 84 | ['discriminator', getU32Encoder()], 85 | ['base', getAddressEncoder()], 86 | ['seed', addEncoderSizePrefix(getUtf8Encoder(), getU64Encoder())], 87 | ['space', getU64Encoder()], 88 | ['programAddress', getAddressEncoder()], 89 | ]), 90 | (value) => ({ ...value, discriminator: ALLOCATE_WITH_SEED_DISCRIMINATOR }) 91 | ); 92 | } 93 | 94 | export function getAllocateWithSeedInstructionDataDecoder(): Decoder { 95 | return getStructDecoder([ 96 | ['discriminator', getU32Decoder()], 97 | ['base', getAddressDecoder()], 98 | ['seed', addDecoderSizePrefix(getUtf8Decoder(), getU64Decoder())], 99 | ['space', getU64Decoder()], 100 | ['programAddress', getAddressDecoder()], 101 | ]); 102 | } 103 | 104 | export function getAllocateWithSeedInstructionDataCodec(): Codec< 105 | AllocateWithSeedInstructionDataArgs, 106 | AllocateWithSeedInstructionData 107 | > { 108 | return combineCodec( 109 | getAllocateWithSeedInstructionDataEncoder(), 110 | getAllocateWithSeedInstructionDataDecoder() 111 | ); 112 | } 113 | 114 | export type AllocateWithSeedInput< 115 | TAccountNewAccount extends string = string, 116 | TAccountBaseAccount extends string = string, 117 | > = { 118 | newAccount: Address; 119 | baseAccount: TransactionSigner; 120 | base: AllocateWithSeedInstructionDataArgs['base']; 121 | seed: AllocateWithSeedInstructionDataArgs['seed']; 122 | space: AllocateWithSeedInstructionDataArgs['space']; 123 | programAddress: AllocateWithSeedInstructionDataArgs['programAddress']; 124 | }; 125 | 126 | export function getAllocateWithSeedInstruction< 127 | TAccountNewAccount extends string, 128 | TAccountBaseAccount extends string, 129 | TProgramAddress extends Address = typeof SYSTEM_PROGRAM_ADDRESS, 130 | >( 131 | input: AllocateWithSeedInput, 132 | config?: { programAddress?: TProgramAddress } 133 | ): AllocateWithSeedInstruction< 134 | TProgramAddress, 135 | TAccountNewAccount, 136 | TAccountBaseAccount 137 | > { 138 | // Program address. 139 | const programAddress = config?.programAddress ?? SYSTEM_PROGRAM_ADDRESS; 140 | 141 | // Original accounts. 142 | const originalAccounts = { 143 | newAccount: { value: input.newAccount ?? null, isWritable: true }, 144 | baseAccount: { value: input.baseAccount ?? null, isWritable: false }, 145 | }; 146 | const accounts = originalAccounts as Record< 147 | keyof typeof originalAccounts, 148 | ResolvedAccount 149 | >; 150 | 151 | // Original args. 152 | const args = { ...input }; 153 | 154 | const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); 155 | const instruction = { 156 | accounts: [ 157 | getAccountMeta(accounts.newAccount), 158 | getAccountMeta(accounts.baseAccount), 159 | ], 160 | programAddress, 161 | data: getAllocateWithSeedInstructionDataEncoder().encode( 162 | args as AllocateWithSeedInstructionDataArgs 163 | ), 164 | } as AllocateWithSeedInstruction< 165 | TProgramAddress, 166 | TAccountNewAccount, 167 | TAccountBaseAccount 168 | >; 169 | 170 | return instruction; 171 | } 172 | 173 | export type ParsedAllocateWithSeedInstruction< 174 | TProgram extends string = typeof SYSTEM_PROGRAM_ADDRESS, 175 | TAccountMetas extends readonly IAccountMeta[] = readonly IAccountMeta[], 176 | > = { 177 | programAddress: Address; 178 | accounts: { 179 | newAccount: TAccountMetas[0]; 180 | baseAccount: TAccountMetas[1]; 181 | }; 182 | data: AllocateWithSeedInstructionData; 183 | }; 184 | 185 | export function parseAllocateWithSeedInstruction< 186 | TProgram extends string, 187 | TAccountMetas extends readonly IAccountMeta[], 188 | >( 189 | instruction: IInstruction & 190 | IInstructionWithAccounts & 191 | IInstructionWithData 192 | ): ParsedAllocateWithSeedInstruction { 193 | if (instruction.accounts.length < 2) { 194 | // TODO: Coded error. 195 | throw new Error('Not enough accounts'); 196 | } 197 | let accountIndex = 0; 198 | const getNextAccount = () => { 199 | const accountMeta = instruction.accounts![accountIndex]!; 200 | accountIndex += 1; 201 | return accountMeta; 202 | }; 203 | return { 204 | programAddress: instruction.programAddress, 205 | accounts: { 206 | newAccount: getNextAccount(), 207 | baseAccount: getNextAccount(), 208 | }, 209 | data: getAllocateWithSeedInstructionDataDecoder().decode(instruction.data), 210 | }; 211 | } 212 | -------------------------------------------------------------------------------- /clients/js/src/generated/instructions/assign.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was AUTOGENERATED using the codama library. 3 | * Please DO NOT EDIT THIS FILE, instead use visitors 4 | * to add features, then rerun codama to update it. 5 | * 6 | * @see https://github.com/codama-idl/codama 7 | */ 8 | 9 | import { 10 | combineCodec, 11 | getAddressDecoder, 12 | getAddressEncoder, 13 | getStructDecoder, 14 | getStructEncoder, 15 | getU32Decoder, 16 | getU32Encoder, 17 | transformEncoder, 18 | type Address, 19 | type Codec, 20 | type Decoder, 21 | type Encoder, 22 | type IAccountMeta, 23 | type IAccountSignerMeta, 24 | type IInstruction, 25 | type IInstructionWithAccounts, 26 | type IInstructionWithData, 27 | type TransactionSigner, 28 | type WritableSignerAccount, 29 | } from '@solana/kit'; 30 | import { SYSTEM_PROGRAM_ADDRESS } from '../programs'; 31 | import { getAccountMetaFactory, type ResolvedAccount } from '../shared'; 32 | 33 | export const ASSIGN_DISCRIMINATOR = 1; 34 | 35 | export function getAssignDiscriminatorBytes() { 36 | return getU32Encoder().encode(ASSIGN_DISCRIMINATOR); 37 | } 38 | 39 | export type AssignInstruction< 40 | TProgram extends string = typeof SYSTEM_PROGRAM_ADDRESS, 41 | TAccountAccount extends string | IAccountMeta = string, 42 | TRemainingAccounts extends readonly IAccountMeta[] = [], 43 | > = IInstruction & 44 | IInstructionWithData & 45 | IInstructionWithAccounts< 46 | [ 47 | TAccountAccount extends string 48 | ? WritableSignerAccount & 49 | IAccountSignerMeta 50 | : TAccountAccount, 51 | ...TRemainingAccounts, 52 | ] 53 | >; 54 | 55 | export type AssignInstructionData = { 56 | discriminator: number; 57 | programAddress: Address; 58 | }; 59 | 60 | export type AssignInstructionDataArgs = { programAddress: Address }; 61 | 62 | export function getAssignInstructionDataEncoder(): Encoder { 63 | return transformEncoder( 64 | getStructEncoder([ 65 | ['discriminator', getU32Encoder()], 66 | ['programAddress', getAddressEncoder()], 67 | ]), 68 | (value) => ({ ...value, discriminator: ASSIGN_DISCRIMINATOR }) 69 | ); 70 | } 71 | 72 | export function getAssignInstructionDataDecoder(): Decoder { 73 | return getStructDecoder([ 74 | ['discriminator', getU32Decoder()], 75 | ['programAddress', getAddressDecoder()], 76 | ]); 77 | } 78 | 79 | export function getAssignInstructionDataCodec(): Codec< 80 | AssignInstructionDataArgs, 81 | AssignInstructionData 82 | > { 83 | return combineCodec( 84 | getAssignInstructionDataEncoder(), 85 | getAssignInstructionDataDecoder() 86 | ); 87 | } 88 | 89 | export type AssignInput = { 90 | account: TransactionSigner; 91 | programAddress: AssignInstructionDataArgs['programAddress']; 92 | }; 93 | 94 | export function getAssignInstruction< 95 | TAccountAccount extends string, 96 | TProgramAddress extends Address = typeof SYSTEM_PROGRAM_ADDRESS, 97 | >( 98 | input: AssignInput, 99 | config?: { programAddress?: TProgramAddress } 100 | ): AssignInstruction { 101 | // Program address. 102 | const programAddress = config?.programAddress ?? SYSTEM_PROGRAM_ADDRESS; 103 | 104 | // Original accounts. 105 | const originalAccounts = { 106 | account: { value: input.account ?? null, isWritable: true }, 107 | }; 108 | const accounts = originalAccounts as Record< 109 | keyof typeof originalAccounts, 110 | ResolvedAccount 111 | >; 112 | 113 | // Original args. 114 | const args = { ...input }; 115 | 116 | const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); 117 | const instruction = { 118 | accounts: [getAccountMeta(accounts.account)], 119 | programAddress, 120 | data: getAssignInstructionDataEncoder().encode( 121 | args as AssignInstructionDataArgs 122 | ), 123 | } as AssignInstruction; 124 | 125 | return instruction; 126 | } 127 | 128 | export type ParsedAssignInstruction< 129 | TProgram extends string = typeof SYSTEM_PROGRAM_ADDRESS, 130 | TAccountMetas extends readonly IAccountMeta[] = readonly IAccountMeta[], 131 | > = { 132 | programAddress: Address; 133 | accounts: { 134 | account: TAccountMetas[0]; 135 | }; 136 | data: AssignInstructionData; 137 | }; 138 | 139 | export function parseAssignInstruction< 140 | TProgram extends string, 141 | TAccountMetas extends readonly IAccountMeta[], 142 | >( 143 | instruction: IInstruction & 144 | IInstructionWithAccounts & 145 | IInstructionWithData 146 | ): ParsedAssignInstruction { 147 | if (instruction.accounts.length < 1) { 148 | // TODO: Coded error. 149 | throw new Error('Not enough accounts'); 150 | } 151 | let accountIndex = 0; 152 | const getNextAccount = () => { 153 | const accountMeta = instruction.accounts![accountIndex]!; 154 | accountIndex += 1; 155 | return accountMeta; 156 | }; 157 | return { 158 | programAddress: instruction.programAddress, 159 | accounts: { 160 | account: getNextAccount(), 161 | }, 162 | data: getAssignInstructionDataDecoder().decode(instruction.data), 163 | }; 164 | } 165 | -------------------------------------------------------------------------------- /clients/js/src/generated/instructions/assignWithSeed.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was AUTOGENERATED using the codama library. 3 | * Please DO NOT EDIT THIS FILE, instead use visitors 4 | * to add features, then rerun codama to update it. 5 | * 6 | * @see https://github.com/codama-idl/codama 7 | */ 8 | 9 | import { 10 | addDecoderSizePrefix, 11 | addEncoderSizePrefix, 12 | combineCodec, 13 | getAddressDecoder, 14 | getAddressEncoder, 15 | getStructDecoder, 16 | getStructEncoder, 17 | getU32Decoder, 18 | getU32Encoder, 19 | getU64Decoder, 20 | getU64Encoder, 21 | getUtf8Decoder, 22 | getUtf8Encoder, 23 | transformEncoder, 24 | type Address, 25 | type Codec, 26 | type Decoder, 27 | type Encoder, 28 | type IAccountMeta, 29 | type IAccountSignerMeta, 30 | type IInstruction, 31 | type IInstructionWithAccounts, 32 | type IInstructionWithData, 33 | type ReadonlySignerAccount, 34 | type TransactionSigner, 35 | type WritableAccount, 36 | } from '@solana/kit'; 37 | import { SYSTEM_PROGRAM_ADDRESS } from '../programs'; 38 | import { getAccountMetaFactory, type ResolvedAccount } from '../shared'; 39 | 40 | export const ASSIGN_WITH_SEED_DISCRIMINATOR = 10; 41 | 42 | export function getAssignWithSeedDiscriminatorBytes() { 43 | return getU32Encoder().encode(ASSIGN_WITH_SEED_DISCRIMINATOR); 44 | } 45 | 46 | export type AssignWithSeedInstruction< 47 | TProgram extends string = typeof SYSTEM_PROGRAM_ADDRESS, 48 | TAccountAccount extends string | IAccountMeta = string, 49 | TAccountBaseAccount extends string | IAccountMeta = string, 50 | TRemainingAccounts extends readonly IAccountMeta[] = [], 51 | > = IInstruction & 52 | IInstructionWithData & 53 | IInstructionWithAccounts< 54 | [ 55 | TAccountAccount extends string 56 | ? WritableAccount 57 | : TAccountAccount, 58 | TAccountBaseAccount extends string 59 | ? ReadonlySignerAccount & 60 | IAccountSignerMeta 61 | : TAccountBaseAccount, 62 | ...TRemainingAccounts, 63 | ] 64 | >; 65 | 66 | export type AssignWithSeedInstructionData = { 67 | discriminator: number; 68 | base: Address; 69 | seed: string; 70 | programAddress: Address; 71 | }; 72 | 73 | export type AssignWithSeedInstructionDataArgs = { 74 | base: Address; 75 | seed: string; 76 | programAddress: Address; 77 | }; 78 | 79 | export function getAssignWithSeedInstructionDataEncoder(): Encoder { 80 | return transformEncoder( 81 | getStructEncoder([ 82 | ['discriminator', getU32Encoder()], 83 | ['base', getAddressEncoder()], 84 | ['seed', addEncoderSizePrefix(getUtf8Encoder(), getU64Encoder())], 85 | ['programAddress', getAddressEncoder()], 86 | ]), 87 | (value) => ({ ...value, discriminator: ASSIGN_WITH_SEED_DISCRIMINATOR }) 88 | ); 89 | } 90 | 91 | export function getAssignWithSeedInstructionDataDecoder(): Decoder { 92 | return getStructDecoder([ 93 | ['discriminator', getU32Decoder()], 94 | ['base', getAddressDecoder()], 95 | ['seed', addDecoderSizePrefix(getUtf8Decoder(), getU64Decoder())], 96 | ['programAddress', getAddressDecoder()], 97 | ]); 98 | } 99 | 100 | export function getAssignWithSeedInstructionDataCodec(): Codec< 101 | AssignWithSeedInstructionDataArgs, 102 | AssignWithSeedInstructionData 103 | > { 104 | return combineCodec( 105 | getAssignWithSeedInstructionDataEncoder(), 106 | getAssignWithSeedInstructionDataDecoder() 107 | ); 108 | } 109 | 110 | export type AssignWithSeedInput< 111 | TAccountAccount extends string = string, 112 | TAccountBaseAccount extends string = string, 113 | > = { 114 | account: Address; 115 | baseAccount: TransactionSigner; 116 | base: AssignWithSeedInstructionDataArgs['base']; 117 | seed: AssignWithSeedInstructionDataArgs['seed']; 118 | programAddress: AssignWithSeedInstructionDataArgs['programAddress']; 119 | }; 120 | 121 | export function getAssignWithSeedInstruction< 122 | TAccountAccount extends string, 123 | TAccountBaseAccount extends string, 124 | TProgramAddress extends Address = typeof SYSTEM_PROGRAM_ADDRESS, 125 | >( 126 | input: AssignWithSeedInput, 127 | config?: { programAddress?: TProgramAddress } 128 | ): AssignWithSeedInstruction< 129 | TProgramAddress, 130 | TAccountAccount, 131 | TAccountBaseAccount 132 | > { 133 | // Program address. 134 | const programAddress = config?.programAddress ?? SYSTEM_PROGRAM_ADDRESS; 135 | 136 | // Original accounts. 137 | const originalAccounts = { 138 | account: { value: input.account ?? null, isWritable: true }, 139 | baseAccount: { value: input.baseAccount ?? null, isWritable: false }, 140 | }; 141 | const accounts = originalAccounts as Record< 142 | keyof typeof originalAccounts, 143 | ResolvedAccount 144 | >; 145 | 146 | // Original args. 147 | const args = { ...input }; 148 | 149 | const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); 150 | const instruction = { 151 | accounts: [ 152 | getAccountMeta(accounts.account), 153 | getAccountMeta(accounts.baseAccount), 154 | ], 155 | programAddress, 156 | data: getAssignWithSeedInstructionDataEncoder().encode( 157 | args as AssignWithSeedInstructionDataArgs 158 | ), 159 | } as AssignWithSeedInstruction< 160 | TProgramAddress, 161 | TAccountAccount, 162 | TAccountBaseAccount 163 | >; 164 | 165 | return instruction; 166 | } 167 | 168 | export type ParsedAssignWithSeedInstruction< 169 | TProgram extends string = typeof SYSTEM_PROGRAM_ADDRESS, 170 | TAccountMetas extends readonly IAccountMeta[] = readonly IAccountMeta[], 171 | > = { 172 | programAddress: Address; 173 | accounts: { 174 | account: TAccountMetas[0]; 175 | baseAccount: TAccountMetas[1]; 176 | }; 177 | data: AssignWithSeedInstructionData; 178 | }; 179 | 180 | export function parseAssignWithSeedInstruction< 181 | TProgram extends string, 182 | TAccountMetas extends readonly IAccountMeta[], 183 | >( 184 | instruction: IInstruction & 185 | IInstructionWithAccounts & 186 | IInstructionWithData 187 | ): ParsedAssignWithSeedInstruction { 188 | if (instruction.accounts.length < 2) { 189 | // TODO: Coded error. 190 | throw new Error('Not enough accounts'); 191 | } 192 | let accountIndex = 0; 193 | const getNextAccount = () => { 194 | const accountMeta = instruction.accounts![accountIndex]!; 195 | accountIndex += 1; 196 | return accountMeta; 197 | }; 198 | return { 199 | programAddress: instruction.programAddress, 200 | accounts: { 201 | account: getNextAccount(), 202 | baseAccount: getNextAccount(), 203 | }, 204 | data: getAssignWithSeedInstructionDataDecoder().decode(instruction.data), 205 | }; 206 | } 207 | -------------------------------------------------------------------------------- /clients/js/src/generated/instructions/authorizeNonceAccount.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was AUTOGENERATED using the codama library. 3 | * Please DO NOT EDIT THIS FILE, instead use visitors 4 | * to add features, then rerun codama to update it. 5 | * 6 | * @see https://github.com/codama-idl/codama 7 | */ 8 | 9 | import { 10 | combineCodec, 11 | getAddressDecoder, 12 | getAddressEncoder, 13 | getStructDecoder, 14 | getStructEncoder, 15 | getU32Decoder, 16 | getU32Encoder, 17 | transformEncoder, 18 | type Address, 19 | type Codec, 20 | type Decoder, 21 | type Encoder, 22 | type IAccountMeta, 23 | type IAccountSignerMeta, 24 | type IInstruction, 25 | type IInstructionWithAccounts, 26 | type IInstructionWithData, 27 | type ReadonlySignerAccount, 28 | type TransactionSigner, 29 | type WritableAccount, 30 | } from '@solana/kit'; 31 | import { SYSTEM_PROGRAM_ADDRESS } from '../programs'; 32 | import { getAccountMetaFactory, type ResolvedAccount } from '../shared'; 33 | 34 | export const AUTHORIZE_NONCE_ACCOUNT_DISCRIMINATOR = 7; 35 | 36 | export function getAuthorizeNonceAccountDiscriminatorBytes() { 37 | return getU32Encoder().encode(AUTHORIZE_NONCE_ACCOUNT_DISCRIMINATOR); 38 | } 39 | 40 | export type AuthorizeNonceAccountInstruction< 41 | TProgram extends string = typeof SYSTEM_PROGRAM_ADDRESS, 42 | TAccountNonceAccount extends string | IAccountMeta = string, 43 | TAccountNonceAuthority extends string | IAccountMeta = string, 44 | TRemainingAccounts extends readonly IAccountMeta[] = [], 45 | > = IInstruction & 46 | IInstructionWithData & 47 | IInstructionWithAccounts< 48 | [ 49 | TAccountNonceAccount extends string 50 | ? WritableAccount 51 | : TAccountNonceAccount, 52 | TAccountNonceAuthority extends string 53 | ? ReadonlySignerAccount & 54 | IAccountSignerMeta 55 | : TAccountNonceAuthority, 56 | ...TRemainingAccounts, 57 | ] 58 | >; 59 | 60 | export type AuthorizeNonceAccountInstructionData = { 61 | discriminator: number; 62 | newNonceAuthority: Address; 63 | }; 64 | 65 | export type AuthorizeNonceAccountInstructionDataArgs = { 66 | newNonceAuthority: Address; 67 | }; 68 | 69 | export function getAuthorizeNonceAccountInstructionDataEncoder(): Encoder { 70 | return transformEncoder( 71 | getStructEncoder([ 72 | ['discriminator', getU32Encoder()], 73 | ['newNonceAuthority', getAddressEncoder()], 74 | ]), 75 | (value) => ({ 76 | ...value, 77 | discriminator: AUTHORIZE_NONCE_ACCOUNT_DISCRIMINATOR, 78 | }) 79 | ); 80 | } 81 | 82 | export function getAuthorizeNonceAccountInstructionDataDecoder(): Decoder { 83 | return getStructDecoder([ 84 | ['discriminator', getU32Decoder()], 85 | ['newNonceAuthority', getAddressDecoder()], 86 | ]); 87 | } 88 | 89 | export function getAuthorizeNonceAccountInstructionDataCodec(): Codec< 90 | AuthorizeNonceAccountInstructionDataArgs, 91 | AuthorizeNonceAccountInstructionData 92 | > { 93 | return combineCodec( 94 | getAuthorizeNonceAccountInstructionDataEncoder(), 95 | getAuthorizeNonceAccountInstructionDataDecoder() 96 | ); 97 | } 98 | 99 | export type AuthorizeNonceAccountInput< 100 | TAccountNonceAccount extends string = string, 101 | TAccountNonceAuthority extends string = string, 102 | > = { 103 | nonceAccount: Address; 104 | nonceAuthority: TransactionSigner; 105 | newNonceAuthority: AuthorizeNonceAccountInstructionDataArgs['newNonceAuthority']; 106 | }; 107 | 108 | export function getAuthorizeNonceAccountInstruction< 109 | TAccountNonceAccount extends string, 110 | TAccountNonceAuthority extends string, 111 | TProgramAddress extends Address = typeof SYSTEM_PROGRAM_ADDRESS, 112 | >( 113 | input: AuthorizeNonceAccountInput< 114 | TAccountNonceAccount, 115 | TAccountNonceAuthority 116 | >, 117 | config?: { programAddress?: TProgramAddress } 118 | ): AuthorizeNonceAccountInstruction< 119 | TProgramAddress, 120 | TAccountNonceAccount, 121 | TAccountNonceAuthority 122 | > { 123 | // Program address. 124 | const programAddress = config?.programAddress ?? SYSTEM_PROGRAM_ADDRESS; 125 | 126 | // Original accounts. 127 | const originalAccounts = { 128 | nonceAccount: { value: input.nonceAccount ?? null, isWritable: true }, 129 | nonceAuthority: { value: input.nonceAuthority ?? null, isWritable: false }, 130 | }; 131 | const accounts = originalAccounts as Record< 132 | keyof typeof originalAccounts, 133 | ResolvedAccount 134 | >; 135 | 136 | // Original args. 137 | const args = { ...input }; 138 | 139 | const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); 140 | const instruction = { 141 | accounts: [ 142 | getAccountMeta(accounts.nonceAccount), 143 | getAccountMeta(accounts.nonceAuthority), 144 | ], 145 | programAddress, 146 | data: getAuthorizeNonceAccountInstructionDataEncoder().encode( 147 | args as AuthorizeNonceAccountInstructionDataArgs 148 | ), 149 | } as AuthorizeNonceAccountInstruction< 150 | TProgramAddress, 151 | TAccountNonceAccount, 152 | TAccountNonceAuthority 153 | >; 154 | 155 | return instruction; 156 | } 157 | 158 | export type ParsedAuthorizeNonceAccountInstruction< 159 | TProgram extends string = typeof SYSTEM_PROGRAM_ADDRESS, 160 | TAccountMetas extends readonly IAccountMeta[] = readonly IAccountMeta[], 161 | > = { 162 | programAddress: Address; 163 | accounts: { 164 | nonceAccount: TAccountMetas[0]; 165 | nonceAuthority: TAccountMetas[1]; 166 | }; 167 | data: AuthorizeNonceAccountInstructionData; 168 | }; 169 | 170 | export function parseAuthorizeNonceAccountInstruction< 171 | TProgram extends string, 172 | TAccountMetas extends readonly IAccountMeta[], 173 | >( 174 | instruction: IInstruction & 175 | IInstructionWithAccounts & 176 | IInstructionWithData 177 | ): ParsedAuthorizeNonceAccountInstruction { 178 | if (instruction.accounts.length < 2) { 179 | // TODO: Coded error. 180 | throw new Error('Not enough accounts'); 181 | } 182 | let accountIndex = 0; 183 | const getNextAccount = () => { 184 | const accountMeta = instruction.accounts![accountIndex]!; 185 | accountIndex += 1; 186 | return accountMeta; 187 | }; 188 | return { 189 | programAddress: instruction.programAddress, 190 | accounts: { 191 | nonceAccount: getNextAccount(), 192 | nonceAuthority: getNextAccount(), 193 | }, 194 | data: getAuthorizeNonceAccountInstructionDataDecoder().decode( 195 | instruction.data 196 | ), 197 | }; 198 | } 199 | -------------------------------------------------------------------------------- /clients/js/src/generated/instructions/createAccount.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was AUTOGENERATED using the codama library. 3 | * Please DO NOT EDIT THIS FILE, instead use visitors 4 | * to add features, then rerun codama to update it. 5 | * 6 | * @see https://github.com/codama-idl/codama 7 | */ 8 | 9 | import { 10 | BASE_ACCOUNT_SIZE, 11 | combineCodec, 12 | getAddressDecoder, 13 | getAddressEncoder, 14 | getStructDecoder, 15 | getStructEncoder, 16 | getU32Decoder, 17 | getU32Encoder, 18 | getU64Decoder, 19 | getU64Encoder, 20 | transformEncoder, 21 | type Address, 22 | type Codec, 23 | type Decoder, 24 | type Encoder, 25 | type IAccountMeta, 26 | type IAccountSignerMeta, 27 | type IInstruction, 28 | type IInstructionWithAccounts, 29 | type IInstructionWithData, 30 | type TransactionSigner, 31 | type WritableSignerAccount, 32 | } from '@solana/kit'; 33 | import { SYSTEM_PROGRAM_ADDRESS } from '../programs'; 34 | import { 35 | getAccountMetaFactory, 36 | type IInstructionWithByteDelta, 37 | type ResolvedAccount, 38 | } from '../shared'; 39 | 40 | export const CREATE_ACCOUNT_DISCRIMINATOR = 0; 41 | 42 | export function getCreateAccountDiscriminatorBytes() { 43 | return getU32Encoder().encode(CREATE_ACCOUNT_DISCRIMINATOR); 44 | } 45 | 46 | export type CreateAccountInstruction< 47 | TProgram extends string = typeof SYSTEM_PROGRAM_ADDRESS, 48 | TAccountPayer extends string | IAccountMeta = string, 49 | TAccountNewAccount extends string | IAccountMeta = string, 50 | TRemainingAccounts extends readonly IAccountMeta[] = [], 51 | > = IInstruction & 52 | IInstructionWithData & 53 | IInstructionWithAccounts< 54 | [ 55 | TAccountPayer extends string 56 | ? WritableSignerAccount & 57 | IAccountSignerMeta 58 | : TAccountPayer, 59 | TAccountNewAccount extends string 60 | ? WritableSignerAccount & 61 | IAccountSignerMeta 62 | : TAccountNewAccount, 63 | ...TRemainingAccounts, 64 | ] 65 | >; 66 | 67 | export type CreateAccountInstructionData = { 68 | discriminator: number; 69 | lamports: bigint; 70 | space: bigint; 71 | programAddress: Address; 72 | }; 73 | 74 | export type CreateAccountInstructionDataArgs = { 75 | lamports: number | bigint; 76 | space: number | bigint; 77 | programAddress: Address; 78 | }; 79 | 80 | export function getCreateAccountInstructionDataEncoder(): Encoder { 81 | return transformEncoder( 82 | getStructEncoder([ 83 | ['discriminator', getU32Encoder()], 84 | ['lamports', getU64Encoder()], 85 | ['space', getU64Encoder()], 86 | ['programAddress', getAddressEncoder()], 87 | ]), 88 | (value) => ({ ...value, discriminator: CREATE_ACCOUNT_DISCRIMINATOR }) 89 | ); 90 | } 91 | 92 | export function getCreateAccountInstructionDataDecoder(): Decoder { 93 | return getStructDecoder([ 94 | ['discriminator', getU32Decoder()], 95 | ['lamports', getU64Decoder()], 96 | ['space', getU64Decoder()], 97 | ['programAddress', getAddressDecoder()], 98 | ]); 99 | } 100 | 101 | export function getCreateAccountInstructionDataCodec(): Codec< 102 | CreateAccountInstructionDataArgs, 103 | CreateAccountInstructionData 104 | > { 105 | return combineCodec( 106 | getCreateAccountInstructionDataEncoder(), 107 | getCreateAccountInstructionDataDecoder() 108 | ); 109 | } 110 | 111 | export type CreateAccountInput< 112 | TAccountPayer extends string = string, 113 | TAccountNewAccount extends string = string, 114 | > = { 115 | payer: TransactionSigner; 116 | newAccount: TransactionSigner; 117 | lamports: CreateAccountInstructionDataArgs['lamports']; 118 | space: CreateAccountInstructionDataArgs['space']; 119 | programAddress: CreateAccountInstructionDataArgs['programAddress']; 120 | }; 121 | 122 | export function getCreateAccountInstruction< 123 | TAccountPayer extends string, 124 | TAccountNewAccount extends string, 125 | TProgramAddress extends Address = typeof SYSTEM_PROGRAM_ADDRESS, 126 | >( 127 | input: CreateAccountInput, 128 | config?: { programAddress?: TProgramAddress } 129 | ): CreateAccountInstruction< 130 | TProgramAddress, 131 | TAccountPayer, 132 | TAccountNewAccount 133 | > & 134 | IInstructionWithByteDelta { 135 | // Program address. 136 | const programAddress = config?.programAddress ?? SYSTEM_PROGRAM_ADDRESS; 137 | 138 | // Original accounts. 139 | const originalAccounts = { 140 | payer: { value: input.payer ?? null, isWritable: true }, 141 | newAccount: { value: input.newAccount ?? null, isWritable: true }, 142 | }; 143 | const accounts = originalAccounts as Record< 144 | keyof typeof originalAccounts, 145 | ResolvedAccount 146 | >; 147 | 148 | // Original args. 149 | const args = { ...input }; 150 | 151 | // Bytes created or reallocated by the instruction. 152 | const byteDelta: number = [Number(args.space) + BASE_ACCOUNT_SIZE].reduce( 153 | (a, b) => a + b, 154 | 0 155 | ); 156 | 157 | const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); 158 | const instruction = { 159 | accounts: [ 160 | getAccountMeta(accounts.payer), 161 | getAccountMeta(accounts.newAccount), 162 | ], 163 | programAddress, 164 | data: getCreateAccountInstructionDataEncoder().encode( 165 | args as CreateAccountInstructionDataArgs 166 | ), 167 | } as CreateAccountInstruction< 168 | TProgramAddress, 169 | TAccountPayer, 170 | TAccountNewAccount 171 | >; 172 | 173 | return Object.freeze({ ...instruction, byteDelta }); 174 | } 175 | 176 | export type ParsedCreateAccountInstruction< 177 | TProgram extends string = typeof SYSTEM_PROGRAM_ADDRESS, 178 | TAccountMetas extends readonly IAccountMeta[] = readonly IAccountMeta[], 179 | > = { 180 | programAddress: Address; 181 | accounts: { 182 | payer: TAccountMetas[0]; 183 | newAccount: TAccountMetas[1]; 184 | }; 185 | data: CreateAccountInstructionData; 186 | }; 187 | 188 | export function parseCreateAccountInstruction< 189 | TProgram extends string, 190 | TAccountMetas extends readonly IAccountMeta[], 191 | >( 192 | instruction: IInstruction & 193 | IInstructionWithAccounts & 194 | IInstructionWithData 195 | ): ParsedCreateAccountInstruction { 196 | if (instruction.accounts.length < 2) { 197 | // TODO: Coded error. 198 | throw new Error('Not enough accounts'); 199 | } 200 | let accountIndex = 0; 201 | const getNextAccount = () => { 202 | const accountMeta = instruction.accounts![accountIndex]!; 203 | accountIndex += 1; 204 | return accountMeta; 205 | }; 206 | return { 207 | programAddress: instruction.programAddress, 208 | accounts: { 209 | payer: getNextAccount(), 210 | newAccount: getNextAccount(), 211 | }, 212 | data: getCreateAccountInstructionDataDecoder().decode(instruction.data), 213 | }; 214 | } 215 | -------------------------------------------------------------------------------- /clients/js/src/generated/instructions/createAccountWithSeed.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was AUTOGENERATED using the codama library. 3 | * Please DO NOT EDIT THIS FILE, instead use visitors 4 | * to add features, then rerun codama to update it. 5 | * 6 | * @see https://github.com/codama-idl/codama 7 | */ 8 | 9 | import { 10 | addDecoderSizePrefix, 11 | addEncoderSizePrefix, 12 | combineCodec, 13 | getAddressDecoder, 14 | getAddressEncoder, 15 | getStructDecoder, 16 | getStructEncoder, 17 | getU32Decoder, 18 | getU32Encoder, 19 | getU64Decoder, 20 | getU64Encoder, 21 | getUtf8Decoder, 22 | getUtf8Encoder, 23 | transformEncoder, 24 | type Address, 25 | type Codec, 26 | type Decoder, 27 | type Encoder, 28 | type IAccountMeta, 29 | type IAccountSignerMeta, 30 | type IInstruction, 31 | type IInstructionWithAccounts, 32 | type IInstructionWithData, 33 | type ReadonlySignerAccount, 34 | type TransactionSigner, 35 | type WritableAccount, 36 | type WritableSignerAccount, 37 | } from '@solana/kit'; 38 | import { SYSTEM_PROGRAM_ADDRESS } from '../programs'; 39 | import { getAccountMetaFactory, type ResolvedAccount } from '../shared'; 40 | 41 | export const CREATE_ACCOUNT_WITH_SEED_DISCRIMINATOR = 3; 42 | 43 | export function getCreateAccountWithSeedDiscriminatorBytes() { 44 | return getU32Encoder().encode(CREATE_ACCOUNT_WITH_SEED_DISCRIMINATOR); 45 | } 46 | 47 | export type CreateAccountWithSeedInstruction< 48 | TProgram extends string = typeof SYSTEM_PROGRAM_ADDRESS, 49 | TAccountPayer extends string | IAccountMeta = string, 50 | TAccountNewAccount extends string | IAccountMeta = string, 51 | TAccountBaseAccount extends string | IAccountMeta = string, 52 | TRemainingAccounts extends readonly IAccountMeta[] = [], 53 | > = IInstruction & 54 | IInstructionWithData & 55 | IInstructionWithAccounts< 56 | [ 57 | TAccountPayer extends string 58 | ? WritableSignerAccount & 59 | IAccountSignerMeta 60 | : TAccountPayer, 61 | TAccountNewAccount extends string 62 | ? WritableAccount 63 | : TAccountNewAccount, 64 | TAccountBaseAccount extends string 65 | ? ReadonlySignerAccount & 66 | IAccountSignerMeta 67 | : TAccountBaseAccount, 68 | ...TRemainingAccounts, 69 | ] 70 | >; 71 | 72 | export type CreateAccountWithSeedInstructionData = { 73 | discriminator: number; 74 | base: Address; 75 | seed: string; 76 | amount: bigint; 77 | space: bigint; 78 | programAddress: Address; 79 | }; 80 | 81 | export type CreateAccountWithSeedInstructionDataArgs = { 82 | base: Address; 83 | seed: string; 84 | amount: number | bigint; 85 | space: number | bigint; 86 | programAddress: Address; 87 | }; 88 | 89 | export function getCreateAccountWithSeedInstructionDataEncoder(): Encoder { 90 | return transformEncoder( 91 | getStructEncoder([ 92 | ['discriminator', getU32Encoder()], 93 | ['base', getAddressEncoder()], 94 | ['seed', addEncoderSizePrefix(getUtf8Encoder(), getU64Encoder())], 95 | ['amount', getU64Encoder()], 96 | ['space', getU64Encoder()], 97 | ['programAddress', getAddressEncoder()], 98 | ]), 99 | (value) => ({ 100 | ...value, 101 | discriminator: CREATE_ACCOUNT_WITH_SEED_DISCRIMINATOR, 102 | }) 103 | ); 104 | } 105 | 106 | export function getCreateAccountWithSeedInstructionDataDecoder(): Decoder { 107 | return getStructDecoder([ 108 | ['discriminator', getU32Decoder()], 109 | ['base', getAddressDecoder()], 110 | ['seed', addDecoderSizePrefix(getUtf8Decoder(), getU64Decoder())], 111 | ['amount', getU64Decoder()], 112 | ['space', getU64Decoder()], 113 | ['programAddress', getAddressDecoder()], 114 | ]); 115 | } 116 | 117 | export function getCreateAccountWithSeedInstructionDataCodec(): Codec< 118 | CreateAccountWithSeedInstructionDataArgs, 119 | CreateAccountWithSeedInstructionData 120 | > { 121 | return combineCodec( 122 | getCreateAccountWithSeedInstructionDataEncoder(), 123 | getCreateAccountWithSeedInstructionDataDecoder() 124 | ); 125 | } 126 | 127 | export type CreateAccountWithSeedInput< 128 | TAccountPayer extends string = string, 129 | TAccountNewAccount extends string = string, 130 | TAccountBaseAccount extends string = string, 131 | > = { 132 | payer: TransactionSigner; 133 | newAccount: Address; 134 | baseAccount: TransactionSigner; 135 | base: CreateAccountWithSeedInstructionDataArgs['base']; 136 | seed: CreateAccountWithSeedInstructionDataArgs['seed']; 137 | amount: CreateAccountWithSeedInstructionDataArgs['amount']; 138 | space: CreateAccountWithSeedInstructionDataArgs['space']; 139 | programAddress: CreateAccountWithSeedInstructionDataArgs['programAddress']; 140 | }; 141 | 142 | export function getCreateAccountWithSeedInstruction< 143 | TAccountPayer extends string, 144 | TAccountNewAccount extends string, 145 | TAccountBaseAccount extends string, 146 | TProgramAddress extends Address = typeof SYSTEM_PROGRAM_ADDRESS, 147 | >( 148 | input: CreateAccountWithSeedInput< 149 | TAccountPayer, 150 | TAccountNewAccount, 151 | TAccountBaseAccount 152 | >, 153 | config?: { programAddress?: TProgramAddress } 154 | ): CreateAccountWithSeedInstruction< 155 | TProgramAddress, 156 | TAccountPayer, 157 | TAccountNewAccount, 158 | TAccountBaseAccount 159 | > { 160 | // Program address. 161 | const programAddress = config?.programAddress ?? SYSTEM_PROGRAM_ADDRESS; 162 | 163 | // Original accounts. 164 | const originalAccounts = { 165 | payer: { value: input.payer ?? null, isWritable: true }, 166 | newAccount: { value: input.newAccount ?? null, isWritable: true }, 167 | baseAccount: { value: input.baseAccount ?? null, isWritable: false }, 168 | }; 169 | const accounts = originalAccounts as Record< 170 | keyof typeof originalAccounts, 171 | ResolvedAccount 172 | >; 173 | 174 | // Original args. 175 | const args = { ...input }; 176 | 177 | const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); 178 | const instruction = { 179 | accounts: [ 180 | getAccountMeta(accounts.payer), 181 | getAccountMeta(accounts.newAccount), 182 | getAccountMeta(accounts.baseAccount), 183 | ], 184 | programAddress, 185 | data: getCreateAccountWithSeedInstructionDataEncoder().encode( 186 | args as CreateAccountWithSeedInstructionDataArgs 187 | ), 188 | } as CreateAccountWithSeedInstruction< 189 | TProgramAddress, 190 | TAccountPayer, 191 | TAccountNewAccount, 192 | TAccountBaseAccount 193 | >; 194 | 195 | return instruction; 196 | } 197 | 198 | export type ParsedCreateAccountWithSeedInstruction< 199 | TProgram extends string = typeof SYSTEM_PROGRAM_ADDRESS, 200 | TAccountMetas extends readonly IAccountMeta[] = readonly IAccountMeta[], 201 | > = { 202 | programAddress: Address; 203 | accounts: { 204 | payer: TAccountMetas[0]; 205 | newAccount: TAccountMetas[1]; 206 | baseAccount: TAccountMetas[2]; 207 | }; 208 | data: CreateAccountWithSeedInstructionData; 209 | }; 210 | 211 | export function parseCreateAccountWithSeedInstruction< 212 | TProgram extends string, 213 | TAccountMetas extends readonly IAccountMeta[], 214 | >( 215 | instruction: IInstruction & 216 | IInstructionWithAccounts & 217 | IInstructionWithData 218 | ): ParsedCreateAccountWithSeedInstruction { 219 | if (instruction.accounts.length < 3) { 220 | // TODO: Coded error. 221 | throw new Error('Not enough accounts'); 222 | } 223 | let accountIndex = 0; 224 | const getNextAccount = () => { 225 | const accountMeta = instruction.accounts![accountIndex]!; 226 | accountIndex += 1; 227 | return accountMeta; 228 | }; 229 | return { 230 | programAddress: instruction.programAddress, 231 | accounts: { 232 | payer: getNextAccount(), 233 | newAccount: getNextAccount(), 234 | baseAccount: getNextAccount(), 235 | }, 236 | data: getCreateAccountWithSeedInstructionDataDecoder().decode( 237 | instruction.data 238 | ), 239 | }; 240 | } 241 | -------------------------------------------------------------------------------- /clients/js/src/generated/instructions/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was AUTOGENERATED using the codama library. 3 | * Please DO NOT EDIT THIS FILE, instead use visitors 4 | * to add features, then rerun codama to update it. 5 | * 6 | * @see https://github.com/codama-idl/codama 7 | */ 8 | 9 | export * from './advanceNonceAccount'; 10 | export * from './allocate'; 11 | export * from './allocateWithSeed'; 12 | export * from './assign'; 13 | export * from './assignWithSeed'; 14 | export * from './authorizeNonceAccount'; 15 | export * from './createAccount'; 16 | export * from './createAccountWithSeed'; 17 | export * from './initializeNonceAccount'; 18 | export * from './transferSol'; 19 | export * from './transferSolWithSeed'; 20 | export * from './upgradeNonceAccount'; 21 | export * from './withdrawNonceAccount'; 22 | -------------------------------------------------------------------------------- /clients/js/src/generated/instructions/initializeNonceAccount.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was AUTOGENERATED using the codama library. 3 | * Please DO NOT EDIT THIS FILE, instead use visitors 4 | * to add features, then rerun codama to update it. 5 | * 6 | * @see https://github.com/codama-idl/codama 7 | */ 8 | 9 | import { 10 | combineCodec, 11 | getAddressDecoder, 12 | getAddressEncoder, 13 | getStructDecoder, 14 | getStructEncoder, 15 | getU32Decoder, 16 | getU32Encoder, 17 | transformEncoder, 18 | type Address, 19 | type Codec, 20 | type Decoder, 21 | type Encoder, 22 | type IAccountMeta, 23 | type IInstruction, 24 | type IInstructionWithAccounts, 25 | type IInstructionWithData, 26 | type ReadonlyAccount, 27 | type WritableAccount, 28 | } from '@solana/kit'; 29 | import { SYSTEM_PROGRAM_ADDRESS } from '../programs'; 30 | import { getAccountMetaFactory, type ResolvedAccount } from '../shared'; 31 | 32 | export const INITIALIZE_NONCE_ACCOUNT_DISCRIMINATOR = 6; 33 | 34 | export function getInitializeNonceAccountDiscriminatorBytes() { 35 | return getU32Encoder().encode(INITIALIZE_NONCE_ACCOUNT_DISCRIMINATOR); 36 | } 37 | 38 | export type InitializeNonceAccountInstruction< 39 | TProgram extends string = typeof SYSTEM_PROGRAM_ADDRESS, 40 | TAccountNonceAccount extends string | IAccountMeta = string, 41 | TAccountRecentBlockhashesSysvar extends 42 | | string 43 | | IAccountMeta = 'SysvarRecentB1ockHashes11111111111111111111', 44 | TAccountRentSysvar extends 45 | | string 46 | | IAccountMeta = 'SysvarRent111111111111111111111111111111111', 47 | TRemainingAccounts extends readonly IAccountMeta[] = [], 48 | > = IInstruction & 49 | IInstructionWithData & 50 | IInstructionWithAccounts< 51 | [ 52 | TAccountNonceAccount extends string 53 | ? WritableAccount 54 | : TAccountNonceAccount, 55 | TAccountRecentBlockhashesSysvar extends string 56 | ? ReadonlyAccount 57 | : TAccountRecentBlockhashesSysvar, 58 | TAccountRentSysvar extends string 59 | ? ReadonlyAccount 60 | : TAccountRentSysvar, 61 | ...TRemainingAccounts, 62 | ] 63 | >; 64 | 65 | export type InitializeNonceAccountInstructionData = { 66 | discriminator: number; 67 | nonceAuthority: Address; 68 | }; 69 | 70 | export type InitializeNonceAccountInstructionDataArgs = { 71 | nonceAuthority: Address; 72 | }; 73 | 74 | export function getInitializeNonceAccountInstructionDataEncoder(): Encoder { 75 | return transformEncoder( 76 | getStructEncoder([ 77 | ['discriminator', getU32Encoder()], 78 | ['nonceAuthority', getAddressEncoder()], 79 | ]), 80 | (value) => ({ 81 | ...value, 82 | discriminator: INITIALIZE_NONCE_ACCOUNT_DISCRIMINATOR, 83 | }) 84 | ); 85 | } 86 | 87 | export function getInitializeNonceAccountInstructionDataDecoder(): Decoder { 88 | return getStructDecoder([ 89 | ['discriminator', getU32Decoder()], 90 | ['nonceAuthority', getAddressDecoder()], 91 | ]); 92 | } 93 | 94 | export function getInitializeNonceAccountInstructionDataCodec(): Codec< 95 | InitializeNonceAccountInstructionDataArgs, 96 | InitializeNonceAccountInstructionData 97 | > { 98 | return combineCodec( 99 | getInitializeNonceAccountInstructionDataEncoder(), 100 | getInitializeNonceAccountInstructionDataDecoder() 101 | ); 102 | } 103 | 104 | export type InitializeNonceAccountInput< 105 | TAccountNonceAccount extends string = string, 106 | TAccountRecentBlockhashesSysvar extends string = string, 107 | TAccountRentSysvar extends string = string, 108 | > = { 109 | nonceAccount: Address; 110 | recentBlockhashesSysvar?: Address; 111 | rentSysvar?: Address; 112 | nonceAuthority: InitializeNonceAccountInstructionDataArgs['nonceAuthority']; 113 | }; 114 | 115 | export function getInitializeNonceAccountInstruction< 116 | TAccountNonceAccount extends string, 117 | TAccountRecentBlockhashesSysvar extends string, 118 | TAccountRentSysvar extends string, 119 | TProgramAddress extends Address = typeof SYSTEM_PROGRAM_ADDRESS, 120 | >( 121 | input: InitializeNonceAccountInput< 122 | TAccountNonceAccount, 123 | TAccountRecentBlockhashesSysvar, 124 | TAccountRentSysvar 125 | >, 126 | config?: { programAddress?: TProgramAddress } 127 | ): InitializeNonceAccountInstruction< 128 | TProgramAddress, 129 | TAccountNonceAccount, 130 | TAccountRecentBlockhashesSysvar, 131 | TAccountRentSysvar 132 | > { 133 | // Program address. 134 | const programAddress = config?.programAddress ?? SYSTEM_PROGRAM_ADDRESS; 135 | 136 | // Original accounts. 137 | const originalAccounts = { 138 | nonceAccount: { value: input.nonceAccount ?? null, isWritable: true }, 139 | recentBlockhashesSysvar: { 140 | value: input.recentBlockhashesSysvar ?? null, 141 | isWritable: false, 142 | }, 143 | rentSysvar: { value: input.rentSysvar ?? null, isWritable: false }, 144 | }; 145 | const accounts = originalAccounts as Record< 146 | keyof typeof originalAccounts, 147 | ResolvedAccount 148 | >; 149 | 150 | // Original args. 151 | const args = { ...input }; 152 | 153 | // Resolve default values. 154 | if (!accounts.recentBlockhashesSysvar.value) { 155 | accounts.recentBlockhashesSysvar.value = 156 | 'SysvarRecentB1ockHashes11111111111111111111' as Address<'SysvarRecentB1ockHashes11111111111111111111'>; 157 | } 158 | if (!accounts.rentSysvar.value) { 159 | accounts.rentSysvar.value = 160 | 'SysvarRent111111111111111111111111111111111' as Address<'SysvarRent111111111111111111111111111111111'>; 161 | } 162 | 163 | const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); 164 | const instruction = { 165 | accounts: [ 166 | getAccountMeta(accounts.nonceAccount), 167 | getAccountMeta(accounts.recentBlockhashesSysvar), 168 | getAccountMeta(accounts.rentSysvar), 169 | ], 170 | programAddress, 171 | data: getInitializeNonceAccountInstructionDataEncoder().encode( 172 | args as InitializeNonceAccountInstructionDataArgs 173 | ), 174 | } as InitializeNonceAccountInstruction< 175 | TProgramAddress, 176 | TAccountNonceAccount, 177 | TAccountRecentBlockhashesSysvar, 178 | TAccountRentSysvar 179 | >; 180 | 181 | return instruction; 182 | } 183 | 184 | export type ParsedInitializeNonceAccountInstruction< 185 | TProgram extends string = typeof SYSTEM_PROGRAM_ADDRESS, 186 | TAccountMetas extends readonly IAccountMeta[] = readonly IAccountMeta[], 187 | > = { 188 | programAddress: Address; 189 | accounts: { 190 | nonceAccount: TAccountMetas[0]; 191 | recentBlockhashesSysvar: TAccountMetas[1]; 192 | rentSysvar: TAccountMetas[2]; 193 | }; 194 | data: InitializeNonceAccountInstructionData; 195 | }; 196 | 197 | export function parseInitializeNonceAccountInstruction< 198 | TProgram extends string, 199 | TAccountMetas extends readonly IAccountMeta[], 200 | >( 201 | instruction: IInstruction & 202 | IInstructionWithAccounts & 203 | IInstructionWithData 204 | ): ParsedInitializeNonceAccountInstruction { 205 | if (instruction.accounts.length < 3) { 206 | // TODO: Coded error. 207 | throw new Error('Not enough accounts'); 208 | } 209 | let accountIndex = 0; 210 | const getNextAccount = () => { 211 | const accountMeta = instruction.accounts![accountIndex]!; 212 | accountIndex += 1; 213 | return accountMeta; 214 | }; 215 | return { 216 | programAddress: instruction.programAddress, 217 | accounts: { 218 | nonceAccount: getNextAccount(), 219 | recentBlockhashesSysvar: getNextAccount(), 220 | rentSysvar: getNextAccount(), 221 | }, 222 | data: getInitializeNonceAccountInstructionDataDecoder().decode( 223 | instruction.data 224 | ), 225 | }; 226 | } 227 | -------------------------------------------------------------------------------- /clients/js/src/generated/instructions/transferSol.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was AUTOGENERATED using the codama library. 3 | * Please DO NOT EDIT THIS FILE, instead use visitors 4 | * to add features, then rerun codama to update it. 5 | * 6 | * @see https://github.com/codama-idl/codama 7 | */ 8 | 9 | import { 10 | combineCodec, 11 | getStructDecoder, 12 | getStructEncoder, 13 | getU32Decoder, 14 | getU32Encoder, 15 | getU64Decoder, 16 | getU64Encoder, 17 | transformEncoder, 18 | type Address, 19 | type Codec, 20 | type Decoder, 21 | type Encoder, 22 | type IAccountMeta, 23 | type IAccountSignerMeta, 24 | type IInstruction, 25 | type IInstructionWithAccounts, 26 | type IInstructionWithData, 27 | type TransactionSigner, 28 | type WritableAccount, 29 | type WritableSignerAccount, 30 | } from '@solana/kit'; 31 | import { SYSTEM_PROGRAM_ADDRESS } from '../programs'; 32 | import { getAccountMetaFactory, type ResolvedAccount } from '../shared'; 33 | 34 | export const TRANSFER_SOL_DISCRIMINATOR = 2; 35 | 36 | export function getTransferSolDiscriminatorBytes() { 37 | return getU32Encoder().encode(TRANSFER_SOL_DISCRIMINATOR); 38 | } 39 | 40 | export type TransferSolInstruction< 41 | TProgram extends string = typeof SYSTEM_PROGRAM_ADDRESS, 42 | TAccountSource extends string | IAccountMeta = string, 43 | TAccountDestination extends string | IAccountMeta = string, 44 | TRemainingAccounts extends readonly IAccountMeta[] = [], 45 | > = IInstruction & 46 | IInstructionWithData & 47 | IInstructionWithAccounts< 48 | [ 49 | TAccountSource extends string 50 | ? WritableSignerAccount & 51 | IAccountSignerMeta 52 | : TAccountSource, 53 | TAccountDestination extends string 54 | ? WritableAccount 55 | : TAccountDestination, 56 | ...TRemainingAccounts, 57 | ] 58 | >; 59 | 60 | export type TransferSolInstructionData = { 61 | discriminator: number; 62 | amount: bigint; 63 | }; 64 | 65 | export type TransferSolInstructionDataArgs = { amount: number | bigint }; 66 | 67 | export function getTransferSolInstructionDataEncoder(): Encoder { 68 | return transformEncoder( 69 | getStructEncoder([ 70 | ['discriminator', getU32Encoder()], 71 | ['amount', getU64Encoder()], 72 | ]), 73 | (value) => ({ ...value, discriminator: TRANSFER_SOL_DISCRIMINATOR }) 74 | ); 75 | } 76 | 77 | export function getTransferSolInstructionDataDecoder(): Decoder { 78 | return getStructDecoder([ 79 | ['discriminator', getU32Decoder()], 80 | ['amount', getU64Decoder()], 81 | ]); 82 | } 83 | 84 | export function getTransferSolInstructionDataCodec(): Codec< 85 | TransferSolInstructionDataArgs, 86 | TransferSolInstructionData 87 | > { 88 | return combineCodec( 89 | getTransferSolInstructionDataEncoder(), 90 | getTransferSolInstructionDataDecoder() 91 | ); 92 | } 93 | 94 | export type TransferSolInput< 95 | TAccountSource extends string = string, 96 | TAccountDestination extends string = string, 97 | > = { 98 | source: TransactionSigner; 99 | destination: Address; 100 | amount: TransferSolInstructionDataArgs['amount']; 101 | }; 102 | 103 | export function getTransferSolInstruction< 104 | TAccountSource extends string, 105 | TAccountDestination extends string, 106 | TProgramAddress extends Address = typeof SYSTEM_PROGRAM_ADDRESS, 107 | >( 108 | input: TransferSolInput, 109 | config?: { programAddress?: TProgramAddress } 110 | ): TransferSolInstruction< 111 | TProgramAddress, 112 | TAccountSource, 113 | TAccountDestination 114 | > { 115 | // Program address. 116 | const programAddress = config?.programAddress ?? SYSTEM_PROGRAM_ADDRESS; 117 | 118 | // Original accounts. 119 | const originalAccounts = { 120 | source: { value: input.source ?? null, isWritable: true }, 121 | destination: { value: input.destination ?? null, isWritable: true }, 122 | }; 123 | const accounts = originalAccounts as Record< 124 | keyof typeof originalAccounts, 125 | ResolvedAccount 126 | >; 127 | 128 | // Original args. 129 | const args = { ...input }; 130 | 131 | const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); 132 | const instruction = { 133 | accounts: [ 134 | getAccountMeta(accounts.source), 135 | getAccountMeta(accounts.destination), 136 | ], 137 | programAddress, 138 | data: getTransferSolInstructionDataEncoder().encode( 139 | args as TransferSolInstructionDataArgs 140 | ), 141 | } as TransferSolInstruction< 142 | TProgramAddress, 143 | TAccountSource, 144 | TAccountDestination 145 | >; 146 | 147 | return instruction; 148 | } 149 | 150 | export type ParsedTransferSolInstruction< 151 | TProgram extends string = typeof SYSTEM_PROGRAM_ADDRESS, 152 | TAccountMetas extends readonly IAccountMeta[] = readonly IAccountMeta[], 153 | > = { 154 | programAddress: Address; 155 | accounts: { 156 | source: TAccountMetas[0]; 157 | destination: TAccountMetas[1]; 158 | }; 159 | data: TransferSolInstructionData; 160 | }; 161 | 162 | export function parseTransferSolInstruction< 163 | TProgram extends string, 164 | TAccountMetas extends readonly IAccountMeta[], 165 | >( 166 | instruction: IInstruction & 167 | IInstructionWithAccounts & 168 | IInstructionWithData 169 | ): ParsedTransferSolInstruction { 170 | if (instruction.accounts.length < 2) { 171 | // TODO: Coded error. 172 | throw new Error('Not enough accounts'); 173 | } 174 | let accountIndex = 0; 175 | const getNextAccount = () => { 176 | const accountMeta = instruction.accounts![accountIndex]!; 177 | accountIndex += 1; 178 | return accountMeta; 179 | }; 180 | return { 181 | programAddress: instruction.programAddress, 182 | accounts: { 183 | source: getNextAccount(), 184 | destination: getNextAccount(), 185 | }, 186 | data: getTransferSolInstructionDataDecoder().decode(instruction.data), 187 | }; 188 | } 189 | -------------------------------------------------------------------------------- /clients/js/src/generated/instructions/transferSolWithSeed.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was AUTOGENERATED using the codama library. 3 | * Please DO NOT EDIT THIS FILE, instead use visitors 4 | * to add features, then rerun codama to update it. 5 | * 6 | * @see https://github.com/codama-idl/codama 7 | */ 8 | 9 | import { 10 | addDecoderSizePrefix, 11 | addEncoderSizePrefix, 12 | combineCodec, 13 | getAddressDecoder, 14 | getAddressEncoder, 15 | getStructDecoder, 16 | getStructEncoder, 17 | getU32Decoder, 18 | getU32Encoder, 19 | getU64Decoder, 20 | getU64Encoder, 21 | getUtf8Decoder, 22 | getUtf8Encoder, 23 | transformEncoder, 24 | type Address, 25 | type Codec, 26 | type Decoder, 27 | type Encoder, 28 | type IAccountMeta, 29 | type IAccountSignerMeta, 30 | type IInstruction, 31 | type IInstructionWithAccounts, 32 | type IInstructionWithData, 33 | type ReadonlySignerAccount, 34 | type TransactionSigner, 35 | type WritableAccount, 36 | } from '@solana/kit'; 37 | import { SYSTEM_PROGRAM_ADDRESS } from '../programs'; 38 | import { getAccountMetaFactory, type ResolvedAccount } from '../shared'; 39 | 40 | export const TRANSFER_SOL_WITH_SEED_DISCRIMINATOR = 11; 41 | 42 | export function getTransferSolWithSeedDiscriminatorBytes() { 43 | return getU32Encoder().encode(TRANSFER_SOL_WITH_SEED_DISCRIMINATOR); 44 | } 45 | 46 | export type TransferSolWithSeedInstruction< 47 | TProgram extends string = typeof SYSTEM_PROGRAM_ADDRESS, 48 | TAccountSource extends string | IAccountMeta = string, 49 | TAccountBaseAccount extends string | IAccountMeta = string, 50 | TAccountDestination extends string | IAccountMeta = string, 51 | TRemainingAccounts extends readonly IAccountMeta[] = [], 52 | > = IInstruction & 53 | IInstructionWithData & 54 | IInstructionWithAccounts< 55 | [ 56 | TAccountSource extends string 57 | ? WritableAccount 58 | : TAccountSource, 59 | TAccountBaseAccount extends string 60 | ? ReadonlySignerAccount & 61 | IAccountSignerMeta 62 | : TAccountBaseAccount, 63 | TAccountDestination extends string 64 | ? WritableAccount 65 | : TAccountDestination, 66 | ...TRemainingAccounts, 67 | ] 68 | >; 69 | 70 | export type TransferSolWithSeedInstructionData = { 71 | discriminator: number; 72 | amount: bigint; 73 | fromSeed: string; 74 | fromOwner: Address; 75 | }; 76 | 77 | export type TransferSolWithSeedInstructionDataArgs = { 78 | amount: number | bigint; 79 | fromSeed: string; 80 | fromOwner: Address; 81 | }; 82 | 83 | export function getTransferSolWithSeedInstructionDataEncoder(): Encoder { 84 | return transformEncoder( 85 | getStructEncoder([ 86 | ['discriminator', getU32Encoder()], 87 | ['amount', getU64Encoder()], 88 | ['fromSeed', addEncoderSizePrefix(getUtf8Encoder(), getU64Encoder())], 89 | ['fromOwner', getAddressEncoder()], 90 | ]), 91 | (value) => ({ 92 | ...value, 93 | discriminator: TRANSFER_SOL_WITH_SEED_DISCRIMINATOR, 94 | }) 95 | ); 96 | } 97 | 98 | export function getTransferSolWithSeedInstructionDataDecoder(): Decoder { 99 | return getStructDecoder([ 100 | ['discriminator', getU32Decoder()], 101 | ['amount', getU64Decoder()], 102 | ['fromSeed', addDecoderSizePrefix(getUtf8Decoder(), getU64Decoder())], 103 | ['fromOwner', getAddressDecoder()], 104 | ]); 105 | } 106 | 107 | export function getTransferSolWithSeedInstructionDataCodec(): Codec< 108 | TransferSolWithSeedInstructionDataArgs, 109 | TransferSolWithSeedInstructionData 110 | > { 111 | return combineCodec( 112 | getTransferSolWithSeedInstructionDataEncoder(), 113 | getTransferSolWithSeedInstructionDataDecoder() 114 | ); 115 | } 116 | 117 | export type TransferSolWithSeedInput< 118 | TAccountSource extends string = string, 119 | TAccountBaseAccount extends string = string, 120 | TAccountDestination extends string = string, 121 | > = { 122 | source: Address; 123 | baseAccount: TransactionSigner; 124 | destination: Address; 125 | amount: TransferSolWithSeedInstructionDataArgs['amount']; 126 | fromSeed: TransferSolWithSeedInstructionDataArgs['fromSeed']; 127 | fromOwner: TransferSolWithSeedInstructionDataArgs['fromOwner']; 128 | }; 129 | 130 | export function getTransferSolWithSeedInstruction< 131 | TAccountSource extends string, 132 | TAccountBaseAccount extends string, 133 | TAccountDestination extends string, 134 | TProgramAddress extends Address = typeof SYSTEM_PROGRAM_ADDRESS, 135 | >( 136 | input: TransferSolWithSeedInput< 137 | TAccountSource, 138 | TAccountBaseAccount, 139 | TAccountDestination 140 | >, 141 | config?: { programAddress?: TProgramAddress } 142 | ): TransferSolWithSeedInstruction< 143 | TProgramAddress, 144 | TAccountSource, 145 | TAccountBaseAccount, 146 | TAccountDestination 147 | > { 148 | // Program address. 149 | const programAddress = config?.programAddress ?? SYSTEM_PROGRAM_ADDRESS; 150 | 151 | // Original accounts. 152 | const originalAccounts = { 153 | source: { value: input.source ?? null, isWritable: true }, 154 | baseAccount: { value: input.baseAccount ?? null, isWritable: false }, 155 | destination: { value: input.destination ?? null, isWritable: true }, 156 | }; 157 | const accounts = originalAccounts as Record< 158 | keyof typeof originalAccounts, 159 | ResolvedAccount 160 | >; 161 | 162 | // Original args. 163 | const args = { ...input }; 164 | 165 | const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); 166 | const instruction = { 167 | accounts: [ 168 | getAccountMeta(accounts.source), 169 | getAccountMeta(accounts.baseAccount), 170 | getAccountMeta(accounts.destination), 171 | ], 172 | programAddress, 173 | data: getTransferSolWithSeedInstructionDataEncoder().encode( 174 | args as TransferSolWithSeedInstructionDataArgs 175 | ), 176 | } as TransferSolWithSeedInstruction< 177 | TProgramAddress, 178 | TAccountSource, 179 | TAccountBaseAccount, 180 | TAccountDestination 181 | >; 182 | 183 | return instruction; 184 | } 185 | 186 | export type ParsedTransferSolWithSeedInstruction< 187 | TProgram extends string = typeof SYSTEM_PROGRAM_ADDRESS, 188 | TAccountMetas extends readonly IAccountMeta[] = readonly IAccountMeta[], 189 | > = { 190 | programAddress: Address; 191 | accounts: { 192 | source: TAccountMetas[0]; 193 | baseAccount: TAccountMetas[1]; 194 | destination: TAccountMetas[2]; 195 | }; 196 | data: TransferSolWithSeedInstructionData; 197 | }; 198 | 199 | export function parseTransferSolWithSeedInstruction< 200 | TProgram extends string, 201 | TAccountMetas extends readonly IAccountMeta[], 202 | >( 203 | instruction: IInstruction & 204 | IInstructionWithAccounts & 205 | IInstructionWithData 206 | ): ParsedTransferSolWithSeedInstruction { 207 | if (instruction.accounts.length < 3) { 208 | // TODO: Coded error. 209 | throw new Error('Not enough accounts'); 210 | } 211 | let accountIndex = 0; 212 | const getNextAccount = () => { 213 | const accountMeta = instruction.accounts![accountIndex]!; 214 | accountIndex += 1; 215 | return accountMeta; 216 | }; 217 | return { 218 | programAddress: instruction.programAddress, 219 | accounts: { 220 | source: getNextAccount(), 221 | baseAccount: getNextAccount(), 222 | destination: getNextAccount(), 223 | }, 224 | data: getTransferSolWithSeedInstructionDataDecoder().decode( 225 | instruction.data 226 | ), 227 | }; 228 | } 229 | -------------------------------------------------------------------------------- /clients/js/src/generated/instructions/upgradeNonceAccount.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was AUTOGENERATED using the codama library. 3 | * Please DO NOT EDIT THIS FILE, instead use visitors 4 | * to add features, then rerun codama to update it. 5 | * 6 | * @see https://github.com/codama-idl/codama 7 | */ 8 | 9 | import { 10 | combineCodec, 11 | getStructDecoder, 12 | getStructEncoder, 13 | getU32Decoder, 14 | getU32Encoder, 15 | transformEncoder, 16 | type Address, 17 | type Codec, 18 | type Decoder, 19 | type Encoder, 20 | type IAccountMeta, 21 | type IInstruction, 22 | type IInstructionWithAccounts, 23 | type IInstructionWithData, 24 | type WritableAccount, 25 | } from '@solana/kit'; 26 | import { SYSTEM_PROGRAM_ADDRESS } from '../programs'; 27 | import { getAccountMetaFactory, type ResolvedAccount } from '../shared'; 28 | 29 | export const UPGRADE_NONCE_ACCOUNT_DISCRIMINATOR = 12; 30 | 31 | export function getUpgradeNonceAccountDiscriminatorBytes() { 32 | return getU32Encoder().encode(UPGRADE_NONCE_ACCOUNT_DISCRIMINATOR); 33 | } 34 | 35 | export type UpgradeNonceAccountInstruction< 36 | TProgram extends string = typeof SYSTEM_PROGRAM_ADDRESS, 37 | TAccountNonceAccount extends string | IAccountMeta = string, 38 | TRemainingAccounts extends readonly IAccountMeta[] = [], 39 | > = IInstruction & 40 | IInstructionWithData & 41 | IInstructionWithAccounts< 42 | [ 43 | TAccountNonceAccount extends string 44 | ? WritableAccount 45 | : TAccountNonceAccount, 46 | ...TRemainingAccounts, 47 | ] 48 | >; 49 | 50 | export type UpgradeNonceAccountInstructionData = { discriminator: number }; 51 | 52 | export type UpgradeNonceAccountInstructionDataArgs = {}; 53 | 54 | export function getUpgradeNonceAccountInstructionDataEncoder(): Encoder { 55 | return transformEncoder( 56 | getStructEncoder([['discriminator', getU32Encoder()]]), 57 | (value) => ({ 58 | ...value, 59 | discriminator: UPGRADE_NONCE_ACCOUNT_DISCRIMINATOR, 60 | }) 61 | ); 62 | } 63 | 64 | export function getUpgradeNonceAccountInstructionDataDecoder(): Decoder { 65 | return getStructDecoder([['discriminator', getU32Decoder()]]); 66 | } 67 | 68 | export function getUpgradeNonceAccountInstructionDataCodec(): Codec< 69 | UpgradeNonceAccountInstructionDataArgs, 70 | UpgradeNonceAccountInstructionData 71 | > { 72 | return combineCodec( 73 | getUpgradeNonceAccountInstructionDataEncoder(), 74 | getUpgradeNonceAccountInstructionDataDecoder() 75 | ); 76 | } 77 | 78 | export type UpgradeNonceAccountInput< 79 | TAccountNonceAccount extends string = string, 80 | > = { 81 | nonceAccount: Address; 82 | }; 83 | 84 | export function getUpgradeNonceAccountInstruction< 85 | TAccountNonceAccount extends string, 86 | TProgramAddress extends Address = typeof SYSTEM_PROGRAM_ADDRESS, 87 | >( 88 | input: UpgradeNonceAccountInput, 89 | config?: { programAddress?: TProgramAddress } 90 | ): UpgradeNonceAccountInstruction { 91 | // Program address. 92 | const programAddress = config?.programAddress ?? SYSTEM_PROGRAM_ADDRESS; 93 | 94 | // Original accounts. 95 | const originalAccounts = { 96 | nonceAccount: { value: input.nonceAccount ?? null, isWritable: true }, 97 | }; 98 | const accounts = originalAccounts as Record< 99 | keyof typeof originalAccounts, 100 | ResolvedAccount 101 | >; 102 | 103 | const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); 104 | const instruction = { 105 | accounts: [getAccountMeta(accounts.nonceAccount)], 106 | programAddress, 107 | data: getUpgradeNonceAccountInstructionDataEncoder().encode({}), 108 | } as UpgradeNonceAccountInstruction; 109 | 110 | return instruction; 111 | } 112 | 113 | export type ParsedUpgradeNonceAccountInstruction< 114 | TProgram extends string = typeof SYSTEM_PROGRAM_ADDRESS, 115 | TAccountMetas extends readonly IAccountMeta[] = readonly IAccountMeta[], 116 | > = { 117 | programAddress: Address; 118 | accounts: { 119 | nonceAccount: TAccountMetas[0]; 120 | }; 121 | data: UpgradeNonceAccountInstructionData; 122 | }; 123 | 124 | export function parseUpgradeNonceAccountInstruction< 125 | TProgram extends string, 126 | TAccountMetas extends readonly IAccountMeta[], 127 | >( 128 | instruction: IInstruction & 129 | IInstructionWithAccounts & 130 | IInstructionWithData 131 | ): ParsedUpgradeNonceAccountInstruction { 132 | if (instruction.accounts.length < 1) { 133 | // TODO: Coded error. 134 | throw new Error('Not enough accounts'); 135 | } 136 | let accountIndex = 0; 137 | const getNextAccount = () => { 138 | const accountMeta = instruction.accounts![accountIndex]!; 139 | accountIndex += 1; 140 | return accountMeta; 141 | }; 142 | return { 143 | programAddress: instruction.programAddress, 144 | accounts: { 145 | nonceAccount: getNextAccount(), 146 | }, 147 | data: getUpgradeNonceAccountInstructionDataDecoder().decode( 148 | instruction.data 149 | ), 150 | }; 151 | } 152 | -------------------------------------------------------------------------------- /clients/js/src/generated/instructions/withdrawNonceAccount.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was AUTOGENERATED using the codama library. 3 | * Please DO NOT EDIT THIS FILE, instead use visitors 4 | * to add features, then rerun codama to update it. 5 | * 6 | * @see https://github.com/codama-idl/codama 7 | */ 8 | 9 | import { 10 | combineCodec, 11 | getStructDecoder, 12 | getStructEncoder, 13 | getU32Decoder, 14 | getU32Encoder, 15 | getU64Decoder, 16 | getU64Encoder, 17 | transformEncoder, 18 | type Address, 19 | type Codec, 20 | type Decoder, 21 | type Encoder, 22 | type IAccountMeta, 23 | type IAccountSignerMeta, 24 | type IInstruction, 25 | type IInstructionWithAccounts, 26 | type IInstructionWithData, 27 | type ReadonlyAccount, 28 | type ReadonlySignerAccount, 29 | type TransactionSigner, 30 | type WritableAccount, 31 | } from '@solana/kit'; 32 | import { SYSTEM_PROGRAM_ADDRESS } from '../programs'; 33 | import { getAccountMetaFactory, type ResolvedAccount } from '../shared'; 34 | 35 | export const WITHDRAW_NONCE_ACCOUNT_DISCRIMINATOR = 5; 36 | 37 | export function getWithdrawNonceAccountDiscriminatorBytes() { 38 | return getU32Encoder().encode(WITHDRAW_NONCE_ACCOUNT_DISCRIMINATOR); 39 | } 40 | 41 | export type WithdrawNonceAccountInstruction< 42 | TProgram extends string = typeof SYSTEM_PROGRAM_ADDRESS, 43 | TAccountNonceAccount extends string | IAccountMeta = string, 44 | TAccountRecipientAccount extends string | IAccountMeta = string, 45 | TAccountRecentBlockhashesSysvar extends 46 | | string 47 | | IAccountMeta = 'SysvarRecentB1ockHashes11111111111111111111', 48 | TAccountRentSysvar extends 49 | | string 50 | | IAccountMeta = 'SysvarRent111111111111111111111111111111111', 51 | TAccountNonceAuthority extends string | IAccountMeta = string, 52 | TRemainingAccounts extends readonly IAccountMeta[] = [], 53 | > = IInstruction & 54 | IInstructionWithData & 55 | IInstructionWithAccounts< 56 | [ 57 | TAccountNonceAccount extends string 58 | ? WritableAccount 59 | : TAccountNonceAccount, 60 | TAccountRecipientAccount extends string 61 | ? WritableAccount 62 | : TAccountRecipientAccount, 63 | TAccountRecentBlockhashesSysvar extends string 64 | ? ReadonlyAccount 65 | : TAccountRecentBlockhashesSysvar, 66 | TAccountRentSysvar extends string 67 | ? ReadonlyAccount 68 | : TAccountRentSysvar, 69 | TAccountNonceAuthority extends string 70 | ? ReadonlySignerAccount & 71 | IAccountSignerMeta 72 | : TAccountNonceAuthority, 73 | ...TRemainingAccounts, 74 | ] 75 | >; 76 | 77 | export type WithdrawNonceAccountInstructionData = { 78 | discriminator: number; 79 | withdrawAmount: bigint; 80 | }; 81 | 82 | export type WithdrawNonceAccountInstructionDataArgs = { 83 | withdrawAmount: number | bigint; 84 | }; 85 | 86 | export function getWithdrawNonceAccountInstructionDataEncoder(): Encoder { 87 | return transformEncoder( 88 | getStructEncoder([ 89 | ['discriminator', getU32Encoder()], 90 | ['withdrawAmount', getU64Encoder()], 91 | ]), 92 | (value) => ({ 93 | ...value, 94 | discriminator: WITHDRAW_NONCE_ACCOUNT_DISCRIMINATOR, 95 | }) 96 | ); 97 | } 98 | 99 | export function getWithdrawNonceAccountInstructionDataDecoder(): Decoder { 100 | return getStructDecoder([ 101 | ['discriminator', getU32Decoder()], 102 | ['withdrawAmount', getU64Decoder()], 103 | ]); 104 | } 105 | 106 | export function getWithdrawNonceAccountInstructionDataCodec(): Codec< 107 | WithdrawNonceAccountInstructionDataArgs, 108 | WithdrawNonceAccountInstructionData 109 | > { 110 | return combineCodec( 111 | getWithdrawNonceAccountInstructionDataEncoder(), 112 | getWithdrawNonceAccountInstructionDataDecoder() 113 | ); 114 | } 115 | 116 | export type WithdrawNonceAccountInput< 117 | TAccountNonceAccount extends string = string, 118 | TAccountRecipientAccount extends string = string, 119 | TAccountRecentBlockhashesSysvar extends string = string, 120 | TAccountRentSysvar extends string = string, 121 | TAccountNonceAuthority extends string = string, 122 | > = { 123 | nonceAccount: Address; 124 | recipientAccount: Address; 125 | recentBlockhashesSysvar?: Address; 126 | rentSysvar?: Address; 127 | nonceAuthority: TransactionSigner; 128 | withdrawAmount: WithdrawNonceAccountInstructionDataArgs['withdrawAmount']; 129 | }; 130 | 131 | export function getWithdrawNonceAccountInstruction< 132 | TAccountNonceAccount extends string, 133 | TAccountRecipientAccount extends string, 134 | TAccountRecentBlockhashesSysvar extends string, 135 | TAccountRentSysvar extends string, 136 | TAccountNonceAuthority extends string, 137 | TProgramAddress extends Address = typeof SYSTEM_PROGRAM_ADDRESS, 138 | >( 139 | input: WithdrawNonceAccountInput< 140 | TAccountNonceAccount, 141 | TAccountRecipientAccount, 142 | TAccountRecentBlockhashesSysvar, 143 | TAccountRentSysvar, 144 | TAccountNonceAuthority 145 | >, 146 | config?: { programAddress?: TProgramAddress } 147 | ): WithdrawNonceAccountInstruction< 148 | TProgramAddress, 149 | TAccountNonceAccount, 150 | TAccountRecipientAccount, 151 | TAccountRecentBlockhashesSysvar, 152 | TAccountRentSysvar, 153 | TAccountNonceAuthority 154 | > { 155 | // Program address. 156 | const programAddress = config?.programAddress ?? SYSTEM_PROGRAM_ADDRESS; 157 | 158 | // Original accounts. 159 | const originalAccounts = { 160 | nonceAccount: { value: input.nonceAccount ?? null, isWritable: true }, 161 | recipientAccount: { 162 | value: input.recipientAccount ?? null, 163 | isWritable: true, 164 | }, 165 | recentBlockhashesSysvar: { 166 | value: input.recentBlockhashesSysvar ?? null, 167 | isWritable: false, 168 | }, 169 | rentSysvar: { value: input.rentSysvar ?? null, isWritable: false }, 170 | nonceAuthority: { value: input.nonceAuthority ?? null, isWritable: false }, 171 | }; 172 | const accounts = originalAccounts as Record< 173 | keyof typeof originalAccounts, 174 | ResolvedAccount 175 | >; 176 | 177 | // Original args. 178 | const args = { ...input }; 179 | 180 | // Resolve default values. 181 | if (!accounts.recentBlockhashesSysvar.value) { 182 | accounts.recentBlockhashesSysvar.value = 183 | 'SysvarRecentB1ockHashes11111111111111111111' as Address<'SysvarRecentB1ockHashes11111111111111111111'>; 184 | } 185 | if (!accounts.rentSysvar.value) { 186 | accounts.rentSysvar.value = 187 | 'SysvarRent111111111111111111111111111111111' as Address<'SysvarRent111111111111111111111111111111111'>; 188 | } 189 | 190 | const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); 191 | const instruction = { 192 | accounts: [ 193 | getAccountMeta(accounts.nonceAccount), 194 | getAccountMeta(accounts.recipientAccount), 195 | getAccountMeta(accounts.recentBlockhashesSysvar), 196 | getAccountMeta(accounts.rentSysvar), 197 | getAccountMeta(accounts.nonceAuthority), 198 | ], 199 | programAddress, 200 | data: getWithdrawNonceAccountInstructionDataEncoder().encode( 201 | args as WithdrawNonceAccountInstructionDataArgs 202 | ), 203 | } as WithdrawNonceAccountInstruction< 204 | TProgramAddress, 205 | TAccountNonceAccount, 206 | TAccountRecipientAccount, 207 | TAccountRecentBlockhashesSysvar, 208 | TAccountRentSysvar, 209 | TAccountNonceAuthority 210 | >; 211 | 212 | return instruction; 213 | } 214 | 215 | export type ParsedWithdrawNonceAccountInstruction< 216 | TProgram extends string = typeof SYSTEM_PROGRAM_ADDRESS, 217 | TAccountMetas extends readonly IAccountMeta[] = readonly IAccountMeta[], 218 | > = { 219 | programAddress: Address; 220 | accounts: { 221 | nonceAccount: TAccountMetas[0]; 222 | recipientAccount: TAccountMetas[1]; 223 | recentBlockhashesSysvar: TAccountMetas[2]; 224 | rentSysvar: TAccountMetas[3]; 225 | nonceAuthority: TAccountMetas[4]; 226 | }; 227 | data: WithdrawNonceAccountInstructionData; 228 | }; 229 | 230 | export function parseWithdrawNonceAccountInstruction< 231 | TProgram extends string, 232 | TAccountMetas extends readonly IAccountMeta[], 233 | >( 234 | instruction: IInstruction & 235 | IInstructionWithAccounts & 236 | IInstructionWithData 237 | ): ParsedWithdrawNonceAccountInstruction { 238 | if (instruction.accounts.length < 5) { 239 | // TODO: Coded error. 240 | throw new Error('Not enough accounts'); 241 | } 242 | let accountIndex = 0; 243 | const getNextAccount = () => { 244 | const accountMeta = instruction.accounts![accountIndex]!; 245 | accountIndex += 1; 246 | return accountMeta; 247 | }; 248 | return { 249 | programAddress: instruction.programAddress, 250 | accounts: { 251 | nonceAccount: getNextAccount(), 252 | recipientAccount: getNextAccount(), 253 | recentBlockhashesSysvar: getNextAccount(), 254 | rentSysvar: getNextAccount(), 255 | nonceAuthority: getNextAccount(), 256 | }, 257 | data: getWithdrawNonceAccountInstructionDataDecoder().decode( 258 | instruction.data 259 | ), 260 | }; 261 | } 262 | -------------------------------------------------------------------------------- /clients/js/src/generated/programs/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was AUTOGENERATED using the codama library. 3 | * Please DO NOT EDIT THIS FILE, instead use visitors 4 | * to add features, then rerun codama to update it. 5 | * 6 | * @see https://github.com/codama-idl/codama 7 | */ 8 | 9 | export * from './system'; 10 | -------------------------------------------------------------------------------- /clients/js/src/generated/programs/system.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was AUTOGENERATED using the codama library. 3 | * Please DO NOT EDIT THIS FILE, instead use visitors 4 | * to add features, then rerun codama to update it. 5 | * 6 | * @see https://github.com/codama-idl/codama 7 | */ 8 | 9 | import { 10 | containsBytes, 11 | getU32Encoder, 12 | type Address, 13 | type ReadonlyUint8Array, 14 | } from '@solana/kit'; 15 | import { 16 | type ParsedAdvanceNonceAccountInstruction, 17 | type ParsedAllocateInstruction, 18 | type ParsedAllocateWithSeedInstruction, 19 | type ParsedAssignInstruction, 20 | type ParsedAssignWithSeedInstruction, 21 | type ParsedAuthorizeNonceAccountInstruction, 22 | type ParsedCreateAccountInstruction, 23 | type ParsedCreateAccountWithSeedInstruction, 24 | type ParsedInitializeNonceAccountInstruction, 25 | type ParsedTransferSolInstruction, 26 | type ParsedTransferSolWithSeedInstruction, 27 | type ParsedUpgradeNonceAccountInstruction, 28 | type ParsedWithdrawNonceAccountInstruction, 29 | } from '../instructions'; 30 | 31 | export const SYSTEM_PROGRAM_ADDRESS = 32 | '11111111111111111111111111111111' as Address<'11111111111111111111111111111111'>; 33 | 34 | export enum SystemAccount { 35 | Nonce, 36 | } 37 | 38 | export enum SystemInstruction { 39 | CreateAccount, 40 | Assign, 41 | TransferSol, 42 | CreateAccountWithSeed, 43 | AdvanceNonceAccount, 44 | WithdrawNonceAccount, 45 | InitializeNonceAccount, 46 | AuthorizeNonceAccount, 47 | Allocate, 48 | AllocateWithSeed, 49 | AssignWithSeed, 50 | TransferSolWithSeed, 51 | UpgradeNonceAccount, 52 | } 53 | 54 | export function identifySystemInstruction( 55 | instruction: { data: ReadonlyUint8Array } | ReadonlyUint8Array 56 | ): SystemInstruction { 57 | const data = 'data' in instruction ? instruction.data : instruction; 58 | if (containsBytes(data, getU32Encoder().encode(0), 0)) { 59 | return SystemInstruction.CreateAccount; 60 | } 61 | if (containsBytes(data, getU32Encoder().encode(1), 0)) { 62 | return SystemInstruction.Assign; 63 | } 64 | if (containsBytes(data, getU32Encoder().encode(2), 0)) { 65 | return SystemInstruction.TransferSol; 66 | } 67 | if (containsBytes(data, getU32Encoder().encode(3), 0)) { 68 | return SystemInstruction.CreateAccountWithSeed; 69 | } 70 | if (containsBytes(data, getU32Encoder().encode(4), 0)) { 71 | return SystemInstruction.AdvanceNonceAccount; 72 | } 73 | if (containsBytes(data, getU32Encoder().encode(5), 0)) { 74 | return SystemInstruction.WithdrawNonceAccount; 75 | } 76 | if (containsBytes(data, getU32Encoder().encode(6), 0)) { 77 | return SystemInstruction.InitializeNonceAccount; 78 | } 79 | if (containsBytes(data, getU32Encoder().encode(7), 0)) { 80 | return SystemInstruction.AuthorizeNonceAccount; 81 | } 82 | if (containsBytes(data, getU32Encoder().encode(8), 0)) { 83 | return SystemInstruction.Allocate; 84 | } 85 | if (containsBytes(data, getU32Encoder().encode(9), 0)) { 86 | return SystemInstruction.AllocateWithSeed; 87 | } 88 | if (containsBytes(data, getU32Encoder().encode(10), 0)) { 89 | return SystemInstruction.AssignWithSeed; 90 | } 91 | if (containsBytes(data, getU32Encoder().encode(11), 0)) { 92 | return SystemInstruction.TransferSolWithSeed; 93 | } 94 | if (containsBytes(data, getU32Encoder().encode(12), 0)) { 95 | return SystemInstruction.UpgradeNonceAccount; 96 | } 97 | throw new Error( 98 | 'The provided instruction could not be identified as a system instruction.' 99 | ); 100 | } 101 | 102 | export type ParsedSystemInstruction< 103 | TProgram extends string = '11111111111111111111111111111111', 104 | > = 105 | | ({ 106 | instructionType: SystemInstruction.CreateAccount; 107 | } & ParsedCreateAccountInstruction) 108 | | ({ 109 | instructionType: SystemInstruction.Assign; 110 | } & ParsedAssignInstruction) 111 | | ({ 112 | instructionType: SystemInstruction.TransferSol; 113 | } & ParsedTransferSolInstruction) 114 | | ({ 115 | instructionType: SystemInstruction.CreateAccountWithSeed; 116 | } & ParsedCreateAccountWithSeedInstruction) 117 | | ({ 118 | instructionType: SystemInstruction.AdvanceNonceAccount; 119 | } & ParsedAdvanceNonceAccountInstruction) 120 | | ({ 121 | instructionType: SystemInstruction.WithdrawNonceAccount; 122 | } & ParsedWithdrawNonceAccountInstruction) 123 | | ({ 124 | instructionType: SystemInstruction.InitializeNonceAccount; 125 | } & ParsedInitializeNonceAccountInstruction) 126 | | ({ 127 | instructionType: SystemInstruction.AuthorizeNonceAccount; 128 | } & ParsedAuthorizeNonceAccountInstruction) 129 | | ({ 130 | instructionType: SystemInstruction.Allocate; 131 | } & ParsedAllocateInstruction) 132 | | ({ 133 | instructionType: SystemInstruction.AllocateWithSeed; 134 | } & ParsedAllocateWithSeedInstruction) 135 | | ({ 136 | instructionType: SystemInstruction.AssignWithSeed; 137 | } & ParsedAssignWithSeedInstruction) 138 | | ({ 139 | instructionType: SystemInstruction.TransferSolWithSeed; 140 | } & ParsedTransferSolWithSeedInstruction) 141 | | ({ 142 | instructionType: SystemInstruction.UpgradeNonceAccount; 143 | } & ParsedUpgradeNonceAccountInstruction); 144 | -------------------------------------------------------------------------------- /clients/js/src/generated/shared/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was AUTOGENERATED using the codama library. 3 | * Please DO NOT EDIT THIS FILE, instead use visitors 4 | * to add features, then rerun codama to update it. 5 | * 6 | * @see https://github.com/codama-idl/codama 7 | */ 8 | 9 | import { 10 | AccountRole, 11 | isProgramDerivedAddress, 12 | isTransactionSigner as kitIsTransactionSigner, 13 | type Address, 14 | type IAccountMeta, 15 | type IAccountSignerMeta, 16 | type ProgramDerivedAddress, 17 | type TransactionSigner, 18 | upgradeRoleToSigner, 19 | } from '@solana/kit'; 20 | 21 | /** 22 | * Asserts that the given value is not null or undefined. 23 | * @internal 24 | */ 25 | export function expectSome(value: T | null | undefined): T { 26 | if (value == null) { 27 | throw new Error('Expected a value but received null or undefined.'); 28 | } 29 | return value; 30 | } 31 | 32 | /** 33 | * Asserts that the given value is a PublicKey. 34 | * @internal 35 | */ 36 | export function expectAddress( 37 | value: 38 | | Address 39 | | ProgramDerivedAddress 40 | | TransactionSigner 41 | | null 42 | | undefined 43 | ): Address { 44 | if (!value) { 45 | throw new Error('Expected a Address.'); 46 | } 47 | if (typeof value === 'object' && 'address' in value) { 48 | return value.address; 49 | } 50 | if (Array.isArray(value)) { 51 | return value[0]; 52 | } 53 | return value as Address; 54 | } 55 | 56 | /** 57 | * Asserts that the given value is a PDA. 58 | * @internal 59 | */ 60 | export function expectProgramDerivedAddress( 61 | value: 62 | | Address 63 | | ProgramDerivedAddress 64 | | TransactionSigner 65 | | null 66 | | undefined 67 | ): ProgramDerivedAddress { 68 | if (!value || !Array.isArray(value) || !isProgramDerivedAddress(value)) { 69 | throw new Error('Expected a ProgramDerivedAddress.'); 70 | } 71 | return value; 72 | } 73 | 74 | /** 75 | * Asserts that the given value is a TransactionSigner. 76 | * @internal 77 | */ 78 | export function expectTransactionSigner( 79 | value: 80 | | Address 81 | | ProgramDerivedAddress 82 | | TransactionSigner 83 | | null 84 | | undefined 85 | ): TransactionSigner { 86 | if (!value || !isTransactionSigner(value)) { 87 | throw new Error('Expected a TransactionSigner.'); 88 | } 89 | return value; 90 | } 91 | 92 | /** 93 | * Defines an instruction account to resolve. 94 | * @internal 95 | */ 96 | export type ResolvedAccount< 97 | T extends string = string, 98 | U extends 99 | | Address 100 | | ProgramDerivedAddress 101 | | TransactionSigner 102 | | null = 103 | | Address 104 | | ProgramDerivedAddress 105 | | TransactionSigner 106 | | null, 107 | > = { 108 | isWritable: boolean; 109 | value: U; 110 | }; 111 | 112 | /** 113 | * Defines an instruction that stores additional bytes on-chain. 114 | * @internal 115 | */ 116 | export type IInstructionWithByteDelta = { 117 | byteDelta: number; 118 | }; 119 | 120 | /** 121 | * Get account metas and signers from resolved accounts. 122 | * @internal 123 | */ 124 | export function getAccountMetaFactory( 125 | programAddress: Address, 126 | optionalAccountStrategy: 'omitted' | 'programId' 127 | ) { 128 | return ( 129 | account: ResolvedAccount 130 | ): IAccountMeta | IAccountSignerMeta | undefined => { 131 | if (!account.value) { 132 | if (optionalAccountStrategy === 'omitted') return; 133 | return Object.freeze({ 134 | address: programAddress, 135 | role: AccountRole.READONLY, 136 | }); 137 | } 138 | 139 | const writableRole = account.isWritable 140 | ? AccountRole.WRITABLE 141 | : AccountRole.READONLY; 142 | return Object.freeze({ 143 | address: expectAddress(account.value), 144 | role: isTransactionSigner(account.value) 145 | ? upgradeRoleToSigner(writableRole) 146 | : writableRole, 147 | ...(isTransactionSigner(account.value) ? { signer: account.value } : {}), 148 | }); 149 | }; 150 | } 151 | 152 | export function isTransactionSigner( 153 | value: 154 | | Address 155 | | ProgramDerivedAddress 156 | | TransactionSigner 157 | ): value is TransactionSigner { 158 | return ( 159 | !!value && 160 | typeof value === 'object' && 161 | 'address' in value && 162 | kitIsTransactionSigner(value) 163 | ); 164 | } 165 | -------------------------------------------------------------------------------- /clients/js/src/generated/types/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was AUTOGENERATED using the codama library. 3 | * Please DO NOT EDIT THIS FILE, instead use visitors 4 | * to add features, then rerun codama to update it. 5 | * 6 | * @see https://github.com/codama-idl/codama 7 | */ 8 | 9 | export * from './nonceState'; 10 | export * from './nonceVersion'; 11 | -------------------------------------------------------------------------------- /clients/js/src/generated/types/nonceState.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was AUTOGENERATED using the codama library. 3 | * Please DO NOT EDIT THIS FILE, instead use visitors 4 | * to add features, then rerun codama to update it. 5 | * 6 | * @see https://github.com/codama-idl/codama 7 | */ 8 | 9 | import { 10 | combineCodec, 11 | getEnumDecoder, 12 | getEnumEncoder, 13 | getU32Decoder, 14 | getU32Encoder, 15 | type Codec, 16 | type Decoder, 17 | type Encoder, 18 | } from '@solana/kit'; 19 | 20 | export enum NonceState { 21 | Uninitialized, 22 | Initialized, 23 | } 24 | 25 | export type NonceStateArgs = NonceState; 26 | 27 | export function getNonceStateEncoder(): Encoder { 28 | return getEnumEncoder(NonceState, { size: getU32Encoder() }); 29 | } 30 | 31 | export function getNonceStateDecoder(): Decoder { 32 | return getEnumDecoder(NonceState, { size: getU32Decoder() }); 33 | } 34 | 35 | export function getNonceStateCodec(): Codec { 36 | return combineCodec(getNonceStateEncoder(), getNonceStateDecoder()); 37 | } 38 | -------------------------------------------------------------------------------- /clients/js/src/generated/types/nonceVersion.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This code was AUTOGENERATED using the codama library. 3 | * Please DO NOT EDIT THIS FILE, instead use visitors 4 | * to add features, then rerun codama to update it. 5 | * 6 | * @see https://github.com/codama-idl/codama 7 | */ 8 | 9 | import { 10 | combineCodec, 11 | getEnumDecoder, 12 | getEnumEncoder, 13 | getU32Decoder, 14 | getU32Encoder, 15 | type Codec, 16 | type Decoder, 17 | type Encoder, 18 | } from '@solana/kit'; 19 | 20 | export enum NonceVersion { 21 | Legacy, 22 | Current, 23 | } 24 | 25 | export type NonceVersionArgs = NonceVersion; 26 | 27 | export function getNonceVersionEncoder(): Encoder { 28 | return getEnumEncoder(NonceVersion, { size: getU32Encoder() }); 29 | } 30 | 31 | export function getNonceVersionDecoder(): Decoder { 32 | return getEnumDecoder(NonceVersion, { size: getU32Decoder() }); 33 | } 34 | 35 | export function getNonceVersionCodec(): Codec { 36 | return combineCodec(getNonceVersionEncoder(), getNonceVersionDecoder()); 37 | } 38 | -------------------------------------------------------------------------------- /clients/js/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './generated'; 2 | -------------------------------------------------------------------------------- /clients/js/test/_setup.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Address, 3 | Commitment, 4 | CompilableTransactionMessage, 5 | Rpc, 6 | RpcSubscriptions, 7 | SolanaRpcApi, 8 | SolanaRpcSubscriptionsApi, 9 | TransactionMessageWithBlockhashLifetime, 10 | TransactionSigner, 11 | airdropFactory, 12 | appendTransactionMessageInstruction, 13 | createSolanaRpc, 14 | createSolanaRpcSubscriptions, 15 | createTransactionMessage, 16 | generateKeyPairSigner, 17 | getSignatureFromTransaction, 18 | lamports, 19 | pipe, 20 | sendAndConfirmTransactionFactory, 21 | setTransactionMessageFeePayerSigner, 22 | setTransactionMessageLifetimeUsingBlockhash, 23 | signTransactionMessageWithSigners, 24 | } from '@solana/kit'; 25 | import { 26 | SYSTEM_PROGRAM_ADDRESS, 27 | getCreateAccountInstruction, 28 | getInitializeNonceAccountInstruction, 29 | getNonceSize, 30 | } from '../src'; 31 | 32 | type Client = { 33 | rpc: Rpc; 34 | rpcSubscriptions: RpcSubscriptions; 35 | }; 36 | 37 | export const createDefaultSolanaClient = (): Client => { 38 | const rpc = createSolanaRpc('http://127.0.0.1:8899'); 39 | const rpcSubscriptions = createSolanaRpcSubscriptions('ws://127.0.0.1:8900'); 40 | return { rpc, rpcSubscriptions }; 41 | }; 42 | 43 | export const generateKeyPairSignerWithSol = async ( 44 | client: Client, 45 | putativeLamports: bigint = 1_000_000_000n 46 | ) => { 47 | const signer = await generateKeyPairSigner(); 48 | await airdropFactory(client)({ 49 | recipientAddress: signer.address, 50 | lamports: lamports(putativeLamports), 51 | commitment: 'confirmed', 52 | }); 53 | return signer; 54 | }; 55 | 56 | export const createDefaultTransaction = async ( 57 | client: Client, 58 | feePayer: TransactionSigner 59 | ) => { 60 | const { value: latestBlockhash } = await client.rpc 61 | .getLatestBlockhash() 62 | .send(); 63 | return pipe( 64 | createTransactionMessage({ version: 0 }), 65 | (tx) => setTransactionMessageFeePayerSigner(feePayer, tx), 66 | (tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx) 67 | ); 68 | }; 69 | 70 | export const signAndSendTransaction = async ( 71 | client: Client, 72 | transactionMessage: CompilableTransactionMessage & 73 | TransactionMessageWithBlockhashLifetime, 74 | commitment: Commitment = 'confirmed' 75 | ) => { 76 | const signedTransaction = 77 | await signTransactionMessageWithSigners(transactionMessage); 78 | const signature = getSignatureFromTransaction(signedTransaction); 79 | await sendAndConfirmTransactionFactory(client)(signedTransaction, { 80 | commitment, 81 | }); 82 | return signature; 83 | }; 84 | 85 | export const getBalance = async (client: Client, address: Address) => 86 | (await client.rpc.getBalance(address, { commitment: 'confirmed' }).send()) 87 | .value; 88 | 89 | export const createNonceAccount = async ( 90 | client: Client, 91 | payer: TransactionSigner, 92 | nonce: TransactionSigner, 93 | nonceAuthority: TransactionSigner 94 | ) => { 95 | const space = BigInt(getNonceSize()); 96 | const rent = await client.rpc.getMinimumBalanceForRentExemption(space).send(); 97 | const createAccount = getCreateAccountInstruction({ 98 | payer, 99 | newAccount: nonce, 100 | lamports: rent, 101 | space, 102 | programAddress: SYSTEM_PROGRAM_ADDRESS, 103 | }); 104 | const initializeNonceAccount = getInitializeNonceAccountInstruction({ 105 | nonceAccount: nonce.address, 106 | nonceAuthority: nonceAuthority.address, 107 | }); 108 | await pipe( 109 | await createDefaultTransaction(client, payer), 110 | (tx) => appendTransactionMessageInstruction(createAccount, tx), 111 | (tx) => appendTransactionMessageInstruction(initializeNonceAccount, tx), 112 | (tx) => signAndSendTransaction(client, tx) 113 | ); 114 | }; 115 | -------------------------------------------------------------------------------- /clients/js/test/advanceNonceAccount.test.ts: -------------------------------------------------------------------------------- 1 | import { 2 | appendTransactionMessageInstruction, 3 | generateKeyPairSigner, 4 | pipe, 5 | } from '@solana/kit'; 6 | import test from 'ava'; 7 | import { fetchNonce, getAdvanceNonceAccountInstruction } from '../src'; 8 | import { 9 | createDefaultSolanaClient, 10 | createDefaultTransaction, 11 | createNonceAccount, 12 | generateKeyPairSignerWithSol, 13 | signAndSendTransaction, 14 | } from './_setup'; 15 | 16 | test('it advances the nonce account', async (t) => { 17 | // Given an existing nonce account. 18 | const client = createDefaultSolanaClient(); 19 | const [payer, nonce, authority] = await Promise.all([ 20 | generateKeyPairSignerWithSol(client), 21 | generateKeyPairSigner(), 22 | generateKeyPairSigner(), 23 | ]); 24 | await createNonceAccount(client, payer, nonce, authority); 25 | const originalNonceAccount = await fetchNonce(client.rpc, nonce.address); 26 | 27 | // When the authority advances the nonce account. 28 | const createAccount = getAdvanceNonceAccountInstruction({ 29 | nonceAccount: nonce.address, 30 | nonceAuthority: authority, 31 | }); 32 | await pipe( 33 | await createDefaultTransaction(client, payer), 34 | (tx) => appendTransactionMessageInstruction(createAccount, tx), 35 | (tx) => signAndSendTransaction(client, tx) 36 | ); 37 | 38 | // Then we expect the blockhash to have been updated. 39 | const updatedNonceAccount = await fetchNonce(client.rpc, nonce.address); 40 | t.not( 41 | originalNonceAccount.data.blockhash, 42 | updatedNonceAccount.data.blockhash 43 | ); 44 | }); 45 | -------------------------------------------------------------------------------- /clients/js/test/createAccount.test.ts: -------------------------------------------------------------------------------- 1 | import { 2 | appendTransactionMessageInstruction, 3 | fetchEncodedAccount, 4 | generateKeyPairSigner, 5 | pipe, 6 | } from '@solana/kit'; 7 | import test from 'ava'; 8 | import { SYSTEM_PROGRAM_ADDRESS, getCreateAccountInstruction } from '../src'; 9 | import { 10 | createDefaultSolanaClient, 11 | createDefaultTransaction, 12 | generateKeyPairSignerWithSol, 13 | signAndSendTransaction, 14 | } from './_setup'; 15 | 16 | test('it creates a new empty account', async (t) => { 17 | // Given we have a newly generated account keypair to create with 42 bytes of space. 18 | const client = createDefaultSolanaClient(); 19 | const space = 42n; 20 | const [payer, newAccount, lamports] = await Promise.all([ 21 | generateKeyPairSignerWithSol(client), 22 | generateKeyPairSigner(), 23 | client.rpc.getMinimumBalanceForRentExemption(space).send(), 24 | ]); 25 | 26 | // When we call createAccount in a transaction. 27 | const createAccount = getCreateAccountInstruction({ 28 | payer, 29 | newAccount, 30 | space, 31 | lamports, 32 | programAddress: SYSTEM_PROGRAM_ADDRESS, 33 | }); 34 | await pipe( 35 | await createDefaultTransaction(client, payer), 36 | (tx) => appendTransactionMessageInstruction(createAccount, tx), 37 | (tx) => signAndSendTransaction(client, tx) 38 | ); 39 | 40 | // Then we expect the following account data. 41 | const fetchedAccount = await fetchEncodedAccount( 42 | client.rpc, 43 | newAccount.address 44 | ); 45 | t.deepEqual(fetchedAccount, { 46 | executable: false, 47 | lamports, 48 | programAddress: SYSTEM_PROGRAM_ADDRESS, 49 | address: newAccount.address, 50 | data: new Uint8Array(Array.from({ length: 42 }, () => 0)), 51 | exists: true, 52 | space: 42n, 53 | }); 54 | }); 55 | -------------------------------------------------------------------------------- /clients/js/test/initializeNonceAccount.test.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Account, 3 | appendTransactionMessageInstruction, 4 | generateKeyPairSigner, 5 | pipe, 6 | } from '@solana/kit'; 7 | import test from 'ava'; 8 | import { 9 | Nonce, 10 | NonceState, 11 | NonceVersion, 12 | SYSTEM_PROGRAM_ADDRESS, 13 | fetchNonce, 14 | getCreateAccountInstruction, 15 | getInitializeNonceAccountInstruction, 16 | getNonceSize, 17 | } from '../src'; 18 | import { 19 | createDefaultSolanaClient, 20 | createDefaultTransaction, 21 | generateKeyPairSignerWithSol, 22 | signAndSendTransaction, 23 | } from './_setup'; 24 | 25 | test('it creates and initialize a durable nonce account', async (t) => { 26 | // Given some brand now payer, authority, and nonce KeyPairSigners. 27 | const client = createDefaultSolanaClient(); 28 | const payer = await generateKeyPairSignerWithSol(client); 29 | const nonce = await generateKeyPairSigner(); 30 | const nonceAuthority = await generateKeyPairSigner(); 31 | 32 | // When we use them to create and initialize a nonce account. 33 | const space = BigInt(getNonceSize()); 34 | const rent = await client.rpc.getMinimumBalanceForRentExemption(space).send(); 35 | const createAccount = getCreateAccountInstruction({ 36 | payer, 37 | newAccount: nonce, 38 | lamports: rent, 39 | space, 40 | programAddress: SYSTEM_PROGRAM_ADDRESS, 41 | }); 42 | const initializeNonceAccount = getInitializeNonceAccountInstruction({ 43 | nonceAccount: nonce.address, 44 | nonceAuthority: nonceAuthority.address, 45 | }); 46 | await pipe( 47 | await createDefaultTransaction(client, payer), 48 | (tx) => appendTransactionMessageInstruction(createAccount, tx), 49 | (tx) => appendTransactionMessageInstruction(initializeNonceAccount, tx), 50 | (tx) => signAndSendTransaction(client, tx) 51 | ); 52 | 53 | // Then we expect the nonce account to exist with the following data. 54 | t.like(await fetchNonce(client.rpc, nonce.address), >{ 55 | address: nonce.address, 56 | data: { 57 | version: NonceVersion.Current, 58 | state: NonceState.Initialized, 59 | authority: nonceAuthority.address, 60 | }, 61 | }); 62 | }); 63 | -------------------------------------------------------------------------------- /clients/js/test/transferSol.test.ts: -------------------------------------------------------------------------------- 1 | import { 2 | AccountRole, 3 | Address, 4 | appendTransactionMessageInstruction, 5 | generateKeyPairSigner, 6 | lamports, 7 | pipe, 8 | } from '@solana/kit'; 9 | import test from 'ava'; 10 | import { getTransferSolInstruction, parseTransferSolInstruction } from '../src'; 11 | import { 12 | createDefaultSolanaClient, 13 | createDefaultTransaction, 14 | generateKeyPairSignerWithSol, 15 | getBalance, 16 | signAndSendTransaction, 17 | } from './_setup'; 18 | 19 | test('it transfers SOL from one account to another', async (t) => { 20 | // Given a source account with 3 SOL and a destination account with no SOL. 21 | const client = createDefaultSolanaClient(); 22 | const source = await generateKeyPairSignerWithSol(client, 3_000_000_000n); 23 | const destination = (await generateKeyPairSigner()).address; 24 | 25 | // When the source account transfers 1 SOL to the destination account. 26 | const transferSol = getTransferSolInstruction({ 27 | source, 28 | destination, 29 | amount: 1_000_000_000, 30 | }); 31 | await pipe( 32 | await createDefaultTransaction(client, source), 33 | (tx) => appendTransactionMessageInstruction(transferSol, tx), 34 | (tx) => signAndSendTransaction(client, tx) 35 | ); 36 | 37 | // Then the source account now has roughly 2 SOL (minus the transaction fee). 38 | const sourceBalance = await getBalance(client, source.address); 39 | t.true(sourceBalance < 2_000_000_000n); 40 | t.true(sourceBalance > 1_999_000_000n); 41 | 42 | // And the destination account has exactly 1 SOL. 43 | t.is(await getBalance(client, destination), lamports(1_000_000_000n)); 44 | }); 45 | 46 | test('it parses the accounts and the data of an existing transfer SOL instruction', async (t) => { 47 | // Given a transfer SOL instruction with the following accounts and data. 48 | const source = await generateKeyPairSigner(); 49 | const destination = (await generateKeyPairSigner()).address; 50 | const transferSol = getTransferSolInstruction({ 51 | source, 52 | destination, 53 | amount: 1_000_000_000, 54 | }); 55 | 56 | // When we parse this instruction. 57 | const parsedTransferSol = parseTransferSolInstruction(transferSol); 58 | 59 | // Then we expect the following accounts and data. 60 | t.is(parsedTransferSol.accounts.source.address, source.address); 61 | t.is(parsedTransferSol.accounts.source.role, AccountRole.WRITABLE_SIGNER); 62 | t.is(parsedTransferSol.accounts.source.signer, source); 63 | t.is(parsedTransferSol.accounts.destination.address, destination); 64 | t.is(parsedTransferSol.accounts.destination.role, AccountRole.WRITABLE); 65 | t.is(parsedTransferSol.data.amount, 1_000_000_000n); 66 | t.is( 67 | parsedTransferSol.programAddress, 68 | '11111111111111111111111111111111' as Address<'11111111111111111111111111111111'> 69 | ); 70 | }); 71 | -------------------------------------------------------------------------------- /clients/js/tsconfig.declarations.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "declaration": true, 4 | "declarationMap": true, 5 | "emitDeclarationOnly": true, 6 | "outDir": "./dist/types", 7 | }, 8 | "extends": "./tsconfig.json", 9 | "include": ["src"] 10 | } 11 | -------------------------------------------------------------------------------- /clients/js/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "compilerOptions": { 4 | "composite": false, 5 | "declaration": true, 6 | "declarationMap": true, 7 | "esModuleInterop": true, 8 | "forceConsistentCasingInFileNames": true, 9 | "inlineSources": false, 10 | "isolatedModules": true, 11 | "module": "ESNext", 12 | "moduleResolution": "node", 13 | "noFallthroughCasesInSwitch": true, 14 | "noUnusedLocals": true, 15 | "noUnusedParameters": true, 16 | "outDir": "./dist", 17 | "preserveWatchOutput": true, 18 | "skipLibCheck": true, 19 | "strict": true, 20 | "target": "ESNext" 21 | }, 22 | "exclude": ["node_modules"], 23 | "include": ["src", "test"] 24 | } 25 | -------------------------------------------------------------------------------- /clients/js/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { env } from 'node:process'; 2 | import { defineConfig, Options } from 'tsup'; 3 | 4 | const SHARED_OPTIONS: Options = { 5 | define: { __VERSION__: `"${env.npm_package_version}"` }, 6 | entry: ['./src/index.ts'], 7 | outDir: './dist/src', 8 | outExtension: ({ format }) => ({ js: format === 'cjs' ? '.js' : '.mjs' }), 9 | sourcemap: true, 10 | treeshake: true, 11 | }; 12 | 13 | export default defineConfig(() => [ 14 | // Source. 15 | { ...SHARED_OPTIONS, format: 'cjs' }, 16 | { ...SHARED_OPTIONS, format: 'esm' }, 17 | 18 | // Tests. 19 | { 20 | ...SHARED_OPTIONS, 21 | bundle: false, 22 | entry: ['./test/**/*.ts'], 23 | format: 'cjs', 24 | outDir: './dist/test', 25 | }, 26 | ]); 27 | -------------------------------------------------------------------------------- /clients/js/typedoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "entryPoints": ["src/index.ts"], 3 | "includeVersion": true, 4 | "readme": "none", 5 | "out": "docs" 6 | } 7 | -------------------------------------------------------------------------------- /clients/rust/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "solana-system-client" 3 | version = "0.0.1" 4 | description = "A generated Rust library for the System program" 5 | repository = "https://github.com/solana-program/system" 6 | edition = "2021" 7 | readme = "README.md" 8 | license-file = "../../LICENSE" 9 | 10 | [features] 11 | fetch = ["dep:solana-client", "dep:solana-sdk"] 12 | test-sbf = [] 13 | serde = ["dep:serde", "dep:serde_with", "kaigan/serde"] 14 | 15 | [dependencies] 16 | borsh = "^0.10" 17 | kaigan = "^0.2" 18 | num-derive = "^0.3" 19 | num-traits = "^0.2" 20 | serde = { version = "^1.0", features = ["derive"], optional = true } 21 | serde_with = { version = "^3.0", optional = true } 22 | solana-client = { version = "2.2.0", optional = true } 23 | solana-sdk = { version = "2.2.1", optional = true } 24 | solana-program = "2.2.1" 25 | thiserror = "^1.0" 26 | -------------------------------------------------------------------------------- /clients/rust/README.md: -------------------------------------------------------------------------------- 1 | # Rust client 2 | 3 | A generated Rust library for the System program. 4 | 5 | ## Getting started 6 | 7 | To build and test your Rust client from the root of the repository, you may use the following command. 8 | 9 | ```sh 10 | pnpm clients:js:test 11 | ``` 12 | 13 | This will start a new local validator, if one is not already running, and run the tests for your Rust client. 14 | -------------------------------------------------------------------------------- /clients/rust/src/generated/accounts/mod.rs: -------------------------------------------------------------------------------- 1 | //! This code was AUTOGENERATED using the codama library. 2 | //! Please DO NOT EDIT THIS FILE, instead use visitors 3 | //! to add features, then rerun codama to update it. 4 | //! 5 | //! 6 | //! 7 | 8 | pub(crate) mod r#nonce; 9 | 10 | pub use self::r#nonce::*; 11 | -------------------------------------------------------------------------------- /clients/rust/src/generated/accounts/nonce.rs: -------------------------------------------------------------------------------- 1 | //! This code was AUTOGENERATED using the codama library. 2 | //! Please DO NOT EDIT THIS FILE, instead use visitors 3 | //! to add features, then rerun codama to update it. 4 | //! 5 | //! 6 | //! 7 | 8 | use crate::generated::types::NonceState; 9 | use crate::generated::types::NonceVersion; 10 | use borsh::BorshDeserialize; 11 | use borsh::BorshSerialize; 12 | use solana_program::pubkey::Pubkey; 13 | 14 | #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] 15 | #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] 16 | pub struct Nonce { 17 | pub version: NonceVersion, 18 | pub state: NonceState, 19 | #[cfg_attr( 20 | feature = "serde", 21 | serde(with = "serde_with::As::") 22 | )] 23 | pub authority: Pubkey, 24 | #[cfg_attr( 25 | feature = "serde", 26 | serde(with = "serde_with::As::") 27 | )] 28 | pub blockhash: Pubkey, 29 | pub lamports_per_signature: u64, 30 | } 31 | 32 | impl Nonce { 33 | pub const LEN: usize = 80; 34 | 35 | #[inline(always)] 36 | pub fn from_bytes(data: &[u8]) -> Result { 37 | let mut data = data; 38 | Self::deserialize(&mut data) 39 | } 40 | } 41 | 42 | impl<'a> TryFrom<&solana_program::account_info::AccountInfo<'a>> for Nonce { 43 | type Error = std::io::Error; 44 | 45 | fn try_from( 46 | account_info: &solana_program::account_info::AccountInfo<'a>, 47 | ) -> Result { 48 | let mut data: &[u8] = &(*account_info.data).borrow(); 49 | Self::deserialize(&mut data) 50 | } 51 | } 52 | 53 | #[cfg(feature = "fetch")] 54 | pub fn fetch_nonce( 55 | rpc: &solana_client::rpc_client::RpcClient, 56 | address: &Pubkey, 57 | ) -> Result, std::io::Error> { 58 | let accounts = fetch_all_nonce(rpc, &[*address])?; 59 | Ok(accounts[0].clone()) 60 | } 61 | 62 | #[cfg(feature = "fetch")] 63 | pub fn fetch_all_nonce( 64 | rpc: &solana_client::rpc_client::RpcClient, 65 | addresses: &[Pubkey], 66 | ) -> Result>, std::io::Error> { 67 | let accounts = rpc 68 | .get_multiple_accounts(&addresses) 69 | .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; 70 | let mut decoded_accounts: Vec> = Vec::new(); 71 | for i in 0..addresses.len() { 72 | let address = addresses[i]; 73 | let account = accounts[i].as_ref().ok_or(std::io::Error::new( 74 | std::io::ErrorKind::Other, 75 | format!("Account not found: {}", address), 76 | ))?; 77 | let data = Nonce::from_bytes(&account.data)?; 78 | decoded_accounts.push(crate::shared::DecodedAccount { 79 | address, 80 | account: account.clone(), 81 | data, 82 | }); 83 | } 84 | Ok(decoded_accounts) 85 | } 86 | 87 | #[cfg(feature = "fetch")] 88 | pub fn fetch_maybe_nonce( 89 | rpc: &solana_client::rpc_client::RpcClient, 90 | address: &Pubkey, 91 | ) -> Result, std::io::Error> { 92 | let accounts = fetch_all_maybe_nonce(rpc, &[*address])?; 93 | Ok(accounts[0].clone()) 94 | } 95 | 96 | #[cfg(feature = "fetch")] 97 | pub fn fetch_all_maybe_nonce( 98 | rpc: &solana_client::rpc_client::RpcClient, 99 | addresses: &[Pubkey], 100 | ) -> Result>, std::io::Error> { 101 | let accounts = rpc 102 | .get_multiple_accounts(&addresses) 103 | .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; 104 | let mut decoded_accounts: Vec> = Vec::new(); 105 | for i in 0..addresses.len() { 106 | let address = addresses[i]; 107 | if let Some(account) = accounts[i].as_ref() { 108 | let data = Nonce::from_bytes(&account.data)?; 109 | decoded_accounts.push(crate::shared::MaybeAccount::Exists( 110 | crate::shared::DecodedAccount { 111 | address, 112 | account: account.clone(), 113 | data, 114 | }, 115 | )); 116 | } else { 117 | decoded_accounts.push(crate::shared::MaybeAccount::NotFound(address)); 118 | } 119 | } 120 | Ok(decoded_accounts) 121 | } 122 | -------------------------------------------------------------------------------- /clients/rust/src/generated/errors/mod.rs: -------------------------------------------------------------------------------- 1 | //! This code was AUTOGENERATED using the codama library. 2 | //! Please DO NOT EDIT THIS FILE, instead use visitors 3 | //! to add features, then rerun codama to update it. 4 | //! 5 | //! 6 | //! 7 | 8 | pub(crate) mod system; 9 | 10 | pub use self::system::SystemError; 11 | -------------------------------------------------------------------------------- /clients/rust/src/generated/errors/system.rs: -------------------------------------------------------------------------------- 1 | //! This code was AUTOGENERATED using the codama library. 2 | //! Please DO NOT EDIT THIS FILE, instead use visitors 3 | //! to add features, then rerun codama to update it. 4 | //! 5 | //! 6 | //! 7 | 8 | use num_derive::FromPrimitive; 9 | use thiserror::Error; 10 | 11 | #[derive(Clone, Debug, Eq, Error, FromPrimitive, PartialEq)] 12 | pub enum SystemError { 13 | /// 0 - an account with the same address already exists 14 | #[error("an account with the same address already exists")] 15 | AccountAlreadyInUse = 0x0, 16 | /// 1 - account does not have enough SOL to perform the operation 17 | #[error("account does not have enough SOL to perform the operation")] 18 | ResultWithNegativeLamports = 0x1, 19 | /// 2 - cannot assign account to this program id 20 | #[error("cannot assign account to this program id")] 21 | InvalidProgramId = 0x2, 22 | /// 3 - cannot allocate account data of this length 23 | #[error("cannot allocate account data of this length")] 24 | InvalidAccountDataLength = 0x3, 25 | /// 4 - length of requested seed is too long 26 | #[error("length of requested seed is too long")] 27 | MaxSeedLengthExceeded = 0x4, 28 | /// 5 - provided address does not match addressed derived from seed 29 | #[error("provided address does not match addressed derived from seed")] 30 | AddressWithSeedMismatch = 0x5, 31 | /// 6 - advancing stored nonce requires a populated RecentBlockhashes sysvar 32 | #[error("advancing stored nonce requires a populated RecentBlockhashes sysvar")] 33 | NonceNoRecentBlockhashes = 0x6, 34 | /// 7 - stored nonce is still in recent_blockhashes 35 | #[error("stored nonce is still in recent_blockhashes")] 36 | NonceBlockhashNotExpired = 0x7, 37 | /// 8 - specified nonce does not match stored nonce 38 | #[error("specified nonce does not match stored nonce")] 39 | NonceUnexpectedBlockhashValue = 0x8, 40 | } 41 | 42 | impl solana_program::program_error::PrintProgramError for SystemError { 43 | fn print(&self) { 44 | solana_program::msg!(&self.to_string()); 45 | } 46 | } 47 | 48 | impl solana_program::decode_error::DecodeError for SystemError { 49 | fn type_of() -> &'static str { 50 | "SystemError" 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /clients/rust/src/generated/instructions/mod.rs: -------------------------------------------------------------------------------- 1 | //! This code was AUTOGENERATED using the codama library. 2 | //! Please DO NOT EDIT THIS FILE, instead use visitors 3 | //! to add features, then rerun codama to update it. 4 | //! 5 | //! 6 | //! 7 | 8 | pub(crate) mod r#advance_nonce_account; 9 | pub(crate) mod r#allocate; 10 | pub(crate) mod r#allocate_with_seed; 11 | pub(crate) mod r#assign; 12 | pub(crate) mod r#assign_with_seed; 13 | pub(crate) mod r#authorize_nonce_account; 14 | pub(crate) mod r#create_account; 15 | pub(crate) mod r#create_account_with_seed; 16 | pub(crate) mod r#initialize_nonce_account; 17 | pub(crate) mod r#transfer_sol; 18 | pub(crate) mod r#transfer_sol_with_seed; 19 | pub(crate) mod r#upgrade_nonce_account; 20 | pub(crate) mod r#withdraw_nonce_account; 21 | 22 | pub use self::r#advance_nonce_account::*; 23 | pub use self::r#allocate::*; 24 | pub use self::r#allocate_with_seed::*; 25 | pub use self::r#assign::*; 26 | pub use self::r#assign_with_seed::*; 27 | pub use self::r#authorize_nonce_account::*; 28 | pub use self::r#create_account::*; 29 | pub use self::r#create_account_with_seed::*; 30 | pub use self::r#initialize_nonce_account::*; 31 | pub use self::r#transfer_sol::*; 32 | pub use self::r#transfer_sol_with_seed::*; 33 | pub use self::r#upgrade_nonce_account::*; 34 | pub use self::r#withdraw_nonce_account::*; 35 | -------------------------------------------------------------------------------- /clients/rust/src/generated/instructions/upgrade_nonce_account.rs: -------------------------------------------------------------------------------- 1 | //! This code was AUTOGENERATED using the codama library. 2 | //! Please DO NOT EDIT THIS FILE, instead use visitors 3 | //! to add features, then rerun codama to update it. 4 | //! 5 | //! 6 | //! 7 | 8 | use borsh::BorshDeserialize; 9 | use borsh::BorshSerialize; 10 | 11 | /// Accounts. 12 | #[derive(Debug)] 13 | pub struct UpgradeNonceAccount { 14 | pub nonce_account: solana_program::pubkey::Pubkey, 15 | } 16 | 17 | impl UpgradeNonceAccount { 18 | pub fn instruction(&self) -> solana_program::instruction::Instruction { 19 | self.instruction_with_remaining_accounts(&[]) 20 | } 21 | #[allow(clippy::vec_init_then_push)] 22 | pub fn instruction_with_remaining_accounts( 23 | &self, 24 | remaining_accounts: &[solana_program::instruction::AccountMeta], 25 | ) -> solana_program::instruction::Instruction { 26 | let mut accounts = Vec::with_capacity(1 + remaining_accounts.len()); 27 | accounts.push(solana_program::instruction::AccountMeta::new( 28 | self.nonce_account, 29 | false, 30 | )); 31 | accounts.extend_from_slice(remaining_accounts); 32 | let data = borsh::to_vec(&UpgradeNonceAccountInstructionData::new()).unwrap(); 33 | 34 | solana_program::instruction::Instruction { 35 | program_id: crate::SYSTEM_ID, 36 | accounts, 37 | data, 38 | } 39 | } 40 | } 41 | 42 | #[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] 43 | #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] 44 | pub struct UpgradeNonceAccountInstructionData { 45 | discriminator: u32, 46 | } 47 | 48 | impl UpgradeNonceAccountInstructionData { 49 | pub fn new() -> Self { 50 | Self { discriminator: 12 } 51 | } 52 | } 53 | 54 | impl Default for UpgradeNonceAccountInstructionData { 55 | fn default() -> Self { 56 | Self::new() 57 | } 58 | } 59 | 60 | /// Instruction builder for `UpgradeNonceAccount`. 61 | /// 62 | /// ### Accounts: 63 | /// 64 | /// 0. `[writable]` nonce_account 65 | #[derive(Clone, Debug, Default)] 66 | pub struct UpgradeNonceAccountBuilder { 67 | nonce_account: Option, 68 | __remaining_accounts: Vec, 69 | } 70 | 71 | impl UpgradeNonceAccountBuilder { 72 | pub fn new() -> Self { 73 | Self::default() 74 | } 75 | #[inline(always)] 76 | pub fn nonce_account(&mut self, nonce_account: solana_program::pubkey::Pubkey) -> &mut Self { 77 | self.nonce_account = Some(nonce_account); 78 | self 79 | } 80 | /// Add an additional account to the instruction. 81 | #[inline(always)] 82 | pub fn add_remaining_account( 83 | &mut self, 84 | account: solana_program::instruction::AccountMeta, 85 | ) -> &mut Self { 86 | self.__remaining_accounts.push(account); 87 | self 88 | } 89 | /// Add additional accounts to the instruction. 90 | #[inline(always)] 91 | pub fn add_remaining_accounts( 92 | &mut self, 93 | accounts: &[solana_program::instruction::AccountMeta], 94 | ) -> &mut Self { 95 | self.__remaining_accounts.extend_from_slice(accounts); 96 | self 97 | } 98 | #[allow(clippy::clone_on_copy)] 99 | pub fn instruction(&self) -> solana_program::instruction::Instruction { 100 | let accounts = UpgradeNonceAccount { 101 | nonce_account: self.nonce_account.expect("nonce_account is not set"), 102 | }; 103 | 104 | accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) 105 | } 106 | } 107 | 108 | /// `upgrade_nonce_account` CPI accounts. 109 | pub struct UpgradeNonceAccountCpiAccounts<'a, 'b> { 110 | pub nonce_account: &'b solana_program::account_info::AccountInfo<'a>, 111 | } 112 | 113 | /// `upgrade_nonce_account` CPI instruction. 114 | pub struct UpgradeNonceAccountCpi<'a, 'b> { 115 | /// The program to invoke. 116 | pub __program: &'b solana_program::account_info::AccountInfo<'a>, 117 | 118 | pub nonce_account: &'b solana_program::account_info::AccountInfo<'a>, 119 | } 120 | 121 | impl<'a, 'b> UpgradeNonceAccountCpi<'a, 'b> { 122 | pub fn new( 123 | program: &'b solana_program::account_info::AccountInfo<'a>, 124 | accounts: UpgradeNonceAccountCpiAccounts<'a, 'b>, 125 | ) -> Self { 126 | Self { 127 | __program: program, 128 | nonce_account: accounts.nonce_account, 129 | } 130 | } 131 | #[inline(always)] 132 | pub fn invoke(&self) -> solana_program::entrypoint::ProgramResult { 133 | self.invoke_signed_with_remaining_accounts(&[], &[]) 134 | } 135 | #[inline(always)] 136 | pub fn invoke_with_remaining_accounts( 137 | &self, 138 | remaining_accounts: &[( 139 | &'b solana_program::account_info::AccountInfo<'a>, 140 | bool, 141 | bool, 142 | )], 143 | ) -> solana_program::entrypoint::ProgramResult { 144 | self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) 145 | } 146 | #[inline(always)] 147 | pub fn invoke_signed( 148 | &self, 149 | signers_seeds: &[&[&[u8]]], 150 | ) -> solana_program::entrypoint::ProgramResult { 151 | self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) 152 | } 153 | #[allow(clippy::clone_on_copy)] 154 | #[allow(clippy::vec_init_then_push)] 155 | pub fn invoke_signed_with_remaining_accounts( 156 | &self, 157 | signers_seeds: &[&[&[u8]]], 158 | remaining_accounts: &[( 159 | &'b solana_program::account_info::AccountInfo<'a>, 160 | bool, 161 | bool, 162 | )], 163 | ) -> solana_program::entrypoint::ProgramResult { 164 | let mut accounts = Vec::with_capacity(1 + remaining_accounts.len()); 165 | accounts.push(solana_program::instruction::AccountMeta::new( 166 | *self.nonce_account.key, 167 | false, 168 | )); 169 | remaining_accounts.iter().for_each(|remaining_account| { 170 | accounts.push(solana_program::instruction::AccountMeta { 171 | pubkey: *remaining_account.0.key, 172 | is_signer: remaining_account.1, 173 | is_writable: remaining_account.2, 174 | }) 175 | }); 176 | let data = borsh::to_vec(&UpgradeNonceAccountInstructionData::new()).unwrap(); 177 | 178 | let instruction = solana_program::instruction::Instruction { 179 | program_id: crate::SYSTEM_ID, 180 | accounts, 181 | data, 182 | }; 183 | let mut account_infos = Vec::with_capacity(2 + remaining_accounts.len()); 184 | account_infos.push(self.__program.clone()); 185 | account_infos.push(self.nonce_account.clone()); 186 | remaining_accounts 187 | .iter() 188 | .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); 189 | 190 | if signers_seeds.is_empty() { 191 | solana_program::program::invoke(&instruction, &account_infos) 192 | } else { 193 | solana_program::program::invoke_signed(&instruction, &account_infos, signers_seeds) 194 | } 195 | } 196 | } 197 | 198 | /// Instruction builder for `UpgradeNonceAccount` via CPI. 199 | /// 200 | /// ### Accounts: 201 | /// 202 | /// 0. `[writable]` nonce_account 203 | #[derive(Clone, Debug)] 204 | pub struct UpgradeNonceAccountCpiBuilder<'a, 'b> { 205 | instruction: Box>, 206 | } 207 | 208 | impl<'a, 'b> UpgradeNonceAccountCpiBuilder<'a, 'b> { 209 | pub fn new(program: &'b solana_program::account_info::AccountInfo<'a>) -> Self { 210 | let instruction = Box::new(UpgradeNonceAccountCpiBuilderInstruction { 211 | __program: program, 212 | nonce_account: None, 213 | __remaining_accounts: Vec::new(), 214 | }); 215 | Self { instruction } 216 | } 217 | #[inline(always)] 218 | pub fn nonce_account( 219 | &mut self, 220 | nonce_account: &'b solana_program::account_info::AccountInfo<'a>, 221 | ) -> &mut Self { 222 | self.instruction.nonce_account = Some(nonce_account); 223 | self 224 | } 225 | /// Add an additional account to the instruction. 226 | #[inline(always)] 227 | pub fn add_remaining_account( 228 | &mut self, 229 | account: &'b solana_program::account_info::AccountInfo<'a>, 230 | is_writable: bool, 231 | is_signer: bool, 232 | ) -> &mut Self { 233 | self.instruction 234 | .__remaining_accounts 235 | .push((account, is_writable, is_signer)); 236 | self 237 | } 238 | /// Add additional accounts to the instruction. 239 | /// 240 | /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, 241 | /// and a `bool` indicating whether the account is a signer or not. 242 | #[inline(always)] 243 | pub fn add_remaining_accounts( 244 | &mut self, 245 | accounts: &[( 246 | &'b solana_program::account_info::AccountInfo<'a>, 247 | bool, 248 | bool, 249 | )], 250 | ) -> &mut Self { 251 | self.instruction 252 | .__remaining_accounts 253 | .extend_from_slice(accounts); 254 | self 255 | } 256 | #[inline(always)] 257 | pub fn invoke(&self) -> solana_program::entrypoint::ProgramResult { 258 | self.invoke_signed(&[]) 259 | } 260 | #[allow(clippy::clone_on_copy)] 261 | #[allow(clippy::vec_init_then_push)] 262 | pub fn invoke_signed( 263 | &self, 264 | signers_seeds: &[&[&[u8]]], 265 | ) -> solana_program::entrypoint::ProgramResult { 266 | let instruction = UpgradeNonceAccountCpi { 267 | __program: self.instruction.__program, 268 | 269 | nonce_account: self 270 | .instruction 271 | .nonce_account 272 | .expect("nonce_account is not set"), 273 | }; 274 | instruction.invoke_signed_with_remaining_accounts( 275 | signers_seeds, 276 | &self.instruction.__remaining_accounts, 277 | ) 278 | } 279 | } 280 | 281 | #[derive(Clone, Debug)] 282 | struct UpgradeNonceAccountCpiBuilderInstruction<'a, 'b> { 283 | __program: &'b solana_program::account_info::AccountInfo<'a>, 284 | nonce_account: Option<&'b solana_program::account_info::AccountInfo<'a>>, 285 | /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. 286 | __remaining_accounts: Vec<( 287 | &'b solana_program::account_info::AccountInfo<'a>, 288 | bool, 289 | bool, 290 | )>, 291 | } 292 | -------------------------------------------------------------------------------- /clients/rust/src/generated/mod.rs: -------------------------------------------------------------------------------- 1 | //! This code was AUTOGENERATED using the codama library. 2 | //! Please DO NOT EDIT THIS FILE, instead use visitors 3 | //! to add features, then rerun codama to update it. 4 | //! 5 | //! 6 | //! 7 | 8 | pub mod accounts; 9 | pub mod errors; 10 | pub mod instructions; 11 | pub mod programs; 12 | pub mod shared; 13 | pub mod types; 14 | 15 | pub(crate) use programs::*; 16 | -------------------------------------------------------------------------------- /clients/rust/src/generated/programs.rs: -------------------------------------------------------------------------------- 1 | //! This code was AUTOGENERATED using the codama library. 2 | //! Please DO NOT EDIT THIS FILE, instead use visitors 3 | //! to add features, then rerun codama to update it. 4 | //! 5 | //! 6 | //! 7 | 8 | use solana_program::{pubkey, pubkey::Pubkey}; 9 | 10 | /// `system` program ID. 11 | pub const SYSTEM_ID: Pubkey = pubkey!("11111111111111111111111111111111"); 12 | -------------------------------------------------------------------------------- /clients/rust/src/generated/shared.rs: -------------------------------------------------------------------------------- 1 | //! This code was AUTOGENERATED using the codama library. 2 | //! Please DO NOT EDIT THIS FILE, instead use visitors 3 | //! to add features, then rerun codama to update it. 4 | //! 5 | //! 6 | //! 7 | 8 | #[cfg(feature = "fetch")] 9 | #[derive(Debug, Clone)] 10 | pub struct DecodedAccount { 11 | pub address: solana_program::pubkey::Pubkey, 12 | pub account: solana_sdk::account::Account, 13 | pub data: T, 14 | } 15 | 16 | #[cfg(feature = "fetch")] 17 | #[derive(Debug, Clone)] 18 | pub enum MaybeAccount { 19 | Exists(DecodedAccount), 20 | NotFound(solana_program::pubkey::Pubkey), 21 | } 22 | -------------------------------------------------------------------------------- /clients/rust/src/generated/types/mod.rs: -------------------------------------------------------------------------------- 1 | //! This code was AUTOGENERATED using the codama library. 2 | //! Please DO NOT EDIT THIS FILE, instead use visitors 3 | //! to add features, then rerun codama to update it. 4 | //! 5 | //! 6 | //! 7 | 8 | pub(crate) mod r#nonce_state; 9 | pub(crate) mod r#nonce_version; 10 | 11 | pub use self::r#nonce_state::*; 12 | pub use self::r#nonce_version::*; 13 | -------------------------------------------------------------------------------- /clients/rust/src/generated/types/nonce_state.rs: -------------------------------------------------------------------------------- 1 | //! This code was AUTOGENERATED using the codama library. 2 | //! Please DO NOT EDIT THIS FILE, instead use visitors 3 | //! to add features, then rerun codama to update it. 4 | //! 5 | //! 6 | //! 7 | 8 | use borsh::BorshDeserialize; 9 | use borsh::BorshSerialize; 10 | use num_derive::FromPrimitive; 11 | 12 | #[derive( 13 | BorshSerialize, 14 | BorshDeserialize, 15 | Clone, 16 | Debug, 17 | Eq, 18 | PartialEq, 19 | Copy, 20 | PartialOrd, 21 | Hash, 22 | FromPrimitive, 23 | )] 24 | #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] 25 | pub enum NonceState { 26 | Uninitialized, 27 | Initialized, 28 | } 29 | -------------------------------------------------------------------------------- /clients/rust/src/generated/types/nonce_version.rs: -------------------------------------------------------------------------------- 1 | //! This code was AUTOGENERATED using the codama library. 2 | //! Please DO NOT EDIT THIS FILE, instead use visitors 3 | //! to add features, then rerun codama to update it. 4 | //! 5 | //! 6 | //! 7 | 8 | use borsh::BorshDeserialize; 9 | use borsh::BorshSerialize; 10 | use num_derive::FromPrimitive; 11 | 12 | #[derive( 13 | BorshSerialize, 14 | BorshDeserialize, 15 | Clone, 16 | Debug, 17 | Eq, 18 | PartialEq, 19 | Copy, 20 | PartialOrd, 21 | Hash, 22 | FromPrimitive, 23 | )] 24 | #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] 25 | pub enum NonceVersion { 26 | Legacy, 27 | Current, 28 | } 29 | -------------------------------------------------------------------------------- /clients/rust/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod generated; 2 | 3 | pub use generated::programs::SYSTEM_ID as ID; 4 | pub use generated::*; 5 | -------------------------------------------------------------------------------- /codama.mjs: -------------------------------------------------------------------------------- 1 | import path from 'node:path'; 2 | 3 | const { default: prettierOptions } = await import( 4 | path.resolve('clients', 'js', '.prettierrc.json'), 5 | { with: { type: 'json' } } 6 | ); 7 | 8 | export default { 9 | idl: 'program/idl.json', 10 | before: [], 11 | scripts: { 12 | js: { 13 | from: '@codama/renderers-js', 14 | args: ['clients/js/src/generated', { prettierOptions }], 15 | }, 16 | rust: { 17 | from: '@codama/renderers-rust', 18 | args: [ 19 | 'clients/rust/src/generated', 20 | { 21 | anchorTraits: false, 22 | crateFolder: 'clients/rust', 23 | formatCode: true, 24 | }, 25 | ], 26 | }, 27 | }, 28 | }; 29 | -------------------------------------------------------------------------------- /interface/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "solana-system-interface" 3 | version = "1.0.0" 4 | description = "Instructions and constructors for the System program" 5 | readme = "README.md" 6 | authors = { workspace = true } 7 | repository = { workspace = true } 8 | homepage = { workspace = true } 9 | license = { workspace = true } 10 | edition = { workspace = true } 11 | 12 | [package.metadata.docs.rs] 13 | targets = ["x86_64-unknown-linux-gnu", "wasm32-unknown-unknown"] 14 | all-features = true 15 | rustdoc-args = ["--cfg=docsrs"] 16 | 17 | [dependencies] 18 | num-traits = "0.2" 19 | serde = { version = "1.0.210", optional = true } 20 | serde_derive = { version = "1.0.210", optional = true } 21 | solana-decode-error = { workspace = true } 22 | solana-frozen-abi = { workspace = true, features = ["frozen-abi"], optional = true } 23 | solana-frozen-abi-macro = { workspace = true, features = ["frozen-abi"], optional = true } 24 | solana-instruction = { workspace = true, features = ["bincode", "std"], optional = true } 25 | solana-logger = { workspace = true, optional = true } 26 | solana-msg = { workspace = true } 27 | solana-program-error = { workspace = true } 28 | solana-pubkey = { workspace = true, default-features = false } 29 | 30 | [target.'cfg(target_arch = "wasm32")'.dependencies] 31 | js-sys = "0.3.72" 32 | wasm-bindgen = "0.2" 33 | 34 | [dev-dependencies] 35 | anyhow = "1.0.89" 36 | borsh = { version = "1.5.1", features = ["derive", "unstable__schema"] } 37 | solana-account-info = { workspace = true } 38 | solana-cpi = { workspace = true } 39 | solana-example-mocks = { workspace = true } 40 | solana-nonce = { workspace = true } 41 | solana-program = { workspace = true, default-features = false } 42 | solana-program-entrypoint = { workspace = true } 43 | solana-program-error = { workspace = true, features = ["borsh"] } 44 | solana-pubkey = { workspace = true, features = ["std"] } 45 | solana-system-interface = { path = ".", features = ["bincode"] } 46 | static_assertions = "1.1.0" 47 | strum = "0.24" 48 | strum_macros = "0.24" 49 | 50 | [features] 51 | bincode = ["dep:solana-instruction", "serde"] 52 | frozen-abi = [ 53 | "dep:solana-frozen-abi", 54 | "dep:solana-frozen-abi-macro", 55 | "dep:solana-logger", 56 | "solana-pubkey/frozen-abi", 57 | "solana-pubkey/std" 58 | ] 59 | serde = ["dep:serde", "dep:serde_derive", "solana-pubkey/serde"] 60 | 61 | [lib] 62 | crate-type = ["cdylib", "rlib"] 63 | -------------------------------------------------------------------------------- /interface/README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | Solana 4 | 5 |

6 | 7 | # Solana System Interface 8 | 9 | This crate contains instructions and constructors for interacting with the [System program](https://docs.solanalabs.com/runtime/programs#system-program). 10 | 11 | The System program can be used to create new accounts, allocate account data, assign accounts to owning programs, transfer lamports from System Program owned accounts and pay transaction fees. 12 | 13 | ## Getting Started 14 | 15 | From your project folder: 16 | 17 | ```bash 18 | cargo add solana-system-interface --features bincode 19 | ``` 20 | 21 | This will add the `solana-system-interface` dependency with the `bincode` feature enabled to your `Cargo.toml` file. The `bincode` feature contains the instruction constructors to create instructions for the System program. 22 | 23 | ## Examples 24 | 25 | Creating an account: 26 | 27 | ```rust 28 | use solana_rpc_client::rpc_client::RpcClient; 29 | use solana_sdk::{ 30 | signature::{Keypair, Signer}, 31 | transaction::Transaction, 32 | }; 33 | use solana_system_interface::instruction; 34 | use anyhow::Result; 35 | 36 | fn create_account( 37 | client: &RpcClient, 38 | payer: &Keypair, 39 | new_account: &Keypair, 40 | owning_program: &Pubkey, 41 | space: u64, 42 | ) -> Result<()> { 43 | let rent = client.get_minimum_balance_for_rent_exemption(space.try_into()?)?; 44 | let instr = instruction::create_account( 45 | &payer.pubkey(), 46 | &new_account.pubkey(), 47 | rent, 48 | space, 49 | owning_program, 50 | ); 51 | 52 | let blockhash = client.get_latest_blockhash()?; 53 | let tx = Transaction::new_signed_with_payer( 54 | &[instr], 55 | Some(&payer.pubkey()), 56 | &[payer, new_account], 57 | blockhash, 58 | ); 59 | 60 | let _sig = client.send_and_confirm_transaction(&tx)?; 61 | 62 | Ok(()) 63 | } 64 | ``` 65 | 66 | Transfer lamports between accounts: 67 | 68 | ```rust 69 | use solana_rpc_client::rpc_client::RpcClient; 70 | use solana_pubkey::Pubkey; 71 | use solana_sdk::{ 72 | signature::{Keypair, Signer}, 73 | transaction::Transaction, 74 | }; 75 | use solana_system_interface::instruction; 76 | use anyhow::Result; 77 | 78 | fn transfer( 79 | client: &RpcClient, 80 | from: &Keypair, 81 | recipient: &Pubkey, 82 | lamports: u64, 83 | ) -> Result<()> { 84 | let instr = instruction::transfer( 85 | &from.pubkey(), 86 | recipient, 87 | lamports, 88 | ); 89 | 90 | let blockhash = client.get_latest_blockhash()?; 91 | let tx = Transaction::new_signed_with_payer( 92 | &[instr], 93 | Some(&from.pubkey()), 94 | &[from], 95 | blockhash, 96 | ); 97 | 98 | let _sig = client.send_and_confirm_transaction(&tx)?; 99 | 100 | Ok(()) 101 | } 102 | ``` 103 | 104 | More examples can be found on the crate [documentation](https://docs.rs/solana-system-interface/latest/solana-system-interface/). 105 | -------------------------------------------------------------------------------- /interface/src/error.rs: -------------------------------------------------------------------------------- 1 | use { 2 | num_traits::{FromPrimitive, ToPrimitive}, 3 | solana_decode_error::DecodeError, 4 | solana_msg::msg, 5 | solana_program_error::{PrintProgramError, ProgramError}, 6 | }; 7 | 8 | // Use strum when testing to ensure our FromPrimitive 9 | // impl is exhaustive 10 | #[cfg_attr(test, derive(strum_macros::FromRepr, strum_macros::EnumIter))] 11 | #[cfg_attr( 12 | feature = "serde", 13 | derive(serde_derive::Deserialize, serde_derive::Serialize) 14 | )] 15 | #[derive(Clone, Debug, PartialEq, Eq)] 16 | pub enum SystemError { 17 | /// An account with the same address already exists. 18 | AccountAlreadyInUse, 19 | /// Account does not have enough SOL to perform the operation. 20 | ResultWithNegativeLamports, 21 | /// Cannot assign account to this program id. 22 | InvalidProgramId, 23 | /// Cannot allocate account data of this length. 24 | InvalidAccountDataLength, 25 | /// Length of requested seed is too long. 26 | MaxSeedLengthExceeded, 27 | /// Provided address does not match addressed derived from seed. 28 | AddressWithSeedMismatch, 29 | /// Advancing stored nonce requires a populated RecentBlockhashes sysvar. 30 | NonceNoRecentBlockhashes, 31 | /// Stored nonce is still in recent_blockhashes. 32 | NonceBlockhashNotExpired, 33 | /// Specified nonce does not match stored nonce. 34 | NonceUnexpectedBlockhashValue, 35 | } 36 | 37 | impl FromPrimitive for SystemError { 38 | #[inline] 39 | fn from_i64(n: i64) -> Option { 40 | if n == Self::AccountAlreadyInUse as i64 { 41 | Some(Self::AccountAlreadyInUse) 42 | } else if n == Self::ResultWithNegativeLamports as i64 { 43 | Some(Self::ResultWithNegativeLamports) 44 | } else if n == Self::InvalidProgramId as i64 { 45 | Some(Self::InvalidProgramId) 46 | } else if n == Self::InvalidAccountDataLength as i64 { 47 | Some(Self::InvalidAccountDataLength) 48 | } else if n == Self::MaxSeedLengthExceeded as i64 { 49 | Some(Self::MaxSeedLengthExceeded) 50 | } else if n == Self::AddressWithSeedMismatch as i64 { 51 | Some(Self::AddressWithSeedMismatch) 52 | } else if n == Self::NonceNoRecentBlockhashes as i64 { 53 | Some(Self::NonceNoRecentBlockhashes) 54 | } else if n == Self::NonceBlockhashNotExpired as i64 { 55 | Some(Self::NonceBlockhashNotExpired) 56 | } else if n == Self::NonceUnexpectedBlockhashValue as i64 { 57 | Some(Self::NonceUnexpectedBlockhashValue) 58 | } else { 59 | None 60 | } 61 | } 62 | #[inline] 63 | fn from_u64(n: u64) -> Option { 64 | Self::from_i64(n as i64) 65 | } 66 | } 67 | 68 | impl ToPrimitive for SystemError { 69 | #[inline] 70 | fn to_i64(&self) -> Option { 71 | Some(match *self { 72 | Self::AccountAlreadyInUse => Self::AccountAlreadyInUse as i64, 73 | Self::ResultWithNegativeLamports => Self::ResultWithNegativeLamports as i64, 74 | Self::InvalidProgramId => Self::InvalidProgramId as i64, 75 | Self::InvalidAccountDataLength => Self::InvalidAccountDataLength as i64, 76 | Self::MaxSeedLengthExceeded => Self::MaxSeedLengthExceeded as i64, 77 | Self::AddressWithSeedMismatch => Self::AddressWithSeedMismatch as i64, 78 | Self::NonceNoRecentBlockhashes => Self::NonceNoRecentBlockhashes as i64, 79 | Self::NonceBlockhashNotExpired => Self::NonceBlockhashNotExpired as i64, 80 | Self::NonceUnexpectedBlockhashValue => Self::NonceUnexpectedBlockhashValue as i64, 81 | }) 82 | } 83 | #[inline] 84 | fn to_u64(&self) -> Option { 85 | self.to_i64().map(|x| x as u64) 86 | } 87 | } 88 | 89 | impl std::error::Error for SystemError {} 90 | 91 | impl core::fmt::Display for SystemError { 92 | fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { 93 | match self { 94 | SystemError::AccountAlreadyInUse => { 95 | f.write_str("an account with the same address already exists") 96 | } 97 | SystemError::ResultWithNegativeLamports => { 98 | f.write_str("account does not have enough SOL to perform the operation") 99 | } 100 | SystemError::InvalidProgramId => { 101 | f.write_str("cannot assign account to this program id") 102 | } 103 | SystemError::InvalidAccountDataLength => { 104 | f.write_str("cannot allocate account data of this length") 105 | } 106 | SystemError::MaxSeedLengthExceeded => { 107 | f.write_str("length of requested seed is too long") 108 | } 109 | SystemError::AddressWithSeedMismatch => { 110 | f.write_str("provided address does not match addressed derived from seed") 111 | } 112 | SystemError::NonceNoRecentBlockhashes => { 113 | f.write_str("advancing stored nonce requires a populated RecentBlockhashes sysvar") 114 | } 115 | SystemError::NonceBlockhashNotExpired => { 116 | f.write_str("stored nonce is still in recent_blockhashes") 117 | } 118 | SystemError::NonceUnexpectedBlockhashValue => { 119 | f.write_str("specified nonce does not match stored nonce") 120 | } 121 | } 122 | } 123 | } 124 | 125 | impl PrintProgramError for SystemError { 126 | fn print(&self) { 127 | msg!(&self.to_string()); 128 | } 129 | } 130 | 131 | impl From for ProgramError { 132 | fn from(e: SystemError) -> Self { 133 | Self::Custom(e as u32) 134 | } 135 | } 136 | 137 | impl DecodeError for SystemError { 138 | fn type_of() -> &'static str { 139 | "SystemError" 140 | } 141 | } 142 | 143 | impl From for SystemError { 144 | fn from(error: u64) -> Self { 145 | match error { 146 | 0 => SystemError::AccountAlreadyInUse, 147 | 1 => SystemError::ResultWithNegativeLamports, 148 | 2 => SystemError::InvalidProgramId, 149 | 3 => SystemError::InvalidAccountDataLength, 150 | 4 => SystemError::MaxSeedLengthExceeded, 151 | 5 => SystemError::AddressWithSeedMismatch, 152 | 6 => SystemError::NonceNoRecentBlockhashes, 153 | 7 => SystemError::NonceBlockhashNotExpired, 154 | 8 => SystemError::NonceUnexpectedBlockhashValue, 155 | _ => panic!("Unsupported SystemError"), 156 | } 157 | } 158 | } 159 | 160 | #[cfg(test)] 161 | mod tests { 162 | use {super::SystemError, num_traits::FromPrimitive, strum::IntoEnumIterator}; 163 | 164 | #[test] 165 | fn test_system_error_from_primitive_exhaustive() { 166 | for variant in SystemError::iter() { 167 | let variant_i64 = variant.clone() as i64; 168 | assert_eq!( 169 | SystemError::from_repr(variant_i64 as usize), 170 | SystemError::from_i64(variant_i64) 171 | ); 172 | assert_eq!(SystemError::from(variant_i64 as u64), variant); 173 | } 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /interface/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! The System program interface. 2 | 3 | #![cfg_attr(feature = "frozen-abi", feature(min_specialization))] 4 | #![cfg_attr(docsrs, feature(doc_auto_cfg))] 5 | 6 | pub mod error; 7 | pub mod instruction; 8 | #[cfg(target_arch = "wasm32")] 9 | mod wasm; 10 | 11 | #[cfg(test)] 12 | static_assertions::const_assert!(MAX_PERMITTED_DATA_LENGTH <= u32::MAX as u64); 13 | /// Maximum permitted size of account data (10 MiB). 14 | /// 15 | // SBF program entrypoint assumes that the max account data length 16 | // will fit inside a u32. If this constant no longer fits in a u32, 17 | // the entrypoint deserialization code in the SDK must be updated. 18 | pub const MAX_PERMITTED_DATA_LENGTH: u64 = 10 * 1024 * 1024; 19 | 20 | #[cfg(test)] 21 | static_assertions::const_assert_eq!(MAX_PERMITTED_DATA_LENGTH, 10_485_760); 22 | /// Maximum permitted size of new allocations per transaction, in bytes. 23 | /// 24 | /// The value was chosen such that at least one max sized account could be created, 25 | /// plus some additional resize allocations. 26 | pub const MAX_PERMITTED_ACCOUNTS_DATA_ALLOCATIONS_PER_TRANSACTION: i64 = 27 | MAX_PERMITTED_DATA_LENGTH as i64 * 2; 28 | 29 | pub mod program { 30 | solana_pubkey::declare_id!("11111111111111111111111111111111"); 31 | } 32 | -------------------------------------------------------------------------------- /interface/src/wasm.rs: -------------------------------------------------------------------------------- 1 | //! `SystemInstruction` Javascript interface 2 | #![cfg(target_arch = "wasm32")] 3 | #![allow(non_snake_case)] 4 | use { 5 | crate::instruction::{ 6 | advance_nonce_account, allocate, allocate_with_seed, assign, assign_with_seed, 7 | authorize_nonce_account, create_account, create_account_with_seed, create_nonce_account, 8 | transfer, transfer_with_seed, withdraw_nonce_account, SystemInstruction, 9 | }, 10 | solana_instruction::Instruction, 11 | solana_pubkey::Pubkey, 12 | wasm_bindgen::prelude::*, 13 | }; 14 | 15 | #[wasm_bindgen] 16 | impl SystemInstruction { 17 | pub fn createAccount( 18 | from_pubkey: &Pubkey, 19 | to_pubkey: &Pubkey, 20 | lamports: u64, 21 | space: u64, 22 | owner: &Pubkey, 23 | ) -> Instruction { 24 | create_account(from_pubkey, to_pubkey, lamports, space, owner) 25 | } 26 | 27 | pub fn createAccountWithSeed( 28 | from_pubkey: &Pubkey, 29 | to_pubkey: &Pubkey, 30 | base: &Pubkey, 31 | seed: &str, 32 | lamports: u64, 33 | space: u64, 34 | owner: &Pubkey, 35 | ) -> Instruction { 36 | create_account_with_seed(from_pubkey, to_pubkey, base, seed, lamports, space, owner) 37 | } 38 | 39 | pub fn assign(pubkey: &Pubkey, owner: &Pubkey) -> Instruction { 40 | assign(pubkey, owner) 41 | } 42 | 43 | pub fn assignWithSeed( 44 | pubkey: &Pubkey, 45 | base: &Pubkey, 46 | seed: &str, 47 | owner: &Pubkey, 48 | ) -> Instruction { 49 | assign_with_seed(pubkey, base, seed, owner) 50 | } 51 | 52 | pub fn transfer(from_pubkey: &Pubkey, to_pubkey: &Pubkey, lamports: u64) -> Instruction { 53 | transfer(from_pubkey, to_pubkey, lamports) 54 | } 55 | 56 | pub fn transferWithSeed( 57 | from_pubkey: &Pubkey, 58 | from_base: &Pubkey, 59 | from_seed: String, 60 | from_owner: &Pubkey, 61 | to_pubkey: &Pubkey, 62 | lamports: u64, 63 | ) -> Instruction { 64 | transfer_with_seed( 65 | from_pubkey, 66 | from_base, 67 | from_seed, 68 | from_owner, 69 | to_pubkey, 70 | lamports, 71 | ) 72 | } 73 | 74 | pub fn allocate(pubkey: &Pubkey, space: u64) -> Instruction { 75 | allocate(pubkey, space) 76 | } 77 | 78 | pub fn allocateWithSeed( 79 | address: &Pubkey, 80 | base: &Pubkey, 81 | seed: &str, 82 | space: u64, 83 | owner: &Pubkey, 84 | ) -> Instruction { 85 | allocate_with_seed(address, base, seed, space, owner) 86 | } 87 | 88 | pub fn createNonceAccount( 89 | from_pubkey: &Pubkey, 90 | nonce_pubkey: &Pubkey, 91 | authority: &Pubkey, 92 | lamports: u64, 93 | ) -> js_sys::Array { 94 | let instructions = create_nonce_account(from_pubkey, nonce_pubkey, authority, lamports); 95 | instructions.into_iter().map(JsValue::from).collect() 96 | } 97 | 98 | pub fn advanceNonceAccount(nonce_pubkey: &Pubkey, authorized_pubkey: &Pubkey) -> Instruction { 99 | advance_nonce_account(nonce_pubkey, authorized_pubkey) 100 | } 101 | 102 | pub fn withdrawNonceAccount( 103 | nonce_pubkey: &Pubkey, 104 | authorized_pubkey: &Pubkey, 105 | to_pubkey: &Pubkey, 106 | lamports: u64, 107 | ) -> Instruction { 108 | withdraw_nonce_account(nonce_pubkey, authorized_pubkey, to_pubkey, lamports) 109 | } 110 | 111 | pub fn authorizeNonceAccount( 112 | nonce_pubkey: &Pubkey, 113 | authorized_pubkey: &Pubkey, 114 | new_authority: &Pubkey, 115 | ) -> Instruction { 116 | authorize_nonce_account(nonce_pubkey, authorized_pubkey, new_authority) 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "generate": "pnpm generate:clients", 5 | "generate:clients": "codama run --all" 6 | }, 7 | "devDependencies": { 8 | "@codama/renderers-js": "^1.2.7", 9 | "@codama/renderers-rust": "^1.0.16", 10 | "codama": "^1.2.8" 11 | }, 12 | "engines": { 13 | "node": ">=v20.0.0" 14 | }, 15 | "packageManager": "pnpm@9.1.0" 16 | } 17 | -------------------------------------------------------------------------------- /rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | channel = "1.84.1" 3 | -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | max_width = 100 2 | reorder_imports = true 3 | reorder_modules = true 4 | 5 | # == Nightly only. == 6 | # imports_indent = "Block" 7 | # imports_layout = "Mixed" 8 | # imports_granularity = "Crate" 9 | # group_imports = "Preserve" 10 | # reorder_impl_items = false 11 | -------------------------------------------------------------------------------- /scripts/publish-js.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail 4 | 5 | library_path="${1:-}" 6 | level="${2:-}" 7 | tag="${3:-latest}" 8 | dry_run="${DRY_RUN:-false}" 9 | 10 | if [[ -z "$library_path" || -z "$level" ]]; then 11 | echo "Usage: $0 [tag]" 12 | echo "Example: $0 clients/js patch beta" 13 | exit 1 14 | fi 15 | 16 | cd "$library_path" 17 | pnpm install 18 | 19 | # Build version args 20 | version_args=(--no-git-tag-version) 21 | if [[ "$level" == pre* ]]; then 22 | version_args+=(--preid "$tag") 23 | fi 24 | 25 | # Bump version and capture new version 26 | new_version=$(pnpm version "$level" "${version_args[@]}" | tail -n1 | sed 's/^v//;s/\r$//') 27 | 28 | # CI output 29 | if [[ -n "${CI:-}" ]]; then 30 | echo "new_version=${new_version}" >> "$GITHUB_OUTPUT" 31 | fi 32 | 33 | # Publish package 34 | pnpm publish --no-git-checks --tag "$tag" 35 | 36 | # Git commit and tag 37 | git commit -am "Publish JS client v${new_version}" 38 | git tag -a "js@v${new_version}" -m "JS client v${new_version}" 39 | -------------------------------------------------------------------------------- /scripts/publish-rust.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -euo pipefail 4 | 5 | library_path="${1:-}" 6 | level="${2:-}" 7 | dry_run="${DRY_RUN:-false}" 8 | 9 | if [[ -z "$library_path" || -z "$level" ]]; then 10 | echo "Usage: $0 " 11 | echo "Example: $0 clients/rust patch" 12 | exit 1 13 | fi 14 | 15 | cd "$library_path" 16 | 17 | # Run cargo-release 18 | if [[ "$dry_run" != "true" ]]; then 19 | cargo release "$level" --no-push --no-tag --no-confirm --execute 20 | else 21 | cargo release "$level" 22 | exit 0 23 | fi 24 | 25 | # Extract crate name and version using cargo metadata 26 | metadata=$(cargo metadata --no-deps --format-version 1) 27 | crate_name=$(echo "$metadata" | jq -r '.packages[0].name') 28 | new_version=$(echo "$metadata" | jq -r '.packages[0].version') 29 | 30 | # CI output 31 | if [[ -n "${CI:-}" ]]; then 32 | echo "new_version=${new_version}" >> "$GITHUB_OUTPUT" 33 | fi 34 | 35 | # Rebuild commit and tag 36 | git reset --soft HEAD~1 37 | git commit -am "Publish ${crate_name} v${new_version}" 38 | git tag -a "${crate_name}@v${new_version}" -m "${crate_name} v${new_version}" 39 | -------------------------------------------------------------------------------- /scripts/restart-test-validator.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | PORT=8899 4 | LOG_FILE="./test-ledger/validator.log" 5 | 6 | PID=$(lsof -t -i:$PORT) 7 | 8 | if [ -n "$PID" ]; then 9 | echo "Detected test validator running on PID $PID. Restarting..." 10 | kill "$PID" 11 | sleep 1 12 | fi 13 | 14 | echo "Starting Solana test validator..." 15 | solana-test-validator > /dev/null 2>&1 & 16 | VALIDATOR_PID=$! 17 | 18 | # Wait for test validator to move past slot 0. 19 | echo -n "Waiting for validator to stabilize" 20 | for i in {1..8}; do 21 | if ! kill -0 "$VALIDATOR_PID" 2>/dev/null; then 22 | echo -e "\nTest validator exited early." 23 | exit 1 24 | fi 25 | 26 | SLOT=$(solana slot -ul 2>/dev/null) 27 | if [[ "$SLOT" =~ ^[0-9]+$ ]] && [ "$SLOT" -gt 0 ]; then 28 | echo -e "\nTest validator is ready. Slot: $SLOT" 29 | exit 0 30 | fi 31 | 32 | echo -n "." 33 | sleep 1 34 | done 35 | 36 | echo -e "\nTimed out waiting for test validator to stabilize." 37 | exit 1 38 | -------------------------------------------------------------------------------- /scripts/stop-test-validator.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if lsof -t -i:8899 > /dev/null; then 4 | echo "Stopping test validator..." 5 | pkill -f solana-test-validator 6 | sleep 1 7 | echo "Test validator terminated." 8 | else 9 | echo "Test validator is not running." 10 | fi 11 | -------------------------------------------------------------------------------- /vars.env: -------------------------------------------------------------------------------- 1 | RUST_TOOLCHAIN_NIGHTLY="nightly-2024-11-22" 2 | SOLANA_CLI_VERSION="2.2.0" 3 | --------------------------------------------------------------------------------